Merge branch 'MDL-73457-master-2' of https://github.com/HuongNV13/moodle

This commit is contained in:
Jake Dallimore
2022-03-04 11:59:26 +08:00
8 changed files with 197 additions and 50 deletions
+102 -22
View File
@@ -113,6 +113,13 @@ M.course_dndupload = {
self.sectionRefreshed.bind(self)
);
});
document.addEventListener('scroll', function() {
sections.each(function(el) {
if (el.hasClass('dndupload-dropzone')) {
self.rePositionPreviewInfoElement(el);
}
}, this);
}, true);
},
/**
@@ -295,6 +302,24 @@ M.course_dndupload = {
return false;
},
/**
* Check if the event includes only data of the Files type
*
* Chrome drag page images as files. To differentiate a real file from a page
* image we need to check if all the dataTransfers types are files.
*
* @param {Event} e the event details
* @return true if the data types contains only Files related type
*/
typesIncludesFilesOnly: function(e) {
return e._event.dataTransfer.types.every(function(currentType) {
return (currentType.toLowerCase() != 'text/uri-list'
&& currentType.toLowerCase() != 'text/html'
&& currentType.toLowerCase() != 'text/plain'
);
});
},
/**
* Look through the event data, checking it against the registered data types
* (in order of priority) and return details of the first matching data type
@@ -319,7 +344,7 @@ M.course_dndupload = {
}
// Check for files first.
if (this.types_includes(e, 'Files')) {
if (this.types_includes(e, 'Files') && this.typesIncludesFilesOnly(e)) {
if (e.type != 'drop' || e._event.dataTransfer.files.length != 0) {
if (this.handlers.filehandlers.length == 0) {
return false; // No available file handlers - ignore this drag.
@@ -397,7 +422,7 @@ M.course_dndupload = {
}
}
this.show_preview_element(section, type);
this.showPreviewInfoElement(section);
return false;
},
@@ -549,8 +574,9 @@ M.course_dndupload = {
* Hide any visible dndupload-preview elements on the page
*/
hide_preview_element: function() {
this.Y.all('li.dndupload-preview').addClass('dndupload-hidden');
this.Y.all('.dndupload-preview-wrapper').addClass('dndupload-hidden');
this.Y.all('.dndupload-over').removeClass('dndupload-over');
this.Y.all('.dndupload-dropzone').removeClass('dndupload-dropzone');
},
/**
@@ -558,6 +584,7 @@ M.course_dndupload = {
* the correct message
* @param section the YUI node representing the selected course section
* @param type the details of the data type detected in the drag (including the message to display)
* @deprecated Since Moodle 4.0. Please use showPreviewInfoElement() instead.
*/
show_preview_element: function(section, type) {
this.hide_preview_element();
@@ -569,37 +596,90 @@ M.course_dndupload = {
node.firstChild.nodeValue = type.addmessage;
},
/**
* Unhide the preview information element for the given section and set it to display
* the correct message
* @param {Object} section the YUI node representing the selected course section
*/
showPreviewInfoElement: function(section) {
this.hide_preview_element();
section.one('.dndupload-preview-wrapper').removeClass('dndupload-hidden');
section.addClass('dndupload-dropzone');
this.rePositionPreviewInfoElement(section);
},
/**
* Add the preview element to a course section. Note: this needs to be done before 'addEventListener'
* is called, otherwise Firefox will ignore events generated when the mouse is over the preview
* element (instead of passing them up to the parent element)
* @param section the YUI node representing the selected course section
* @param {Object} section the YUI node representing the selected course section
*/
add_preview_element: function(section) {
var modsel = this.get_mods_element(section);
var preview = {
li: document.createElement('li'),
const modsEl = this.get_mods_element(section);
// Create overlay div.
const overlay = document.createElement('div');
overlay.className = 'dndupload-preview-overlay';
modsEl.get('parentNode').appendChild(overlay);
// Create preview div.
const preview = {
wrapper: document.createElement('div'),
div: document.createElement('div'),
icon: document.createElement('img'),
namespan: document.createElement('span')
iconSpan: document.createElement('span'),
nameSpan: document.createElement('span')
};
preview.li.className = 'dndupload-preview dndupload-hidden';
preview.div.className = 'mod-indent';
preview.li.appendChild(preview.div);
preview.icon.src = M.util.image_url('t/addfile');
preview.icon.className = 'icon';
preview.div.appendChild(preview.icon);
preview.wrapper.className = 'dndupload-preview-wrapper dndupload-hidden';
preview.wrapper.appendChild(preview.div);
preview.div.className = 'dndupload-preview';
preview.div.appendChild(document.createTextNode(' '));
preview.iconSpan.className = 'fa fa-arrow-circle-o-down';
preview.nameSpan.className = 'instancename';
preview.nameSpan.innerHTML = M.util.get_string('addfilehere', 'moodle');
preview.div.appendChild(preview.iconSpan);
preview.div.appendChild(preview.nameSpan);
preview.namespan.className = 'instancename';
preview.namespan.innerHTML = M.util.get_string('addfilehere', 'moodle');
preview.div.appendChild(preview.namespan);
modsEl.get('parentNode').appendChild(preview.wrapper);
},
modsel.appendChild(preview.li);
/**
* Re-position the preview information element by calculating the section position.
*
* @param {Object} section the YUI node representing the selected course section
*/
rePositionPreviewInfoElement: function(section) {
const sectionElement = document.getElementById(section.get('id'));
const rect = sectionElement.getBoundingClientRect();
const sectionHeight = parseInt(window.getComputedStyle(sectionElement).height, 10);
const sectionOffset = rect.top;
const preview = sectionElement.querySelector('.dndupload-preview-wrapper');
const previewHeight = parseInt(window.getComputedStyle(preview).height, 10) +
(2 * parseInt(window.getComputedStyle(preview).padding, 10));
let top, bottom;
if (sectionOffset < 0) {
if (sectionHeight + sectionOffset >= previewHeight) {
// We have enough space here, just stick the preview to the top.
let offSetTop = 0 - sectionOffset;
const navBar = document.querySelector('nav.navbar.fixed-top');
if (navBar) {
offSetTop = offSetTop + navBar.offsetHeight;
}
top = offSetTop + 'px';
bottom = 'unset';
} else {
// We do not have enough space here, just stick the preview to the bottom.
top = 'unset';
bottom = 0;
}
} else {
top = 0;
bottom = 'unset';
}
preview.style.top = top
preview.style.bottom = bottom;
},
/**
+1 -1
View File
@@ -58,7 +58,7 @@ $string['added'] = 'Added {$a}';
$string['addedtogroup'] = 'Added to group "{$a}"';
$string['addedtogroupnot'] = 'Not added to group "{$a}"';
$string['addedtogroupnotenrolled'] = 'Not added to group "{$a}", because not enrolled in course';
$string['addfilehere'] = 'Add file(s) here';
$string['addfilehere'] = 'Drop files here to add them at the bottom of this section';
$string['addinganew'] = 'Adding a new {$a}';
$string['additionalcustomnav'] = 'Additional custom navigation';
$string['addnew'] = 'Add a new {$a}';
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
+8 -10
View File
@@ -443,28 +443,26 @@ export default class extends BaseComponent {
* @returns {Object|undefined} with the dragged data (or undefined if none)
*/
_getDropData(event) {
if (this._containsFiles(event)) {
if (this._containsOnlyFiles(event)) {
return undefined;
}
return activeDropData.get(this.reactive);
}
/**
* Check if the dragged event contains files.
* Check if the dragged event contains only files.
*
* Files dragging does not generate drop data because they came from outsite the page and the component
* Files dragging does not generate drop data because they came from outside the page and the component
* must check it before validating the event.
*
* @param {Event} event the original event.
* @returns {boolean} if the drag dataTransfers contains files.
*/
_containsFiles(event) {
if (event.dataTransfer.types) {
for (var i = 0; i < event.dataTransfer.types.length; i++) {
if (event.dataTransfer.types[i] == "Files") {
return true;
}
}
_containsOnlyFiles(event) {
if (event.dataTransfer.types && event.dataTransfer.types.length > 0) {
// Chrome drag page images as files. To differentiate a real file from a page
// image we need to check if all the dataTransfers types are files.
return event.dataTransfer.types.every(type => type === 'Files');
}
return false;
}
+32 -5
View File
@@ -674,11 +674,14 @@ span.editinstructions {
}
.dndupload-preview {
color: #909090;
border: 1px dashed #909090;
list-style: none;
margin-top: .2em;
padding: .3em;
padding: $modal-inner-padding;
background-color: $primary;
color: $white;
text-align: center;
font-size: $font-size-lg;
max-width: 600px;
margin: 0 auto;
@include border-radius();
}
.dndupload-hidden {
@@ -1336,6 +1339,30 @@ $activity-add-hover: theme-color-level('primary', -10) !default;
white-space: nowrap;
display: inline-block;
}
&.dndupload-dropzone {
border: 2px dashed $primary;
padding-left: 2px;
padding-right: 2px;
position: relative;
.dndupload-preview-overlay {
background-color: $white;
opacity: 0.8;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%;
}
.dndupload-preview-wrapper {
position: absolute;
top: 0;
padding: 2rem;
width: 100%;
}
}
}
.description .course-description-item {
+26 -5
View File
@@ -14219,11 +14219,14 @@ span.editinstructions {
color: #00171b; }
.dndupload-preview {
color: #909090;
border: 1px dashed #909090;
list-style: none;
margin-top: .2em;
padding: .3em; }
padding: 1rem;
background-color: #0f6cbf;
color: #fff;
text-align: center;
font-size: 1.171875rem;
max-width: 600px;
margin: 0 auto;
border-radius: 0.5rem; }
.dndupload-hidden {
display: none; }
@@ -14704,6 +14707,24 @@ span.editinstructions {
margin: 3px;
white-space: nowrap;
display: inline-block; }
.course-section.dndupload-dropzone {
border: 2px dashed #0f6cbf;
padding-left: 2px;
padding-right: 2px;
position: relative; }
.course-section.dndupload-dropzone .dndupload-preview-overlay {
background-color: #fff;
opacity: 0.8;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%; }
.course-section.dndupload-dropzone .dndupload-preview-wrapper {
position: absolute;
top: 0;
padding: 2rem;
width: 100%; }
.description .course-description-item {
font-size: 80%;
+26 -5
View File
@@ -14219,11 +14219,14 @@ span.editinstructions {
color: #00171b; }
.dndupload-preview {
color: #909090;
border: 1px dashed #909090;
list-style: none;
margin-top: .2em;
padding: .3em; }
padding: 1rem;
background-color: #0f6cbf;
color: #fff;
text-align: center;
font-size: 1.171875rem;
max-width: 600px;
margin: 0 auto;
border-radius: 0.25rem; }
.dndupload-hidden {
display: none; }
@@ -14704,6 +14707,24 @@ span.editinstructions {
margin: 3px;
white-space: nowrap;
display: inline-block; }
.course-section.dndupload-dropzone {
border: 2px dashed #0f6cbf;
padding-left: 2px;
padding-right: 2px;
position: relative; }
.course-section.dndupload-dropzone .dndupload-preview-overlay {
background-color: #fff;
opacity: 0.8;
position: absolute;
top: 0;
left: 0;
width: 100%;
height: 100%; }
.course-section.dndupload-dropzone .dndupload-preview-wrapper {
position: absolute;
top: 0;
padding: 2rem;
width: 100%; }
.description .course-description-item {
font-size: 80%;