| Línea 22... |
Línea 22... |
| 22 |
*/
|
22 |
*/
|
| 23 |
define([
|
23 |
define([
|
| 24 |
'jquery',
|
24 |
'jquery',
|
| 25 |
'core/dragdrop',
|
25 |
'core/dragdrop',
|
| 26 |
'core/key_codes',
|
26 |
'core/key_codes',
|
| 27 |
'core_form/changechecker'
|
27 |
'core_form/changechecker',
|
| - |
|
28 |
'core_filters/events',
|
| 28 |
], function(
|
29 |
], function(
|
| 29 |
$,
|
30 |
$,
|
| 30 |
dragDrop,
|
31 |
dragDrop,
|
| 31 |
keys,
|
32 |
keys,
|
| 32 |
FormChangeChecker
|
33 |
FormChangeChecker,
|
| - |
|
34 |
filterEvent
|
| 33 |
) {
|
35 |
) {
|
| Línea 34... |
Línea 36... |
| 34 |
|
36 |
|
| Línea 35... |
Línea 37... |
| 35 |
"use strict";
|
37 |
"use strict";
|
| Línea 43... |
Línea 45... |
| 43 |
* @constructor
|
45 |
* @constructor
|
| 44 |
*/
|
46 |
*/
|
| 45 |
function DragDropOntoImageQuestion(containerId, readOnly, places) {
|
47 |
function DragDropOntoImageQuestion(containerId, readOnly, places) {
|
| 46 |
this.containerId = containerId;
|
48 |
this.containerId = containerId;
|
| 47 |
this.questionAnswer = {};
|
49 |
this.questionAnswer = {};
|
| - |
|
50 |
this.questionDragDropWidthHeight = [];
|
| 48 |
M.util.js_pending('qtype_ddimageortext-init-' + this.containerId);
|
51 |
M.util.js_pending('qtype_ddimageortext-init-' + this.containerId);
|
| 49 |
this.places = places;
|
52 |
this.places = places;
|
| 50 |
this.allImagesLoaded = false;
|
53 |
this.allImagesLoaded = false;
|
| 51 |
this.imageLoadingTimeoutId = null;
|
54 |
this.imageLoadingTimeoutId = null;
|
| 52 |
this.isPrinting = false;
|
55 |
this.isPrinting = false;
|
| Línea 60... |
Línea 63... |
| 60 |
});
|
63 |
});
|
| 61 |
this.waitForAllImagesToBeLoaded();
|
64 |
this.waitForAllImagesToBeLoaded();
|
| 62 |
}
|
65 |
}
|
| Línea 63... |
Línea 66... |
| 63 |
|
66 |
|
| - |
|
67 |
/**
|
| - |
|
68 |
* Change all the drags and drops related to the item that has been changed by filter to correct size and content.
|
| - |
|
69 |
*
|
| - |
|
70 |
* @param {object} filteredElement the element has been modified by filter.
|
| - |
|
71 |
*/
|
| - |
|
72 |
DragDropOntoImageQuestion.prototype.changeAllDragsAndDropsToFilteredContent = function(filteredElement) {
|
| - |
|
73 |
let currentFilteredItem = $(filteredElement);
|
| - |
|
74 |
const parentIsDD = currentFilteredItem.parent().closest('div').hasClass('placed') ||
|
| - |
|
75 |
currentFilteredItem.parent().hasClass('draghome');
|
| - |
|
76 |
const isDD = currentFilteredItem.hasClass('placed') || currentFilteredItem.hasClass('draghome');
|
| - |
|
77 |
// The filtered element or parent element should a drag or drop item.
|
| - |
|
78 |
if (!parentIsDD && !isDD) {
|
| - |
|
79 |
return;
|
| - |
|
80 |
}
|
| - |
|
81 |
if (parentIsDD) {
|
| - |
|
82 |
currentFilteredItem = currentFilteredItem.parent().closest('div');
|
| - |
|
83 |
}
|
| - |
|
84 |
if (this.getRoot().find(currentFilteredItem).length <= 0) {
|
| - |
|
85 |
// If the DD item doesn't belong to this question
|
| - |
|
86 |
// In case we have multiple questions in the same page.
|
| - |
|
87 |
return;
|
| - |
|
88 |
}
|
| - |
|
89 |
const group = this.getGroup(currentFilteredItem),
|
| - |
|
90 |
choice = this.getChoice(currentFilteredItem);
|
| - |
|
91 |
let listOfModifiedDragDrop = [];
|
| - |
|
92 |
// Get the list of drag and drop item within the same group and choice.
|
| - |
|
93 |
this.getRoot().find('.group' + group + '.choice' + choice).each(function(i, node) {
|
| - |
|
94 |
// Same modified item, skip it.
|
| - |
|
95 |
if ($(node).get(0) === currentFilteredItem.get(0)) {
|
| - |
|
96 |
return;
|
| - |
|
97 |
}
|
| - |
|
98 |
const originalClass = $(node).attr('class');
|
| - |
|
99 |
const originalStyle = $(node).attr('style');
|
| - |
|
100 |
// We want to keep all the handler and event for filtered item, so using clone is the only choice.
|
| - |
|
101 |
const filteredDragDropClone = currentFilteredItem.clone();
|
| - |
|
102 |
// Sometimes, for the question that has a lot of input groups and unlimited draggable items,
|
| - |
|
103 |
// this 'clone' process takes longer than usual,it will not add the eventHandler for this cloned drag.
|
| - |
|
104 |
// We need to make sure to add the eventHandler for the cloned drag too.
|
| - |
|
105 |
questionManager.addEventHandlersToDrag(filteredDragDropClone);
|
| - |
|
106 |
// Replace the class and style of the drag drop item we want to replace for the clone.
|
| - |
|
107 |
filteredDragDropClone.attr('class', originalClass);
|
| - |
|
108 |
filteredDragDropClone.attr('style', originalStyle);
|
| - |
|
109 |
// Insert into DOM.
|
| - |
|
110 |
$(node).before(filteredDragDropClone);
|
| - |
|
111 |
// Add the item has been replaced to a list so we can remove it later.
|
| - |
|
112 |
listOfModifiedDragDrop.push(node);
|
| - |
|
113 |
});
|
| - |
|
114 |
|
| - |
|
115 |
listOfModifiedDragDrop.forEach(function(node) {
|
| - |
|
116 |
$(node).remove();
|
| - |
|
117 |
});
|
| - |
|
118 |
// Save the current height and width.
|
| - |
|
119 |
const currentHeight = currentFilteredItem.height();
|
| - |
|
120 |
const currentWidth = currentFilteredItem.width();
|
| - |
|
121 |
// Set to auto, so we can get the real height and width of the filtered item.
|
| - |
|
122 |
currentFilteredItem.height('auto');
|
| - |
|
123 |
currentFilteredItem.width('auto');
|
| - |
|
124 |
// We need to set display block so we can get height and width.
|
| - |
|
125 |
// Some browsers can't get the offsetWidth/Height if they are an inline element like span tag.
|
| - |
|
126 |
if (!filteredElement.offsetWidth || !filteredElement.offsetHeight) {
|
| - |
|
127 |
filteredElement.classList.add('d-block');
|
| - |
|
128 |
}
|
| - |
|
129 |
if (this.questionDragDropWidthHeight[group].maxWidth < Math.ceil(filteredElement.offsetWidth) ||
|
| - |
|
130 |
this.questionDragDropWidthHeight[group].maxHeight < Math.ceil(0 + filteredElement.offsetHeight)) {
|
| - |
|
131 |
// Remove the d-block class before calculation.
|
| - |
|
132 |
filteredElement.classList.remove('d-block');
|
| - |
|
133 |
// Now resize all the items in the same group if we have new maximum width or height.
|
| - |
|
134 |
this.resizeAllDragsAndDropsInGroup(group);
|
| - |
|
135 |
} else {
|
| - |
|
136 |
// Calculate the top padding.
|
| - |
|
137 |
const top = Math.floor((this.questionDragDropWidthHeight[group].maxHeight - filteredElement.offsetHeight) / 2);
|
| - |
|
138 |
// Set top padding so the content of filtered item is center again.
|
| - |
|
139 |
currentFilteredItem.width(currentWidth).height(currentHeight).css({
|
| - |
|
140 |
'padding-top': top + 'px',
|
| - |
|
141 |
});
|
| - |
|
142 |
}
|
| - |
|
143 |
// Remove the d-block class after resize.
|
| - |
|
144 |
filteredElement.classList.remove('d-block');
|
| - |
|
145 |
};
|
| - |
|
146 |
|
| 64 |
/**
|
147 |
/**
|
| 65 |
* Waits until all images are loaded before calling setupQuestion().
|
148 |
* Waits until all images are loaded before calling setupQuestion().
|
| 66 |
*
|
149 |
*
|
| 67 |
* This function is called from the onLoad of each image, and also polls with
|
150 |
* This function is called from the onLoad of each image, and also polls with
|
| 68 |
* a time-out, because image on-loads are allegedly unreliable.
|
151 |
* a time-out, because image on-loads are allegedly unreliable.
|
| Línea 92... |
Línea 175... |
| 92 |
}
|
175 |
}
|
| Línea 93... |
Línea 176... |
| 93 |
|
176 |
|
| 94 |
// We now have all images. Carry on, but only after giving the layout a chance to settle down.
|
177 |
// We now have all images. Carry on, but only after giving the layout a chance to settle down.
|
| 95 |
this.allImagesLoaded = true;
|
178 |
this.allImagesLoaded = true;
|
| - |
|
179 |
thisQ.setupQuestion();
|
| - |
|
180 |
// Wait for all dynamic content loaded by filter to be completed.
|
| - |
|
181 |
document.addEventListener(filterEvent.eventTypes.filterContentRenderingComplete, (elements) => {
|
| - |
|
182 |
elements.detail.nodes.forEach((element) => {
|
| - |
|
183 |
thisQ.changeAllDragsAndDropsToFilteredContent(element);
|
| - |
|
184 |
});
|
| 96 |
thisQ.setupQuestion();
|
185 |
});
|
| Línea 97... |
Línea 186... |
| 97 |
};
|
186 |
};
|
| 98 |
|
187 |
|
| 99 |
/**
|
188 |
/**
|
| Línea 133... |
Línea 222... |
| 133 |
*/
|
222 |
*/
|
| 134 |
DragDropOntoImageQuestion.prototype.resizeAllDragsAndDrops = function() {
|
223 |
DragDropOntoImageQuestion.prototype.resizeAllDragsAndDrops = function() {
|
| 135 |
var thisQ = this;
|
224 |
var thisQ = this;
|
| 136 |
this.getRoot().find('.draghomes > div').each(function(i, node) {
|
225 |
this.getRoot().find('.draghomes > div').each(function(i, node) {
|
| 137 |
thisQ.resizeAllDragsAndDropsInGroup(
|
226 |
thisQ.resizeAllDragsAndDropsInGroup(
|
| 138 |
thisQ.getClassnameNumericSuffix($(node), 'dragitemgroup'));
|
227 |
thisQ.getClassnameNumericSuffix($(node), 'dragitemgroup'));
|
| 139 |
});
|
228 |
});
|
| 140 |
};
|
229 |
};
|
| Línea 141... |
Línea 230... |
| 141 |
|
230 |
|
| 142 |
/**
|
231 |
/**
|
| 143 |
* In a given group, set all the drags and drops to be the same size.
|
232 |
* In a given group, set all the drags and drops to be the same size.
|
| 144 |
*
|
233 |
*
|
| 145 |
* @param {int} group the group number.
|
234 |
* @param {int} group the group number.
|
| 146 |
*/
|
235 |
*/
|
| 147 |
DragDropOntoImageQuestion.prototype.resizeAllDragsAndDropsInGroup = function(group) {
|
236 |
DragDropOntoImageQuestion.prototype.resizeAllDragsAndDropsInGroup = function(group) {
|
| 148 |
var root = this.getRoot(),
|
237 |
var root = this.getRoot(),
|
| 149 |
dragHomes = root.find('.dragitemgroup' + group + ' .draghome'),
|
238 |
dragHomes = root.find(".draghome.group" + group),
|
| 150 |
maxWidth = 0,
|
239 |
maxWidth = 0,
|
| Línea 151... |
Línea 240... |
| 151 |
maxHeight = 0;
|
240 |
maxHeight = 0;
|
| 152 |
|
241 |
|
| Línea 157... |
Línea 246... |
| 157 |
});
|
246 |
});
|
| Línea 158... |
Línea 247... |
| 158 |
|
247 |
|
| 159 |
// The size we will want to set is a bit bigger than this.
|
248 |
// The size we will want to set is a bit bigger than this.
|
| 160 |
maxWidth += 10;
|
249 |
maxWidth += 10;
|
| - |
|
250 |
maxHeight += 10;
|
| Línea 161... |
Línea 251... |
| 161 |
maxHeight += 10;
|
251 |
this.questionDragDropWidthHeight[group] = {maxWidth, maxHeight};
|
| 162 |
|
252 |
|
| 163 |
// Set each drag home to that size.
|
- |
|
| 164 |
dragHomes.each(function(i, drag) {
|
253 |
// Set each drag home to that size.
|
| 165 |
var left = Math.round((maxWidth - drag.offsetWidth) / 2),
|
254 |
dragHomes.each(function(i, drag) {
|
| 166 |
top = Math.floor((maxHeight - drag.offsetHeight) / 2);
|
- |
|
| 167 |
// Set top and left padding so the item is centred.
|
- |
|
| 168 |
$(drag).css({
|
255 |
const top = Math.floor((maxHeight - drag.offsetHeight) / 2);
|
| 169 |
'padding-left': left + 'px',
|
256 |
// Set top padding so the item is centred.
|
| 170 |
'padding-right': (maxWidth - drag.offsetWidth - left) + 'px',
|
- |
|
| 171 |
'padding-top': top + 'px',
|
257 |
$(drag).width(maxWidth).height(maxHeight).css({
|
| 172 |
'padding-bottom': (maxHeight - drag.offsetHeight - top) + 'px'
|
258 |
'padding-top': top + 'px',
|
| Línea 173... |
Línea 259... |
| 173 |
});
|
259 |
});
|
| 174 |
});
|
260 |
});
|
| Línea 184... |
Línea 270... |
| 184 |
continue;
|
270 |
continue;
|
| 185 |
}
|
271 |
}
|
| 186 |
if (label === '') {
|
272 |
if (label === '') {
|
| 187 |
label = M.util.get_string('blank', 'qtype_ddimageortext');
|
273 |
label = M.util.get_string('blank', 'qtype_ddimageortext');
|
| 188 |
}
|
274 |
}
|
| - |
|
275 |
if (root.find('.dropzones .dropzone.group' + place.group + '.place' + i).length === 0) {
|
| 189 |
root.find('.dropzones').append('<div class="dropzone active group' + place.group +
|
276 |
root.find('.dropzones').append('<div class="dropzone active group' + place.group +
|
| 190 |
' place' + i + '" tabindex="0">' +
|
277 |
' place' + i + '" tabindex="0">' +
|
| 191 |
'<span class="accesshide">' + label + '</span> </div>');
|
278 |
'<span class="accesshide">' + label + '</span> </div>');
|
| - |
|
279 |
}
|
| 192 |
root.find('.dropzone.place' + i).width(maxWidth - 2).height(maxHeight - 2);
|
280 |
root.find('.dropzone.place' + i).width(maxWidth - 2).height(maxHeight - 2);
|
| 193 |
}
|
281 |
}
|
| 194 |
};
|
282 |
};
|
| Línea 195... |
Línea 283... |
| 195 |
|
283 |
|