on-demand release 4.0dev+
[moodle.git] / question / type / ddwtos / amd / build / ddwtos.min.js.map
1 {"version":3,"sources":["../src/ddwtos.js"],"names":["define","$","dragDrop","keys","DragDropToTextQuestion","containerId","readOnly","getRoot","addClass","resizeAllDragsAndDrops","cloneDrags","positionDrags","prototype","thisQ","find","each","i","node","resizeAllDragsAndDropsInGroup","getClassnameNumericSuffix","group","dragHomes","maxWidth","maxHeight","drag","Math","max","ceil","offsetWidth","offsetHeight","setElementSize","drop","element","width","height","css","index","draghome","placeHolder","clone","removeClass","getChoice","getGroup","before","root","not","dragNode","currentPlace","removeAttr","inputNode","input","choice","val","place","getPlace","dropPosition","offset","data","top","left","unplacedDrag","getUnplacedChoice","hiddenDrag","getDragClone","length","hasClass","noOfDrags","noOfDropsInGroup","getInfiniteDragClones","cloneDrag","after","questionManager","addEventHandlersToDrag","sendDragToDrop","handleDragStart","e","target","closest","info","prepare","start","setInputValue","hiddenDrop","getDrop","x","y","dragMove","dragEnd","pageX","pageY","dropNode","isPointInDrop","isDragSameAsDrop","placed","placedNode","placedDrag","sendDragHome","oldDrag","getCurrentDragInPlace","focus","attr","animateTo","getDragHome","handleKeyPress","currentDrag","nextDrag","keyCode","space","arrowRight","arrowDown","getNextDrag","arrowLeft","arrowUp","getPreviousDrag","escape","isKeyboardNavigation","preventDefault","numChoices","noOfChoicesInGroup","next","previous","currentPos","targetPos","M","util","js_pending","animate","parseInt","duration","done","trigger","js_complete","position","document","getElementById","is","slice","prefix","classes","classesArr","split","patt1","RegExp","test","match","exec","inHome","eventHandlersInitialised","dragEventHandlersInitialised","questions","init","setupEventHandlers","hasOwnProperty","questionContainer","classList","contains","on","handleDragMoved","unbind","question","getQuestionForEvent","currentTarget","removeData","first","remove"],"mappings":"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","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * JavaScript to make drag-drop into text questions work.\n *\n * Some vocabulary to help understand this code:\n *\n * The question text contains 'drops' - blanks into which the 'drags', the missing\n * words, can be put.\n *\n * The thing that can be moved into the drops are called 'drags'. There may be\n * multiple copies of the 'same' drag which does not really cause problems.\n * Each drag has a 'choice' number which is the value set on the drop's hidden\n * input when this drag is placed in a drop.\n *\n * These may be in separate 'groups', distinguished by colour.\n * Things can only interact with other things in the same group.\n * The groups are numbered from 1.\n *\n * The place where a given drag started from is called its 'home'.\n *\n * @module     qtype_ddwtos/ddwtos\n * @copyright  2018 The Open University\n * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n * @since      3.6\n */\ndefine(['jquery', 'core/dragdrop', 'core/key_codes'], function($, dragDrop, keys) {\n\n    \"use strict\";\n\n    /**\n     * Object to handle one drag-drop into text question.\n     *\n     * @param {String} containerId id of the outer div for this question.\n     * @param {boolean} readOnly whether the question is being displayed read-only.\n     * @constructor\n     */\n    function DragDropToTextQuestion(containerId, readOnly) {\n        this.containerId = containerId;\n        if (readOnly) {\n            this.getRoot().addClass('qtype_ddwtos-readonly');\n        }\n        this.resizeAllDragsAndDrops();\n        this.cloneDrags();\n        this.positionDrags();\n    }\n\n    /**\n     * In each group, resize all the items to be the same size.\n     */\n    DragDropToTextQuestion.prototype.resizeAllDragsAndDrops = function() {\n        var thisQ = this;\n        this.getRoot().find('.answercontainer > div').each(function(i, node) {\n            thisQ.resizeAllDragsAndDropsInGroup(\n                thisQ.getClassnameNumericSuffix($(node), 'draggrouphomes'));\n        });\n    };\n\n    /**\n     * In a given group, set all the drags and drops to be the same size.\n     *\n     * @param {int} group the group number.\n     */\n    DragDropToTextQuestion.prototype.resizeAllDragsAndDropsInGroup = function(group) {\n        var thisQ = this,\n            dragHomes = this.getRoot().find('.draggrouphomes' + group + ' span.draghome'),\n            maxWidth = 0,\n            maxHeight = 0;\n\n        // Find the maximum size of any drag in this groups.\n        dragHomes.each(function(i, drag) {\n            maxWidth = Math.max(maxWidth, Math.ceil(drag.offsetWidth));\n            maxHeight = Math.max(maxHeight, Math.ceil(0 + drag.offsetHeight));\n        });\n\n        // The size we will want to set is a bit bigger than this.\n        maxWidth += 8;\n        maxHeight += 2;\n\n        // Set each drag home to that size.\n        dragHomes.each(function(i, drag) {\n            thisQ.setElementSize(drag, maxWidth, maxHeight);\n        });\n\n        // Set each drop to that size.\n        this.getRoot().find('span.drop.group' + group).each(function(i, drop) {\n            thisQ.setElementSize(drop, maxWidth, maxHeight);\n        });\n    };\n\n    /**\n     * Set a given DOM element to be a particular size.\n     *\n     * @param {HTMLElement} element\n     * @param {int} width\n     * @param {int} height\n     */\n    DragDropToTextQuestion.prototype.setElementSize = function(element, width, height) {\n        $(element).width(width).height(height).css('lineHeight', height + 'px');\n    };\n\n    /**\n     * Invisible 'drag homes' are output by the renderer. These have the same properties\n     * as the drag items but are invisible. We clone these invisible elements to make the\n     * actual drag items.\n     */\n    DragDropToTextQuestion.prototype.cloneDrags = function() {\n        var thisQ = this;\n        thisQ.getRoot().find('span.draghome').each(function(index, draghome) {\n            var drag = $(draghome);\n            var placeHolder = drag.clone();\n            placeHolder.removeClass();\n            placeHolder.addClass('draghome choice' +\n                thisQ.getChoice(drag) + ' group' +\n                thisQ.getGroup(drag) + ' dragplaceholder');\n            drag.before(placeHolder);\n        });\n    };\n\n    /**\n     * Update the position of drags.\n     */\n    DragDropToTextQuestion.prototype.positionDrags = function() {\n        var thisQ = this,\n            root = this.getRoot();\n\n        // First move all items back home.\n        root.find('span.draghome').not('.dragplaceholder').each(function(i, dragNode) {\n            var drag = $(dragNode),\n                currentPlace = thisQ.getClassnameNumericSuffix(drag, 'inplace');\n            drag.addClass('unplaced')\n                .removeClass('placed');\n            drag.removeAttr('tabindex');\n            if (currentPlace !== null) {\n                drag.removeClass('inplace' + currentPlace);\n            }\n        });\n\n        // Then place the once that should be placed.\n        root.find('input.placeinput').each(function(i, inputNode) {\n            var input = $(inputNode),\n                choice = input.val(),\n                place = thisQ.getPlace(input);\n\n            // Record the last known position of the drop.\n            var drop = root.find('.drop.place' + place),\n                dropPosition = drop.offset();\n            drop.data('prev-top', dropPosition.top).data('prev-left', dropPosition.left);\n\n            if (choice === '0') {\n                // No item in this place.\n                return;\n            }\n\n            // Get the unplaced drag.\n            var unplacedDrag = thisQ.getUnplacedChoice(thisQ.getGroup(input), choice);\n            // Get the clone of the drag.\n            var hiddenDrag = thisQ.getDragClone(unplacedDrag);\n            if (hiddenDrag.length) {\n                if (unplacedDrag.hasClass('infinite')) {\n                    var noOfDrags = thisQ.noOfDropsInGroup(thisQ.getGroup(unplacedDrag));\n                    var cloneDrags = thisQ.getInfiniteDragClones(unplacedDrag, false);\n                    if (cloneDrags.length < noOfDrags) {\n                        var cloneDrag = unplacedDrag.clone();\n                        hiddenDrag.after(cloneDrag);\n                        questionManager.addEventHandlersToDrag(cloneDrag);\n                    } else {\n                        hiddenDrag.addClass('active');\n                    }\n                } else {\n                    hiddenDrag.addClass('active');\n                }\n            }\n            // Send the drag to drop.\n            thisQ.sendDragToDrop(thisQ.getUnplacedChoice(thisQ.getGroup(input), choice), drop);\n        });\n    };\n\n    /**\n     * Handles the start of dragging an item.\n     *\n     * @param {Event} e the touch start or mouse down event.\n     */\n    DragDropToTextQuestion.prototype.handleDragStart = function(e) {\n        var thisQ = this,\n            drag = $(e.target).closest('.draghome');\n\n        var info = dragDrop.prepare(e);\n        if (!info.start || drag.hasClass('beingdragged')) {\n            return;\n        }\n\n        drag.addClass('beingdragged');\n        var currentPlace = this.getClassnameNumericSuffix(drag, 'inplace');\n        if (currentPlace !== null) {\n            this.setInputValue(currentPlace, 0);\n            drag.removeClass('inplace' + currentPlace);\n            var hiddenDrop = thisQ.getDrop(drag, currentPlace);\n            if (hiddenDrop.length) {\n                hiddenDrop.addClass('active');\n                drag.offset(hiddenDrop.offset());\n            }\n        } else {\n            var hiddenDrag = thisQ.getDragClone(drag);\n            if (hiddenDrag.length) {\n                if (drag.hasClass('infinite')) {\n                    var noOfDrags = this.noOfDropsInGroup(this.getGroup(drag));\n                    var cloneDrags = this.getInfiniteDragClones(drag, false);\n                    if (cloneDrags.length < noOfDrags) {\n                        var cloneDrag = drag.clone();\n                        cloneDrag.removeClass('beingdragged');\n                        hiddenDrag.after(cloneDrag);\n                        questionManager.addEventHandlersToDrag(cloneDrag);\n                        drag.offset(cloneDrag.offset());\n                    } else {\n                        hiddenDrag.addClass('active');\n                        drag.offset(hiddenDrag.offset());\n                    }\n                } else {\n                    hiddenDrag.addClass('active');\n                    drag.offset(hiddenDrag.offset());\n                }\n            }\n        }\n\n        dragDrop.start(e, drag, function(x, y, drag) {\n            thisQ.dragMove(x, y, drag);\n        }, function(x, y, drag) {\n            thisQ.dragEnd(x, y, drag);\n        });\n    };\n\n    /**\n     * Called whenever the currently dragged items moves.\n     *\n     * @param {Number} pageX the x position.\n     * @param {Number} pageY the y position.\n     * @param {jQuery} drag the item being moved.\n     */\n    DragDropToTextQuestion.prototype.dragMove = function(pageX, pageY, drag) {\n        var thisQ = this;\n        this.getRoot().find('span.drop.group' + this.getGroup(drag)).each(function(i, dropNode) {\n            var drop = $(dropNode);\n            if (thisQ.isPointInDrop(pageX, pageY, drop)) {\n                drop.addClass('valid-drag-over-drop');\n            } else {\n                drop.removeClass('valid-drag-over-drop');\n            }\n        });\n        this.getRoot().find('span.draghome.placed.group' + this.getGroup(drag)).not('.beingdragged').each(function(i, dropNode) {\n            var drop = $(dropNode);\n            if (thisQ.isPointInDrop(pageX, pageY, drop) && !thisQ.isDragSameAsDrop(drag, drop)) {\n                drop.addClass('valid-drag-over-drop');\n            } else {\n                drop.removeClass('valid-drag-over-drop');\n            }\n        });\n    };\n\n    /**\n     * Called when user drops a drag item.\n     *\n     * @param {Number} pageX the x position.\n     * @param {Number} pageY the y position.\n     * @param {jQuery} drag the item being moved.\n     */\n    DragDropToTextQuestion.prototype.dragEnd = function(pageX, pageY, drag) {\n        var thisQ = this,\n            root = this.getRoot(),\n            placed = false;\n        root.find('span.drop.group' + this.getGroup(drag)).each(function(i, dropNode) {\n            var drop = $(dropNode);\n            if (!thisQ.isPointInDrop(pageX, pageY, drop)) {\n                // Not this drop.\n                return true;\n            }\n\n            // Now put this drag into the drop.\n            drop.removeClass('valid-drag-over-drop');\n            thisQ.sendDragToDrop(drag, drop);\n            placed = true;\n            return false; // Stop the each() here.\n        });\n\n        root.find('span.draghome.placed.group' + this.getGroup(drag)).not('.beingdragged').each(function(i, placedNode) {\n            var placedDrag = $(placedNode);\n            if (!thisQ.isPointInDrop(pageX, pageY, placedDrag) || thisQ.isDragSameAsDrop(drag, placedDrag)) {\n                // Not this placed drag.\n                return true;\n            }\n\n            // Now put this drag into the drop.\n            placedDrag.removeClass('valid-drag-over-drop');\n            var currentPlace = thisQ.getClassnameNumericSuffix(placedDrag, 'inplace');\n            var drop = thisQ.getDrop(drag, currentPlace);\n            thisQ.sendDragToDrop(drag, drop);\n            placed = true;\n            return false; // Stop the each() here.\n        });\n\n        if (!placed) {\n            this.sendDragHome(drag);\n        }\n    };\n\n    /**\n     * Animate a drag item into a given place (or back home).\n     *\n     * @param {jQuery|null} drag the item to place. If null, clear the place.\n     * @param {jQuery} drop the place to put it.\n     */\n    DragDropToTextQuestion.prototype.sendDragToDrop = function(drag, drop) {\n        // Is there already a drag in this drop? if so, evict it.\n        var oldDrag = this.getCurrentDragInPlace(this.getPlace(drop));\n        if (oldDrag.length !== 0) {\n            var currentPlace = this.getClassnameNumericSuffix(oldDrag, 'inplace');\n            var hiddenDrop = this.getDrop(oldDrag, currentPlace);\n            hiddenDrop.addClass('active');\n            oldDrag.addClass('beingdragged');\n            oldDrag.offset(hiddenDrop.offset());\n            this.sendDragHome(oldDrag);\n        }\n\n        if (drag.length === 0) {\n            this.setInputValue(this.getPlace(drop), 0);\n            if (drop.data('isfocus')) {\n                drop.focus();\n            }\n        } else {\n            this.setInputValue(this.getPlace(drop), this.getChoice(drag));\n            drag.removeClass('unplaced')\n                .addClass('placed inplace' + this.getPlace(drop));\n            drag.attr('tabindex', 0);\n            this.animateTo(drag, drop);\n        }\n    };\n\n    /**\n     * Animate a drag back to its home.\n     *\n     * @param {jQuery} drag the item being moved.\n     */\n    DragDropToTextQuestion.prototype.sendDragHome = function(drag) {\n        var currentPlace = this.getClassnameNumericSuffix(drag, 'inplace');\n        if (currentPlace !== null) {\n            drag.removeClass('inplace' + currentPlace);\n        }\n        drag.data('unplaced', true);\n\n        this.animateTo(drag, this.getDragHome(this.getGroup(drag), this.getChoice(drag)));\n    };\n\n    /**\n     * Handles keyboard events on drops.\n     *\n     * Drops are focusable. Once focused, right/down/space switches to the next choice, and\n     * left/up switches to the previous. Escape clear.\n     *\n     * @param {KeyboardEvent} e\n     */\n    DragDropToTextQuestion.prototype.handleKeyPress = function(e) {\n        var drop = $(e.target).closest('.drop');\n        if (drop.length === 0) {\n            var placedDrag = $(e.target);\n            var currentPlace = this.getClassnameNumericSuffix(placedDrag, 'inplace');\n            if (currentPlace !== null) {\n                drop = this.getDrop(placedDrag, currentPlace);\n            }\n        }\n        var currentDrag = this.getCurrentDragInPlace(this.getPlace(drop)),\n            nextDrag = $();\n\n        switch (e.keyCode) {\n            case keys.space:\n            case keys.arrowRight:\n            case keys.arrowDown:\n                nextDrag = this.getNextDrag(this.getGroup(drop), currentDrag);\n                break;\n\n            case keys.arrowLeft:\n            case keys.arrowUp:\n                nextDrag = this.getPreviousDrag(this.getGroup(drop), currentDrag);\n                break;\n\n            case keys.escape:\n                break;\n\n            default:\n                questionManager.isKeyboardNavigation = false;\n                return; // To avoid the preventDefault below.\n        }\n\n        if (nextDrag.length) {\n            nextDrag.data('isfocus', true);\n            nextDrag.addClass('beingdragged');\n            var hiddenDrag = this.getDragClone(nextDrag);\n            if (hiddenDrag.length) {\n                if (nextDrag.hasClass('infinite')) {\n                    var noOfDrags = this.noOfDropsInGroup(this.getGroup(nextDrag));\n                    var cloneDrags = this.getInfiniteDragClones(nextDrag, false);\n                    if (cloneDrags.length < noOfDrags) {\n                        var cloneDrag = nextDrag.clone();\n                        cloneDrag.removeClass('beingdragged');\n                        cloneDrag.removeAttr('tabindex');\n                        hiddenDrag.after(cloneDrag);\n                        questionManager.addEventHandlersToDrag(cloneDrag);\n                        nextDrag.offset(cloneDrag.offset());\n                    } else {\n                        hiddenDrag.addClass('active');\n                        nextDrag.offset(hiddenDrag.offset());\n                    }\n                } else {\n                    hiddenDrag.addClass('active');\n                    nextDrag.offset(hiddenDrag.offset());\n                }\n            }\n        } else {\n            drop.data('isfocus', true);\n        }\n\n        e.preventDefault();\n        this.sendDragToDrop(nextDrag, drop);\n    };\n\n    /**\n     * Choose the next drag in a group.\n     *\n     * @param {int} group which group.\n     * @param {jQuery} drag current choice (empty jQuery if there isn't one).\n     * @return {jQuery} the next drag in that group, or null if there wasn't one.\n     */\n    DragDropToTextQuestion.prototype.getNextDrag = function(group, drag) {\n        var choice,\n            numChoices = this.noOfChoicesInGroup(group);\n\n        if (drag.length === 0) {\n            choice = 1; // Was empty, so we want to select the first choice.\n        } else {\n            choice = this.getChoice(drag) + 1;\n        }\n\n        var next = this.getUnplacedChoice(group, choice);\n        while (next.length === 0 && choice < numChoices) {\n            choice++;\n            next = this.getUnplacedChoice(group, choice);\n        }\n\n        return next;\n    };\n\n    /**\n     * Choose the previous drag in a group.\n     *\n     * @param {int} group which group.\n     * @param {jQuery} drag current choice (empty jQuery if there isn't one).\n     * @return {jQuery} the next drag in that group, or null if there wasn't one.\n     */\n    DragDropToTextQuestion.prototype.getPreviousDrag = function(group, drag) {\n        var choice;\n\n        if (drag.length === 0) {\n            choice = this.noOfChoicesInGroup(group);\n        } else {\n            choice = this.getChoice(drag) - 1;\n        }\n\n        var previous = this.getUnplacedChoice(group, choice);\n        while (previous.length === 0 && choice > 1) {\n            choice--;\n            previous = this.getUnplacedChoice(group, choice);\n        }\n\n        // Does this choice exist?\n        return previous;\n    };\n\n    /**\n     * Animate an object to the given destination.\n     *\n     * @param {jQuery} drag the element to be animated.\n     * @param {jQuery} target element marking the place to move it to.\n     */\n    DragDropToTextQuestion.prototype.animateTo = function(drag, target) {\n        var currentPos = drag.offset(),\n            targetPos = target.offset(),\n            thisQ = this;\n\n        M.util.js_pending('qtype_ddwtos-animate-' + thisQ.containerId);\n        // Animate works in terms of CSS position, whereas locating an object\n        // on the page works best with jQuery offset() function. So, to get\n        // the right target position, we work out the required change in\n        // offset() and then add that to the current CSS position.\n        drag.animate(\n            {\n                left: parseInt(drag.css('left')) + targetPos.left - currentPos.left,\n                top: parseInt(drag.css('top')) + targetPos.top - currentPos.top\n            },\n            {\n                duration: 'fast',\n                done: function() {\n                    $('body').trigger('qtype_ddwtos-dragmoved', [drag, target, thisQ]);\n                    M.util.js_complete('qtype_ddwtos-animate-' + thisQ.containerId);\n                }\n            }\n        );\n    };\n\n    /**\n     * Detect if a point is inside a given DOM node.\n     *\n     * @param {Number} pageX the x position.\n     * @param {Number} pageY the y position.\n     * @param {jQuery} drop the node to check (typically a drop).\n     * @return {boolean} whether the point is inside the node.\n     */\n    DragDropToTextQuestion.prototype.isPointInDrop = function(pageX, pageY, drop) {\n        var position = drop.offset();\n        return pageX >= position.left && pageX < position.left + drop.width()\n                && pageY >= position.top && pageY < position.top + drop.height();\n    };\n\n    /**\n     * Set the value of the hidden input for a place, to record what is currently there.\n     *\n     * @param {int} place which place to set the input value for.\n     * @param {int} choice the value to set.\n     */\n    DragDropToTextQuestion.prototype.setInputValue = function(place, choice) {\n        this.getRoot().find('input.placeinput.place' + place).val(choice);\n    };\n\n    /**\n     * Get the outer div for this question.\n     *\n     * @returns {jQuery} containing that div.\n     */\n    DragDropToTextQuestion.prototype.getRoot = function() {\n        return $(document.getElementById(this.containerId));\n    };\n\n    /**\n     * Get drag home for a given choice.\n     *\n     * @param {int} group the group.\n     * @param {int} choice the choice number.\n     * @returns {jQuery} containing that div.\n     */\n    DragDropToTextQuestion.prototype.getDragHome = function(group, choice) {\n        if (!this.getRoot().find('.draghome.dragplaceholder.group' + group + '.choice' + choice).is(':visible')) {\n            return this.getRoot().find('.draggrouphomes' + group +\n                ' span.draghome.infinite' +\n                '.choice' + choice +\n                '.group' + group);\n        }\n        return this.getRoot().find('.draghome.dragplaceholder.group' + group + '.choice' + choice);\n    };\n\n    /**\n     * Get an unplaced choice for a particular group.\n     *\n     * @param {int} group the group.\n     * @param {int} choice the choice number.\n     * @returns {jQuery} jQuery wrapping the unplaced choice. If there isn't one, the jQuery will be empty.\n     */\n    DragDropToTextQuestion.prototype.getUnplacedChoice = function(group, choice) {\n        return this.getRoot().find('.draghome.group' + group + '.choice' + choice + '.unplaced').slice(0, 1);\n    };\n\n    /**\n     * Get the drag that is currently in a given place.\n     *\n     * @param {int} place the place number.\n     * @return {jQuery} the current drag (or an empty jQuery if none).\n     */\n    DragDropToTextQuestion.prototype.getCurrentDragInPlace = function(place) {\n        return this.getRoot().find('span.draghome.inplace' + place);\n    };\n\n    /**\n     * Return the number of blanks in a given group.\n     *\n     * @param {int} group the group number.\n     * @returns {int} the number of drops.\n     */\n    DragDropToTextQuestion.prototype.noOfDropsInGroup = function(group) {\n        return this.getRoot().find('.drop.group' + group).length;\n    };\n\n    /**\n     * Return the number of choices in a given group.\n     *\n     * @param {int} group the group number.\n     * @returns {int} the number of choices.\n     */\n    DragDropToTextQuestion.prototype.noOfChoicesInGroup = function(group) {\n        return this.getRoot().find('.draghome.group' + group).length;\n    };\n\n    /**\n     * Return the number at the end of the CSS class name with the given prefix.\n     *\n     * @param {jQuery} node\n     * @param {String} prefix name prefix\n     * @returns {Number|null} the suffix if found, else null.\n     */\n    DragDropToTextQuestion.prototype.getClassnameNumericSuffix = function(node, prefix) {\n        var classes = node.attr('class');\n        if (classes !== '') {\n            var classesArr = classes.split(' ');\n            for (var index = 0; index < classesArr.length; index++) {\n                var patt1 = new RegExp('^' + prefix + '([0-9])+$');\n                if (patt1.test(classesArr[index])) {\n                    var patt2 = new RegExp('([0-9])+$');\n                    var match = patt2.exec(classesArr[index]);\n                    return Number(match[0]);\n                }\n            }\n        }\n        return null;\n    };\n\n    /**\n     * Get the choice number of a drag.\n     *\n     * @param {jQuery} drag the drag.\n     * @returns {Number} the choice number.\n     */\n    DragDropToTextQuestion.prototype.getChoice = function(drag) {\n        return this.getClassnameNumericSuffix(drag, 'choice');\n    };\n\n    /**\n     * Given a DOM node that is significant to this question\n     * (drag, drop, ...) get the group it belongs to.\n     *\n     * @param {jQuery} node a DOM node.\n     * @returns {Number} the group it belongs to.\n     */\n    DragDropToTextQuestion.prototype.getGroup = function(node) {\n        return this.getClassnameNumericSuffix(node, 'group');\n    };\n\n    /**\n     * Get the place number of a drop, or its corresponding hidden input.\n     *\n     * @param {jQuery} node the DOM node.\n     * @returns {Number} the place number.\n     */\n    DragDropToTextQuestion.prototype.getPlace = function(node) {\n        return this.getClassnameNumericSuffix(node, 'place');\n    };\n\n    /**\n     * Get drag clone for a given drag.\n     *\n     * @param {jQuery} drag the drag.\n     * @returns {jQuery} the drag's clone.\n     */\n    DragDropToTextQuestion.prototype.getDragClone = function(drag) {\n        return this.getRoot().find('.draggrouphomes' +\n            this.getGroup(drag) +\n            ' span.draghome' +\n            '.choice' + this.getChoice(drag) +\n            '.group' + this.getGroup(drag) +\n            '.dragplaceholder');\n    };\n\n    /**\n     * Get infinite drag clones for given drag.\n     *\n     * @param {jQuery} drag the drag.\n     * @param {Boolean} inHome in the home area or not.\n     * @returns {jQuery} the drag's clones.\n     */\n    DragDropToTextQuestion.prototype.getInfiniteDragClones = function(drag, inHome) {\n        if (inHome) {\n            return this.getRoot().find('.draggrouphomes' +\n                this.getGroup(drag) +\n                ' span.draghome' +\n                '.choice' + this.getChoice(drag) +\n                '.group' + this.getGroup(drag) +\n                '.infinite').not('.dragplaceholder');\n        }\n        return this.getRoot().find('span.draghome' +\n            '.choice' + this.getChoice(drag) +\n            '.group' + this.getGroup(drag) +\n            '.infinite').not('.dragplaceholder');\n    };\n\n    /**\n     * Get drop for a given drag and place.\n     *\n     * @param {jQuery} drag the drag.\n     * @param {Integer} currentPlace the current place of drag.\n     * @returns {jQuery} the drop's clone.\n     */\n    DragDropToTextQuestion.prototype.getDrop = function(drag, currentPlace) {\n        return this.getRoot().find('.drop.group' + this.getGroup(drag) + '.place' + currentPlace);\n    };\n\n    /**\n     * Check that the drag is drop to it's clone.\n     *\n     * @param {jQuery} drag The drag.\n     * @param {jQuery} drop The drop.\n     * @returns {boolean}\n     */\n    DragDropToTextQuestion.prototype.isDragSameAsDrop = function(drag, drop) {\n        return this.getChoice(drag) === this.getChoice(drop) && this.getGroup(drag) === this.getGroup(drop);\n    };\n\n    /**\n     * Singleton that tracks all the DragDropToTextQuestions on this page, and deals\n     * with event dispatching.\n     *\n     * @type {Object}\n     */\n    var questionManager = {\n        /**\n         * {boolean} used to ensure the event handlers are only initialised once per page.\n         */\n        eventHandlersInitialised: false,\n\n        /**\n         * {Object} ensures that the drag event handlers are only initialised once per question,\n         * indexed by containerId (id on the .que div).\n         */\n        dragEventHandlersInitialised: {},\n\n        /**\n         * {boolean} is keyboard navigation or not.\n         */\n        isKeyboardNavigation: false,\n\n        /**\n         * {DragDropToTextQuestion[]} all the questions on this page, indexed by containerId (id on the .que div).\n         */\n        questions: {},\n\n        /**\n         * Initialise questions.\n         *\n         * @param {String} containerId id of the outer div for this question.\n         * @param {boolean} readOnly whether the question is being displayed read-only.\n         */\n        init: function(containerId, readOnly) {\n            questionManager.questions[containerId] = new DragDropToTextQuestion(containerId, readOnly);\n            if (!questionManager.eventHandlersInitialised) {\n                questionManager.setupEventHandlers();\n                questionManager.eventHandlersInitialised = true;\n            }\n            if (!questionManager.dragEventHandlersInitialised.hasOwnProperty(containerId)) {\n                questionManager.dragEventHandlersInitialised[containerId] = true;\n                // We do not use the body event here to prevent the other event on Mobile device, such as scroll event.\n                var questionContainer = document.getElementById(containerId);\n                if (questionContainer.classList.contains('ddwtos') &&\n                    !questionContainer.classList.contains('qtype_ddwtos-readonly')) {\n                    // TODO: Convert all the jQuery selectors and events to native Javascript.\n                    questionManager.addEventHandlersToDrag($(questionContainer).find('span.draghome'));\n                }\n            }\n        },\n\n        /**\n         * Set up the event handlers that make this question type work. (Done once per page.)\n         */\n        setupEventHandlers: function() {\n            $('body')\n                .on('keydown',\n                    '.que.ddwtos:not(.qtype_ddwtos-readonly) span.drop',\n                    questionManager.handleKeyPress)\n                .on('keydown',\n                    '.que.ddwtos:not(.qtype_ddwtos-readonly) span.draghome.placed:not(.beingdragged)',\n                    questionManager.handleKeyPress)\n                .on('qtype_ddwtos-dragmoved', questionManager.handleDragMoved);\n        },\n\n        /**\n         * Binding the drag/touch event again for newly created element.\n         *\n         * @param {jQuery} element Element to bind the event\n         */\n        addEventHandlersToDrag: function(element) {\n            // Unbind all the mousedown and touchstart events to prevent double binding.\n            element.unbind('mousedown touchstart');\n            element.on('mousedown touchstart', questionManager.handleDragStart);\n        },\n\n        /**\n         * Handle mouse down / touch start on drags.\n         * @param {Event} e the DOM event.\n         */\n        handleDragStart: function(e) {\n            e.preventDefault();\n            var question = questionManager.getQuestionForEvent(e);\n            if (question) {\n                question.handleDragStart(e);\n            }\n        },\n\n        /**\n         * Handle key down / press on drops.\n         * @param {KeyboardEvent} e\n         */\n        handleKeyPress: function(e) {\n            if (questionManager.isKeyboardNavigation) {\n                return;\n            }\n            questionManager.isKeyboardNavigation = true;\n            var question = questionManager.getQuestionForEvent(e);\n            if (question) {\n                question.handleKeyPress(e);\n            }\n        },\n\n        /**\n         * Given an event, work out which question it affects.\n         *\n         * @param {Event} e the event.\n         * @returns {DragDropToTextQuestion|undefined} The question, or undefined.\n         */\n        getQuestionForEvent: function(e) {\n            var containerId = $(e.currentTarget).closest('.que.ddwtos').attr('id');\n            return questionManager.questions[containerId];\n        },\n\n        /**\n         * Handle when drag moved.\n         *\n         * @param {Event} e the event.\n         * @param {jQuery} drag the drag\n         * @param {jQuery} target the target\n         * @param {DragDropToTextQuestion} thisQ the question.\n         */\n        handleDragMoved: function(e, drag, target, thisQ) {\n            drag.removeClass('beingdragged');\n            drag.css('top', '').css('left', '');\n            target.after(drag);\n            target.removeClass('active');\n            if (typeof drag.data('unplaced') !== 'undefined' && drag.data('unplaced') === true) {\n                drag.removeClass('placed').addClass('unplaced');\n                drag.removeAttr('tabindex');\n                drag.removeData('unplaced');\n                if (drag.hasClass('infinite') && thisQ.getInfiniteDragClones(drag, true).length > 1) {\n                    thisQ.getInfiniteDragClones(drag, true).first().remove();\n                }\n            }\n            if (typeof drag.data('isfocus') !== 'undefined' && drag.data('isfocus') === true) {\n                drag.focus();\n                drag.removeData('isfocus');\n            }\n            if (typeof target.data('isfocus') !== 'undefined' && target.data('isfocus') === true) {\n                target.removeData('isfocus');\n            }\n            if (questionManager.isKeyboardNavigation) {\n                questionManager.isKeyboardNavigation = false;\n            }\n        }\n    };\n\n    /**\n     * @alias module:qtype_ddwtos/ddwtos\n     */\n    return {\n        /**\n         * Initialise one drag-drop into text question.\n         *\n         * @param {String} containerId id of the outer div for this question.\n         * @param {boolean} readOnly whether the question is being displayed read-only.\n         */\n        init: questionManager.init\n    };\n});\n"],"file":"ddwtos.min.js"}