diff --git a/src/addon/qtype/ddimageortext/classes/ddimageortext.ts b/src/addon/qtype/ddimageortext/classes/ddimageortext.ts index e3d1533bb..8e303a71b 100644 --- a/src/addon/qtype/ddimageortext/classes/ddimageortext.ts +++ b/src/addon/qtype/ddimageortext/classes/ddimageortext.ts @@ -133,10 +133,8 @@ export class AddonQtypeDdImageOrTextQuestion { const dragNode = this.doc.cloneNewDragItem(i, dragItemNo); i++; - if (!this.readOnly) { - // Make the item draggable. - this.draggableForQuestion(dragNode, group, choice); - } + // Make the item draggable. + this.draggableForQuestion(dragNode, group, choice); // If the draggable item needs to be created more than once, create the rest of copies. if (dragNode.classList.contains('infinite')) { @@ -146,9 +144,8 @@ export class AddonQtypeDdImageOrTextQuestion { while (dragsToCreate > 0) { const newDragNode = this.doc.cloneNewDragItem(i, dragItemNo); i++; - if (!this.readOnly) { - this.draggableForQuestion(newDragNode, group, choice); - } + this.draggableForQuestion(newDragNode, group, choice); + dragsToCreate--; } } @@ -202,11 +199,15 @@ export class AddonQtypeDdImageOrTextQuestion { let dragItemsArea = topNode.querySelector('div.draghomes'); if (dragItemsArea) { + // On 3.9+ dragitems were removed. + const dragItems = topNode.querySelector('div.dragitems'); + + if (dragItems) { + // Remove empty div.dragitems. + dragItems.remove(); + } + // 3.6+ site, transform HTML so it has the same structure as in Moodle 3.5. - - // Remove empty div.dragitems. - topNode.querySelector('div.dragitems').remove(); - const ddArea = topNode.querySelector('div.ddarea'); // Move div.dropzones to div.ddarea. @@ -332,17 +333,19 @@ export class AddonQtypeDdImageOrTextQuestion { drag.setAttribute('group', String(group)); drag.setAttribute('choice', String(choice)); - // Listen to click events. - drag.addEventListener('click', (e) => { - e.preventDefault(); - e.stopPropagation(); + if (!this.readOnly) { + // Listen to click events. + drag.addEventListener('click', (e) => { + e.preventDefault(); + e.stopPropagation(); - if (drag.classList.contains('beingdragged')) { - this.deselectDrags(); - } else { - this.selectDrag(drag); - } - }); + if (drag.classList.contains('beingdragged')) { + this.deselectDrags(); + } else { + this.selectDrag(drag); + } + }); + } } /** @@ -387,14 +390,9 @@ export class AddonQtypeDdImageOrTextQuestion { getUnplacedChoiceForDrop(choice: number, drop: HTMLElement): HTMLElement { const dragItems = this.getChoicesForDrop(choice, drop); - for (let x = 0; x < dragItems.length; x++) { - const dragItem = dragItems[x]; - if (this.readOnly || (!dragItem.classList.contains('placed') && !dragItem.classList.contains('beingdragged'))) { - return dragItem; - } - } - - return null; + return dragItems.find((dragItem) => { + return (!dragItem.classList.contains('placed') && !dragItem.classList.contains('beingdragged')); + }) || null; } /** @@ -530,7 +528,7 @@ export class AddonQtypeDdImageOrTextQuestion { if (originInputId && originInputId != targetInputId) { // Remove it from the previous place. const originInputNode = this.doc.topNode().querySelector('input#' + originInputId); - originInputNode.setAttribute('value', ''); + originInputNode.setAttribute('value', '0'); } // Now position the draggable and set it to the input. @@ -539,7 +537,10 @@ export class AddonQtypeDdImageOrTextQuestion { drag.style.top = position[1] - 1 + 'px'; drag.classList.add('placed'); - inputNode.setAttribute('value', drag.getAttribute('choice')); + if (drag.getAttribute('choice')) { + inputNode.setAttribute('value', drag.getAttribute('choice')); + } + drag.setAttribute('inputid', targetInputId); } @@ -575,7 +576,7 @@ export class AddonQtypeDdImageOrTextQuestion { const inputId = drag.getAttribute('inputid'); if (inputId) { const inputNode = this.doc.topNode().querySelector('input#' + inputId); - inputNode.setAttribute('value', ''); + inputNode.setAttribute('value', '0'); } // Move the element to its original position. @@ -652,6 +653,7 @@ export class AddonQtypeDdImageOrTextQuestion { if (choice > 0) { const dragItem = this.getUnplacedChoiceForDrop(choice, dropZone); + if (dragItem !== null) { this.placeDragInDrop(dragItem, dropZone); } diff --git a/src/addon/qtype/ddimageortext/component/ddimageortext.scss b/src/addon/qtype/ddimageortext/component/ddimageortext.scss index 9523b78ab..2bd859fed 100644 --- a/src/addon/qtype/ddimageortext/component/ddimageortext.scss +++ b/src/addon/qtype/ddimageortext/component/ddimageortext.scss @@ -35,6 +35,28 @@ addon-qtype-ddimageortext { } } + .group2 { + border-radius: 10px 0 0 0; + } + .group3 { + border-radius: 0 10px 0 0; + } + .group4 { + border-radius: 0 0 10px 0; + } + .group5 { + border-radius: 0 0 0 10px; + } + .group6 { + border-radius: 0 10px 10px 0; + } + .group7 { + border-radius: 10px 0 0 10px; + } + .group8 { + border-radius: 10px 10px 10px 10px; + } + .drag { border: 1px solid $gray-darker; color: $text-color; diff --git a/src/addon/qtype/ddmarker/classes/ddmarker.ts b/src/addon/qtype/ddmarker/classes/ddmarker.ts index d5199c656..90b5686b1 100644 --- a/src/addon/qtype/ddmarker/classes/ddmarker.ts +++ b/src/addon/qtype/ddmarker/classes/ddmarker.ts @@ -27,6 +27,7 @@ export interface AddonQtypeDdMarkerQuestionDocStructure { dragItems?: () => HTMLElement[]; dragItemsForChoice?: (choiceNo: number) => HTMLElement[]; dragItemForChoice?: (choiceNo: number, itemNo: number) => HTMLElement; + dragItemPlaceholder?: (choiceNo: number) => HTMLElement; dragItemBeingDragged?: (choiceNo: number) => HTMLElement; dragItemHome?: (choiceNo: number) => HTMLElement; dragItemHomes?: () => HTMLElement[]; @@ -36,6 +37,14 @@ export interface AddonQtypeDdMarkerQuestionDocStructure { markerTexts?: () => HTMLElement; } +/** + * Point type. + */ +export type AddonQtypeDdMarkerQuestionPoint = { + x: number; // X axis coordinates. + y: number; // Y axis coordinates. +}; + /** * Class to make a question of ddmarker type work. */ @@ -98,14 +107,13 @@ export class AddonQtypeDdMarkerQuestion { * @return The new element. */ cloneNewDragItem(dragHome: HTMLElement, itemNo: number): HTMLElement { - const marker = dragHome.querySelector('span.markertext'); - marker.style.opacity = '0.6'; - // Clone the element and add the right classes. const drag = dragHome.cloneNode(true); drag.classList.remove('draghome'); drag.classList.add('dragitem'); drag.classList.add('item' + itemNo); + drag.classList.remove('dragplaceholder'); // In case it has it. + dragHome.classList.add('dragplaceholder'); // Insert the new drag after the dragHome. dragHome.parentElement.insertBefore(drag, dragHome.nextSibling); @@ -122,15 +130,14 @@ export class AddonQtypeDdMarkerQuestion { * @param bgImgXY X and Y of the BG IMG relative position. * @return Position relative to the window. */ - convertToWindowXY(bgImgXY: number[]): number[] { - const bgImg = this.doc.bgImg(), - position = this.domUtils.getElementXY(bgImg, null, 'ddarea'); + convertToWindowXY(bgImgXY: string): number[] { + const bgImg = this.doc.bgImg(); + const position = this.domUtils.getElementXY(bgImg, null, 'ddarea'); + let coordsNumbers = this.parsePoint(bgImgXY); - // Render the position related to the current image dimensions. - bgImgXY[0] *= this.proportion; - bgImgXY[1] *= this.proportion; + coordsNumbers = this.makePointProportional(coordsNumbers); - return [Number(bgImgXY[0]) + position[0], Number(bgImgXY[1]) + position[1]]; + return [coordsNumbers.x + position[0], coordsNumbers.y + position[1]]; } /** @@ -139,10 +146,10 @@ export class AddonQtypeDdMarkerQuestion { * @param coords Coordinates to check. * @return Whether they're inside the background image. */ - coordsInImg(coords: number[]): boolean { + coordsInImg(coords: AddonQtypeDdMarkerQuestionPoint): boolean { const bgImg = this.doc.bgImg(); - return (coords[0] * this.proportion <= bgImg.width && coords[1] * this.proportion <= bgImg.height); + return (coords.x * this.proportion <= bgImg.width + 1) && (coords.y * this.proportion <= bgImg.height + 1); } /** @@ -173,7 +180,7 @@ export class AddonQtypeDdMarkerQuestion { */ docStructure(slot: number): AddonQtypeDdMarkerQuestionDocStructure { const topNode = this.container.querySelector('.addon-qtype-ddmarker-container'), - dragItemsArea = topNode.querySelector('div.dragitems'); + dragItemsArea = topNode.querySelector('div.dragitems, div.draghomes'); return { topNode: (): HTMLElement => { @@ -194,14 +201,18 @@ export class AddonQtypeDdMarkerQuestion { dragItemForChoice: (choiceNo: number, itemNo: number): HTMLElement => { return dragItemsArea.querySelector('span.dragitem.choice' + choiceNo + '.item' + itemNo); }, + dragItemPlaceholder: (choiceNo: number): HTMLElement => { + return dragItemsArea.querySelector('span.dragplaceholder.choice' + choiceNo); + }, dragItemBeingDragged: (choiceNo: number): HTMLElement => { return dragItemsArea.querySelector('span.dragitem.beingdragged.choice' + choiceNo); }, dragItemHome: (choiceNo: number): HTMLElement => { - return dragItemsArea.querySelector('span.draghome.choice' + choiceNo); + return dragItemsArea.querySelector('span.draghome.choice' + choiceNo + + ', span.marker.choice' + choiceNo); }, dragItemHomes: (): HTMLElement[] => { - return Array.from(dragItemsArea.querySelectorAll('span.draghome')); + return Array.from(dragItemsArea.querySelectorAll('span.draghome, span.marker')); }, getClassnameNumericSuffix: (node: HTMLElement, prefix: string): number => { @@ -328,13 +339,11 @@ export class AddonQtypeDdMarkerQuestion { const markerSpan = this.doc.topNode().querySelector( 'div.ddarea div.markertexts span.markertext' + dropZoneNo); if (markerSpan !== null) { - - xyForText[0] = (xyForText[0] - markerSpan.offsetWidth / 2) * this.proportion; - xyForText[1] = (xyForText[1] - markerSpan.offsetHeight / 2) * this.proportion; - + const width = this.domUtils.getElementMeasure(markerSpan, true, true, false, true); + const height = this.domUtils.getElementMeasure(markerSpan, false, true, false, true); markerSpan.style.opacity = '0.6'; - markerSpan.style.left = xyForText[0] + 'px'; - markerSpan.style.top = xyForText[1] + 'px'; + markerSpan.style.left = (xyForText.x - (width / 2)) + 'px'; + markerSpan.style.top = (xyForText.y - (height / 2)) + 'px'; const markerSpanAnchor = markerSpan.querySelector('a'); if (markerSpanAnchor !== null) { @@ -364,38 +373,36 @@ export class AddonQtypeDdMarkerQuestion { * Draw a circle in a drop zone. * * @param dropZoneNo Number of the drop zone. - * @param coords Coordinates of the circle. + * @param coordinates Coordinates of the circle. * @param colour Colour of the circle. * @return X and Y position of the center of the circle. */ - drawShapeCircle(dropZoneNo: number, coords: string, colour: string): number[] { - // Extract the numbers in the coordinates. - const coordsParts = coords.match(/(\d+),(\d+);(\d+)/); + drawShapeCircle(dropZoneNo: number, coordinates: string, colour: string): AddonQtypeDdMarkerQuestionPoint { + if (!coordinates.match(/^\d+(\.\d+)?,\d+(\.\d+)?;\d+(\.\d+)?$/)) { + return null; + } - if (coordsParts && coordsParts.length === 4) { - // Remove first element and convert them to number. - coordsParts.shift(); + const bits = coordinates.split(';'); + let centre = this.parsePoint(bits[0]); + const radius = Number(bits[1]); - const coordsPartsNum = coordsParts.map((i) => { - return Number(i); + // Calculate circle limits and check it's inside the background image. + const circleLimit = {x: centre.x - radius, y: centre.y - radius}; + if (this.coordsInImg(circleLimit)) { + centre = this.makePointProportional(centre); + + // All good, create the shape. + this.shapes[dropZoneNo] = this.graphics.addShape({ + type: 'circle', + color: colour + }, { + cx: centre.x, + cy: centre.y, + r: Math.round(radius * this.proportion) }); - // Calculate circle limits and check it's inside the background image. - const circleLimit = [coordsPartsNum[0] - coordsPartsNum[2], coordsPartsNum[1] - coordsPartsNum[2]]; - if (this.coordsInImg(circleLimit)) { - // All good, create the shape. - this.shapes[dropZoneNo] = this.graphics.addShape({ - type: 'circle', - color: colour - }, { - cx: coordsPartsNum[0] * this.proportion, - cy: coordsPartsNum[1] * this.proportion, - r: coordsPartsNum[2] * this.proportion - }); - - // Return the center. - return [coordsPartsNum[0], coordsPartsNum[1]]; - } + // Return the centre. + return centre; } return null; @@ -405,39 +412,40 @@ export class AddonQtypeDdMarkerQuestion { * Draw a rectangle in a drop zone. * * @param dropZoneNo Number of the drop zone. - * @param coords Coordinates of the rectangle. + * @param coordinates Coordinates of the rectangle. * @param colour Colour of the rectangle. * @return X and Y position of the center of the rectangle. */ - drawShapeRectangle(dropZoneNo: number, coords: string, colour: string): number[] { - // Extract the numbers in the coordinates. - const coordsParts = coords.match(/(\d+),(\d+);(\d+),(\d+)/); + drawShapeRectangle(dropZoneNo: number, coordinates: string, colour: string): AddonQtypeDdMarkerQuestionPoint { + if (!coordinates.match(/^\d+(\.\d+)?,\d+(\.\d+)?;\d+(\.\d+)?,\d+(\.\d+)?$/)) { + return null; + } - if (coordsParts && coordsParts.length === 5) { - // Remove first element and convert them to number. - coordsParts.shift(); + const bits = coordinates.split(';'); + const startPoint = this.parsePoint(bits[0]); + const size = this.parsePoint(bits[1]); - const coordsPartsNum = coordsParts.map((i) => { - return Number(i); + // Calculate rectangle limits and check it's inside the background image. + const rectLimits = {x: startPoint.x + size.x, y: startPoint.y + size.y}; + if (this.coordsInImg(rectLimits)) { + const startPointProp = this.makePointProportional(startPoint); + const sizeProp = this.makePointProportional(size); + + // All good, create the shape. + this.shapes[dropZoneNo] = this.graphics.addShape({ + type: 'rect', + color: colour + }, { + x: startPointProp.x, + y: startPointProp.y, + width: sizeProp.x, + height: sizeProp.y }); - // Calculate rectangle limits and check it's inside the background image. - const rectLimits = [coordsPartsNum[0] + coordsPartsNum[2], coordsPartsNum[1] + coordsPartsNum[3]]; - if (this.coordsInImg(rectLimits)) { - // All good, create the shape. - this.shapes[dropZoneNo] = this.graphics.addShape({ - type: 'rect', - color: colour - }, { - x: coordsPartsNum[0] * this.proportion, - y: coordsPartsNum[1] * this.proportion, - width: coordsPartsNum[2] * this.proportion, - height: coordsPartsNum[3] * this.proportion - }); + const centre = { x: startPoint.x + (size.x / 2) , y: startPoint.y + (size.y / 2)}; - // Return the center. - return [coordsPartsNum[0] + coordsPartsNum[2] / 2, coordsPartsNum[1] + coordsPartsNum[3] / 2]; - } + // Return the centre. + return this.makePointProportional(centre); } return null; @@ -447,53 +455,83 @@ export class AddonQtypeDdMarkerQuestion { * Draw a polygon in a drop zone. * * @param dropZoneNo Number of the drop zone. - * @param coords Coordinates of the polygon. + * @param coordinates Coordinates of the polygon. * @param colour Colour of the polygon. * @return X and Y position of the center of the polygon. */ - drawShapePolygon(dropZoneNo: number, coords: string, colour: string): number[] { - const coordsParts = coords.split(';'), - points = [], - bgImg = this.doc.bgImg(), - maxXY = [0, 0], - minXY = [bgImg.width, bgImg.height]; - - for (const i in coordsParts) { - // Extract the X and Y of this point. - const partsString = coordsParts[i].match(/^(\d+),(\d+)$/), - parts = partsString && partsString.map((part) => { - return Number(part); - }); - - if (parts !== null && this.coordsInImg([parts[1], parts[2]])) { - parts[1] *= this.proportion; - parts[2] *= this.proportion; - - // Calculate min and max points to find center to show marker on. - minXY[0] = Math.min(parts[1], minXY[0]); - minXY[1] = Math.min(parts[2], minXY[1]); - maxXY[0] = Math.max(parts[1], maxXY[0]); - maxXY[1] = Math.max(parts[2], maxXY[1]); - - points.push(parts[1] + ',' + parts[2]); - } + drawShapePolygon(dropZoneNo: number, coordinates: string, colour: string): AddonQtypeDdMarkerQuestionPoint { + if (!coordinates.match(/^\d+(\.\d+)?,\d+(\.\d+)?(?:;\d+(\.\d+)?,\d+(\.\d+)?)*$/)) { + return null; } - if (points.length > 2) { + const bits = coordinates.split(';'); + const centre = {x: 0, y: 0}; + const points = bits.map((bit) => { + const point = this.parsePoint(bit); + centre.x += point.x; + centre.y += point.y; + + return point; + }); + + if (points.length > 0) { + centre.x = Math.round(centre.x / points.length); + centre.y = Math.round(centre.y / points.length); + } + + const pointsOnImg = []; + points.forEach((point) => { + if (this.coordsInImg(point)) { + point = this.makePointProportional(point); + + pointsOnImg.push(point.x + ',' + point.y); + } + }); + + if (pointsOnImg.length > 2) { this.shapes[dropZoneNo] = this.graphics.addShape({ type: 'polygon', color: colour }, { - points: points.join(' ') + points: pointsOnImg.join(' ') }); - // Return the center. - return [(minXY[0] + maxXY[0]) / 2, (minXY[1] + maxXY[1]) / 2]; + // Return the centre. + return this.makePointProportional(centre); } return null; } + /** + * Make a point from the string representation. + * + * @param coordinates "x,y". + * @return Coordinates to the point. + */ + parsePoint(coordinates: string): AddonQtypeDdMarkerQuestionPoint { + const bits = coordinates.split(','); + if (bits.length !== 2) { + throw coordinates + ' is not a valid point'; + } + + return {x: Number(bits[0]), y: Number(bits[1])}; + } + + /** + * Make proportional position of the point. + * + * @param point Point coordinates. + * @return Converted point. + */ + makePointProportional(point: AddonQtypeDdMarkerQuestionPoint): AddonQtypeDdMarkerQuestionPoint { + return { + x: Math.round(point.x * this.proportion), + y: Math.round(point.y * this.proportion) + + }; + } + /** * Drop a drag element into a certain position. * @@ -507,9 +545,6 @@ export class AddonQtypeDdMarkerQuestion { // Set the position related to the natural image dimensions. if (this.proportion < 1) { position[0] = Math.round(position[0] / this.proportion); - } - - if (this.proportion < 1) { position[1] = Math.round(position[1] / this.proportion); } } @@ -538,11 +573,7 @@ export class AddonQtypeDdMarkerQuestion { const coordsStrings = fv.split(';'); for (let i = 0; i < coordsStrings.length; i++) { - const coordsNumbers = coordsStrings[i].split(',').map((i) => { - return Number(i); - }); - - coords[coords.length] = this.convertToWindowXY(coordsNumbers); + coords[coords.length] = this.convertToWindowXY(coordsStrings[i]); } } @@ -581,9 +612,6 @@ export class AddonQtypeDdMarkerQuestion { // Set the position related to the natural image dimensions. if (this.proportion < 1) { position[0] = Math.round(position[0] / this.proportion); - } - - if (this.proportion < 1) { position[1] = Math.round(position[1] / this.proportion); } @@ -723,6 +751,12 @@ export class AddonQtypeDdMarkerQuestion { this.question.loaded = true; }; + if (bgImg.complete && bgImg.naturalWidth) { + imgLoaded(); + + return; + } + bgImg.addEventListener('load', imgLoaded); // Try again after a while. @@ -764,13 +798,25 @@ export class AddonQtypeDdMarkerQuestion { dragItem.classList.remove('unneeded'); } + const placeholder = this.doc.dragItemPlaceholder(choiceNo); + // Remove the class only if is placed on the image. if (homePosition[0] != coords[i][0] || homePosition[1] != coords[i][1]) { dragItem.classList.remove('unplaced'); - } + dragItem.classList.add('placed'); - dragItem.style.left = coords[i][0] + 'px'; - dragItem.style.top = coords[i][1] + 'px'; + const computedStyle = getComputedStyle(dragItem); + const left = coords[i][0] - this.domUtils.getComputedStyleMeasure(computedStyle, 'marginLeft'); + const top = coords[i][1] - this.domUtils.getComputedStyleMeasure(computedStyle, 'marginTop'); + + dragItem.style.left = left + 'px'; + dragItem.style.top = top + 'px'; + placeholder.classList.add('active'); + } else { + dragItem.classList.remove('placed'); + dragItem.classList.add('unplaced'); + placeholder.classList.remove('active'); + } } } diff --git a/src/addon/qtype/ddmarker/component/ddmarker.scss b/src/addon/qtype/ddmarker/component/ddmarker.scss index cba59c4e7..7c33d5302 100644 --- a/src/addon/qtype/ddmarker/component/ddmarker.scss +++ b/src/addon/qtype/ddmarker/component/ddmarker.scss @@ -9,24 +9,15 @@ addon-qtype-ddmarker { display: block; } + .droparea { + display: inline-block; + } + div.droparea img { border: 1px solid $gray-darker; max-width: 100%; } - .draghome img, .draghome span { - visibility: hidden; - } - - .dragitems .dragitem { - cursor: pointer; - position: absolute; - z-index: 2; - } - - .dropzones { - position: absolute; - } .dropzones svg { z-index: 3; } @@ -35,31 +26,81 @@ addon-qtype-ddmarker { z-index: 5; box-shadow: $core-dd-question-selected-shadow; } - .dragitems .draghome { - margin: 10px; - display: inline-block; + + .dragitems, // Previous to 3.9. + .draghomes { + &.readonly { + .dragitem, + .marker { + cursor: auto; + } + } + + .dragitem, // Previous to 3.9. + .draghome, + .marker { + vertical-align: top; + cursor: pointer; + position: relative; + margin: 10px; + display: inline-block; + &.dragplaceholder { + display: none; + visibility: hidden; + + &.active { + display: inline-block; + } + } + + &.unplaced { + position: relative; + } + &.placed { + position: absolute; + opacity: 0.6; + } + } } - .dragitems.readonly .dragitem { - cursor: auto; + .droparea { + .dragitem, + .marker { + cursor: pointer; + position: absolute; + vertical-align: top; + z-index: 2; + } } + div.ddarea { text-align: center; + position: relative; } + div.ddarea .dropzones, div.ddarea .markertexts { + top: 0; + left: 0; min-height: 80px; position: absolute; @include text-align('start'); } + .dropbackground { margin: 0 auto; } - div.dragitems div.draghome, div.dragitems div.dragitem, - div.draghome, div.drag { + div.dragitems div.draghome, + div.dragitems div.dragitem, + div.draghome, + div.drag, + div.draghomes div.marker, + div.marker, + div.drag { font: 13px/1.231 arial,helvetica,clean,sans-serif; } div.dragitems span.markertext, + div.draghomes span.markertext, div.markertexts span.markertext { margin: 0 5px; z-index: 2; @@ -86,17 +127,18 @@ addon-qtype-ddmarker { border-color: $yellow; padding: 5px; border-radius: 10px; - filter: alpha(opacity=60); opacity: 0.6; margin: 5px; display: inline-block; } - div.dragitems img.target { + div.dragitems img.target, + div.draghomes img.target { position: absolute; left: -7px; /* This must be half the size of the target image, minus 0.5. */ top: -7px; /* In other words, this works for a 15x15 cross-hair. */ } - div.dragitems div.draghome img.target { + div.dragitems div.draghome img.target, + div.draghomes div.marker img.target { display: none; } } diff --git a/src/addon/qtype/ddmarker/component/ddmarker.ts b/src/addon/qtype/ddmarker/component/ddmarker.ts index a7d30837c..1b0870b36 100644 --- a/src/addon/qtype/ddmarker/component/ddmarker.ts +++ b/src/addon/qtype/ddmarker/component/ddmarker.ts @@ -89,14 +89,20 @@ export class AddonQtypeDdMarkerComponent extends CoreQuestionBaseComponent imple } } else if (this.question.amdArgs) { // Moodle version >= 3.6. - if (typeof this.question.amdArgs[1] != 'undefined') { - this.imgSrc = this.question.amdArgs[1]; + let nextIndex = 1; + // Moodle version >= 3.9, imgSrc is not specified, do not advance index. + if (typeof this.question.amdArgs[nextIndex] != 'undefined' && typeof this.question.amdArgs[nextIndex] != 'boolean') { + this.imgSrc = this.question.amdArgs[nextIndex]; + nextIndex++; } - if (typeof this.question.amdArgs[2] != 'undefined') { - this.question.readOnly = this.question.amdArgs[2]; + + if (typeof this.question.amdArgs[nextIndex] != 'undefined') { + this.question.readOnly = this.question.amdArgs[nextIndex]; } - if (typeof this.question.amdArgs[3] != 'undefined') { - this.dropZones = this.question.amdArgs[3]; + nextIndex++; + + if (typeof this.question.amdArgs[nextIndex] != 'undefined') { + this.dropZones = this.question.amdArgs[nextIndex]; } } diff --git a/src/addon/qtype/ddwtos/component/ddwtos.scss b/src/addon/qtype/ddwtos/component/ddwtos.scss index 30a103686..6bce91256 100644 --- a/src/addon/qtype/ddwtos/component/ddwtos.scss +++ b/src/addon/qtype/ddwtos/component/ddwtos.scss @@ -33,7 +33,6 @@ addon-qtype-ddwtos { } .draghome, .drag.unplaced{ border: 1px solid $gray-darker; - border-radius: 5px; } .draghome { visibility: hidden; @@ -89,6 +88,28 @@ addon-qtype-ddwtos { } } + .group2 { + border-radius: 10px 0 0 0; + } + .group3 { + border-radius: 0 10px 0 0; + } + .group4 { + border-radius: 0 0 10px 0; + } + .group5 { + border-radius: 0 0 0 10px; + } + .group6 { + border-radius: 0 10px 10px 0; + } + .group7 { + border-radius: 10px 0 0 10px; + } + .group8 { + border-radius: 10px 10px 10px 10px; + } + sub, sup { font-size: 80%; position: relative; diff --git a/src/core/question/providers/helper.ts b/src/core/question/providers/helper.ts index 378c1a2cb..edaf17390 100644 --- a/src/core/question/providers/helper.ts +++ b/src/core/question/providers/helper.ts @@ -277,7 +277,7 @@ export class CoreQuestionHelperProvider { const amdRegExp = new RegExp('require\\(\\[["\']qtype_' + question.type + '/question["\']\\],[^f]*' + 'function\\(amd\\)[^\\{]*\\{[^a]*amd\\.init\\((["\'](q|question-' + usageId + '-)' + question.slot + - '["\'].*)\\);', 'm'); + '["\'].*?)\\);', 'm'); const amdMatch = match.match(amdRegExp); if (amdMatch) {