Does anyone have a working drag-and-drop implementation in Wix Velo they could share?
I am developing an online examination and we want to include a question where students have to drag an image to the correct part of the screen. If anyone has anything similar working, would you share your code?
The structure and setup of the drag-and-drop elements in Wix Velo.
How to handle the drag events and capture the position of the dragged item.
How to validate and determine if the image was dropped in the correct location.
Any additional considerations or best practices for implementing drag-and-drop functionality in Wix Velo.
MyBKExperience Survey
Here’s my code in the public custom-elements folder for a drag-and-drop custom element. But, the image won’t be dragged into the dropDiv like it should. I’m trying to recreate https://www.w3schools.com/html/tryit.asp?filename=tryhtml5_draganddrop .
const IMAGE_URL = 'http://wix.to/vUBXBKU';
const H2_TEXT = 'This is a Custom Element - drag and drop test';
const DEBUG_TEXT = 'Loading the code for Custom Element drag-and-drop.';
const createImage = () => {
const imageElement = document.createElement('img');
imageElement.src = IMAGE_URL;
imageElement.id = 'wdce-image';
imageElement.draggable = 'true';
imageElement.ondragstart = 'drag(event)';
return imageElement;
};
const createH2 = () => {
const h2Element = document.createElement('h2');
h2Element.textContent = H2_TEXT;
h2Element.id = 'wdce-h2';
return h2Element;
};
const createTextContainer = () => {
const textContainer = document.createElement('div');
textContainer.id = 'wdce-text-container';
textContainer.appendChild(createH2());
return textContainer;
};
const createImageContainer = () => {
const imageContainer = document.createElement('div');
imageContainer.id = 'wdce-image-container';
imageContainer.appendChild(createImage());
return imageContainer;
};
// Script to allow drag and drop.
const createScript = () => {
const scriptElement = document.createElement('script');
scriptElement.setAttribute('type', 'text/javascript');
scriptElement.innerHTML = `
function allowDrop(ev) {
ev.preventDefault();
}
function drag(ev) {
ev.dataTransfer.setData("text", ev.target.id);
}
function drop(ev) {
ev.preventDefault();
var data = ev.dataTransfer.getData("text");
ev.target.appendChild(document.getElementById(data));
}
`;
return scriptElement;
};
const createDropDiv = () => {
const dropDiv = document.createElement('div');
dropDiv.id = 'drag-and-drop-div';
dropDiv.ondrop = 'drop(event)';
dropDiv.ondragover = 'allowDrop(event)';
return dropDiv;
};
const createStyle = () => {
const styleElement = document.createElement('style');
styleElement.innerHTML = `
wix-default-custom-element {
background-color: #f0f4f7;
display: flex;
height: 100%;
width: 100%;
}
#wdce-image-container {
width: 35%;
max-width: 165px;
display: flex;
margin: 0 20px 0 30px;
overflow: hidden;
}
#wdce-image {
width: 35%;
min-width: 100px;
}
#drag-and-drop-div {
width: 350px;
height: 300px;
padding: 10px;
border: 1px solid #aaaaaa;
}
#wdce-text-container {
display: flex;
flex-direction: column;
width: 65%;
justify-content: center;
max-width: 314px;
min-width: 200px;
}
#wdce-h2 {
font-family: Helvetica Neue;
font-size: 16px;
font-weight: 500;
letter-spacing: 0.89px;
color: #32536a;
margin: 0 0 16px 0;
}
`;
return styleElement;
};
class DragAndDropCustomElement extends HTMLElement {
constructor() {
super();
console.log(DEBUG_TEXT);
}
connectedCallback() {
this.appendChild(createScript());
this.appendChild(createStyle());
this.appendChild(createTextContainer());
this.appendChild(createImage());
this.appendChild(createDropDiv());
}
}
customElements.define('drag-and-drop-custom-element', DragAndDropCustomElement);
I’ve had success following the approach here: https://www.javascripttutorial.net/web-apis/javascript-drag-and-drop/
In case it is useful to others, my code in the public custom-elements folder is:
const IMAGE_URL = 'http://wix.to/vUBXBKU';
const H2_TEXT = 'This is a Custom Element - drag and drop test';
const DEBUG_TEXT = 'Loading the code for Custom Element drag-and-drop.';
const createImage = () => {
const imageElement = document.createElement('img');
imageElement.src = IMAGE_URL;
imageElement.id = 'wdce-image';
imageElement.draggable = 'true';
imageElement.addEventListener('dragstart', drag);
return imageElement;
};
const createH2 = () => {
const h2Element = document.createElement('h2');
h2Element.textContent = H2_TEXT;
h2Element.id = 'wdce-h2';
return h2Element;
};
const createTextContainer = () => {
const textContainer = document.createElement('div');
textContainer.id = 'wdce-text-container';
textContainer.appendChild(createH2());
return textContainer;
};
const createImageContainer = () => {
const imageContainer = document.createElement('div');
imageContainer.id = 'wdce-image-container';
imageContainer.addEventListener('dragenter', dragEnter)
imageContainer.addEventListener('dragover', dragOver);
imageContainer.addEventListener('dragleave', dragLeave);
imageContainer.addEventListener('drop', drop);
imageContainer.appendChild(createImage());
return imageContainer;
};
// Script to allow drag and drop.
const createScript = () => {
const scriptElement = document.createElement('script');
scriptElement.innerHTML = `
function allowDrop(ev) {
ev.preventDefault();
}
function dragEnter(ev) {
ev.preventDefault();
ev.target.classList.add('drag-over');
}
function dragOver(ev) {
ev.preventDefault();
ev.target.classList.add('drag-over');
}
function dragLeave(ev) {
ev.target.classList.remove('drag-over');
}
function drag(ev) {
ev.dataTransfer.setData('text/plain', ev.target.id);
setTimeout(() => {
ev.target.classList.add('hide');
}, 0);
}
function drop(ev) {
ev.target.classList.remove('drag-over');
// get the draggable element
const id = ev.dataTransfer.getData('text/plain');
const draggable = document.getElementById(id);
// add it to the drop target
ev.target.appendChild(draggable);
// display the draggable element
draggable.classList.remove('hide');
}
`;
return scriptElement;
};
const createDropDiv = () => {
const dropDiv = document.createElement('div');
dropDiv.id = 'drag-and-drop-div';
dropDiv.addEventListener('dragenter', dragEnter)
dropDiv.addEventListener('dragover', dragOver);
dropDiv.addEventListener('dragleave', dragLeave);
dropDiv.addEventListener('drop', drop);
return dropDiv;
};
const createStyle = () => {
const styleElement = document.createElement('style');
styleElement.innerHTML = `
wix-default-custom-element {
background-color: #f0f4f7;
height: 100%;
width: 100%;
}
#wdce-image-container {
width: 350px;
height: 300px;
padding: 10px;
border: 1px solid #aaaaaa;
margin: 0 20px 0 30px;
}
#wdce-image {
width: 150;
}
#drag-and-drop-div {
width: 350px;
height: 300px;
padding: 10px;
border: 1px solid #aaaaaa;
margin: 0 20px 0 30px;
}
#wdce-text-container {
flex-direction: column;
width: 65%;
justify-content: center;
max-width: 314px;
min-width: 200px;
}
#wdce-h2 {
font-family: Helvetica Neue;
font-size: 16px;
font-weight: 500;
letter-spacing: 0.89px;
color: #32536a;
margin: 0 0 16px 0;
}
`;
return styleElement;
};
class DragAndDropCustomElement extends HTMLElement {
constructor() {
super();
console.log(DEBUG_TEXT);
}
connectedCallback() {
this.appendChild(createStyle());
this.appendChild(createScript());
this.appendChild(createTextContainer());
this.appendChild(createImageContainer());
this.appendChild(createDropDiv());
}
}
customElements.define('drag-and-drop-custom-element', DragAndDropCustomElement);