Search code examples
javascripthtmlcssdrag-and-dropdraggable

How to swicth position of two draggable elements (Javascript)


I struggle with a functionnality I want to implement to my exercice : when we drop an element on something that already has an element, I want this to switch it with the other one.

You don't have the pictures, but the main thing is working.

If you have any idea of how I could do this (or where to start working).

const fills = document.querySelectorAll('.fill');
const empties = document.querySelectorAll('.empty');

var actualFill = null;

var scrollSpaceTop = document.getElementById("scrollSpaceTop");
scrollSpaceTop.remove();
var scrollSpaceBottom = document.getElementById("scrollSpaceBottom");
scrollSpaceBottom.remove();

var scrolls = document.getElementById("scrolls");

const questions = document.getElementById("questions");
var elements = [];
var elemNumb = 24;

for(let i = 1; i < elemNumb; i++)
{
    window['ques'+i] = document.getElementById("ques"+i);
    elements.push(window['ques'+i]);
}

ShuffleArray(elements);


for(element of elements)
{
    element.remove();
    questions.appendChild(element);
}

for(const fill of fills){
    fill.addEventListener('dragstart', dragStart);
    fill.addEventListener('dragend', dragEnd);
}

for(const empty of empties){
    empty.addEventListener('dragover', dragOver);
    empty.addEventListener('dragenter', dragEnter);
    empty.addEventListener('dragleave', dragLeave);
    empty.addEventListener('drop', dragDrop);
}


function dragStart() {
    this.className += ' hold';
    setTimeout(() => (this.className ='invisible'), 0);
    actualFill = this;

    scrolls.appendChild(scrollSpaceTop);
    scrolls.appendChild(scrollSpaceBottom);
}

function dragEnd() {
    this.className = 'fill';

    scrollSpaceTop.remove();
    scrollSpaceBottom.remove();
}

function dragOver(e){
    e.preventDefault();
}

function dragEnter(e){
    e.preventDefault();
    this.className += ' hovered';
}


function dragLeave() {
    this.className = 'empty';
}

function dragDrop() {


    if (this.hasChildNodes()) 
    {
        var childs = this.childNodes;

        for(var child of childs)
        {
            if(child.nodeName == "DIV")
            {
                this.className = 'empty';
                console.log('not empty');
                return;
            }               
        }

    this.className = 'empty';
    this.append(actualFill);    
    
    }
    else
    {
        this.className = 'empty';
        this.append(actualFill);
    }
    
}

function Validate()
{

var score = 0;
//PLEIN
    var q1 = document.getElementById("q1");

    if (q1.hasChildNodes()) 
    {
        cq1 = q1.childNodes[0];

        if(cq1.id == "plein")
        {
            q1.parentElement.style.borderColor = "lightgreen";
            ++score;
        }
        else
        {
            q1.parentElement.style.borderColor = "Crimson";
        }
    }
    else
    {
        q1.parentElement.style.borderColor = "Crimson";
    }


//BON

    var q2 = document.getElementById("q2");

    if (q2.hasChildNodes()) 
    {
        cq2 = q2.childNodes[0];

        if(cq2.id == "bon")
        {
            q2.parentElement.style.borderColor = "lightgreen";
            ++score;
        }
        else
        {
            q2.parentElement.style.borderColor = "Crimson";
        }
    }
    else
    {
        q2.parentElement.style.borderColor = "Crimson";
    }


//SALE

    var q3 = document.getElementById("q3");

    if (q3.hasChildNodes()) 
    {
        cq3 = q3.childNodes[0];

        if(cq3.id == "sale")
        {
            q3.parentElement.style.borderColor = "lightgreen";
            ++score;
        }
        else
        {
            q3.parentElement.style.borderColor = "Crimson";
        }
    }
    else
    {
        q3.parentElement.style.borderColor = "Crimson";
    }


//SUCRE

    var q4 = document.getElementById("q4");

    if (q4.hasChildNodes()) 
    {
        cq4 = q4.childNodes[0];

        if(cq4.id == "sucre")
        {
            q4.parentElement.style.borderColor = "lightgreen";
            ++score;
        }
        else
        {
            q4.parentElement.style.borderColor = "Crimson";
        }
    }
    else
    {
        q4.parentElement.style.borderColor = "Crimson";
    }

//VIDE

    var q5 = document.getElementById("q5");

    if (q5.hasChildNodes()) 
    {
        cq5 = q5.childNodes[0];

        if(cq5.id == "vide")
        {
            q5.parentElement.style.borderColor = "lightgreen";
            ++score;
        }
        else
        {
            q5.parentElement.style.borderColor = "Crimson";
        }
    }
    else
    {
        q5.parentElement.style.borderColor = "Crimson";
    }

//MAUVAIS

    var q6 = document.getElementById("q6");

    if (q6.hasChildNodes()) 
    {
        cq6 = q6.childNodes[0];

        if(cq6.id == "mauvais")
        {
            q6.parentElement.style.borderColor = "lightgreen";
            ++score;
        }
        else
        {
            q6.parentElement.style.borderColor = "Crimson";
        }
    }
    else
    {
        q6.parentElement.style.borderColor = "Crimson";
    }


//l'assiette

    var q7 = document.getElementById("q7");

    if (q7.hasChildNodes()) 
    {
        cq7 = q7.childNodes[0];

        if(cq7.id == "assiette")
        {
            q7.parentElement.style.borderColor = "lightgreen";
            ++score;
        }
        else
        {
            q7.parentElement.style.borderColor = "Crimson";
        }
    }
    else
    {
        q7.parentElement.style.borderColor = "Crimson";
    }

//tasse

    var q8 = document.getElementById("q8");

    if (q8.hasChildNodes()) 
    {
        cq8 = q8.childNodes[0];

        if(cq8.id == "tasse")
        {
            q8.parentElement.style.borderColor = "lightgreen";
            ++score;
        }
        else
        {
            q8.parentElement.style.borderColor = "Crimson";
        }
    }
    else
    {
        q8.parentElement.style.borderColor = "Crimson";
    }


//verre

    var q9 = document.getElementById("q9");

    if (q9.hasChildNodes()) 
    {
        cq9 = q9.childNodes[0];

        if(cq9.id == "verre")
        {
            q9.parentElement.style.borderColor = "lightgreen";
            ++score;
        }
        else
        {
            q9.parentElement.style.borderColor = "Crimson";
        }
    }
    else
    {
        q9.parentElement.style.borderColor = "Crimson";
    }


//couteau

    var q10 = document.getElementById("q10");

    if (q10.hasChildNodes()) 
    {
        cq10 = q10.childNodes[0];

        if(cq10.id == "couteau")
        {
            q10.parentElement.style.borderColor = "lightgreen";
            ++score;
        }
        else
        {
            q10.parentElement.style.borderColor = "Crimson";
        }
    }
    else
    {
        q10.parentElement.style.borderColor = "Crimson";
    }


//fourchette

    var q11 = document.getElementById("q11");

    if (q11.hasChildNodes()) 
    {
        cq11 = q11.childNodes[0];

        if(cq11.id == "fourchette")
        {
            q11.parentElement.style.borderColor = "lightgreen";
            ++score;
        }
        else
        {
            q11.parentElement.style.borderColor = "Crimson";
        }
    }
    else
    {
        q11.parentElement.style.borderColor = "Crimson";
    }

//cuillère

    var q12 = document.getElementById("q12");

    if (q12.hasChildNodes()) 
    {
        cq12 = q12.childNodes[0];

        if(cq12.id == "cuillere")
        {
            q12.parentElement.style.borderColor = "lightgreen";
            ++score;
        }
        else
        {
            q12.parentElement.style.borderColor = "Crimson";
        }
    }
    else
    {
        q12.parentElement.style.borderColor = "Crimson";
    }


//viande

    var q13 = document.getElementById("q13");

    if (q13.hasChildNodes()) 
    {
        cq13 = q13.childNodes[0];

        if(cq13.id == "viande")
        {
            q13.parentElement.style.borderColor = "lightgreen";
            ++score;
        }
        else
        {
            q13.parentElement.style.borderColor = "Crimson";
        }
    }
    else
    {
        q13.parentElement.style.borderColor = "Crimson";
    }


//poisson

    var q14 = document.getElementById("q14");

    if (q14.hasChildNodes()) 
    {
        cq14 = q14.childNodes[0];

        if(cq14.id == "poisson")
        {
            q14.parentElement.style.borderColor = "lightgreen";
            ++score;
        }
        else
        {
            q14.parentElement.style.borderColor = "Crimson";
        }
    }
    else
    {
        q14.parentElement.style.borderColor = "Crimson";
    }


//fruits

    var q15 = document.getElementById("q15");

    if (q15.hasChildNodes()) 
    {
        cq15 = q15.childNodes[0];

        if(cq15.id == "fruits")
        {
            q15.parentElement.style.borderColor = "lightgreen";
            ++score;
        }
        else
        {
            q15.parentElement.style.borderColor = "Crimson";
        }
    }
    else
    {
        q15.parentElement.style.borderColor = "Crimson";
    }


//legumes

    var q16= document.getElementById("q16");

    if (q16.hasChildNodes()) 
    {
        cq16 = q16.childNodes[0];

        if(cq16.id == "legumes")
        {
            q16.parentElement.style.borderColor = "lightgreen";
            ++score;
        }
        else
        {
            q16.parentElement.style.borderColor = "Crimson";
        }
    }
    else
    {
        q16.parentElement.style.borderColor = "Crimson";
    }

//pain

    var q17 = document.getElementById("q17");

    if (q17.hasChildNodes()) 
    {
        cq17 = q17.childNodes[0];

        if(cq17.id == "pain")
        {
            q17.parentElement.style.borderColor = "lightgreen";
            ++score;
        }
        else
        {
            q17.parentElement.style.borderColor = "Crimson";
        }
    }
    else
    {
        q17.parentElement.style.borderColor = "Crimson";
    }


//eau

    var q18 = document.getElementById("q18");

    if (q18.hasChildNodes()) 
    {
        cq18 = q18.childNodes[0];

        if(cq18.id == "eau")
        {
            q18.parentElement.style.borderColor = "lightgreen";
            ++score;
        }
        else
        {
            q18.parentElement.style.borderColor = "Crimson";
        }
    }
    else
    {
        q18.parentElement.style.borderColor = "Crimson";
    }


//lait

    var q19 = document.getElementById("q19");

    if (q19.hasChildNodes()) 
    {
        cq19 = q19.childNodes[0];

        if(cq19.id == "lait")
        {
            q19.parentElement.style.borderColor = "lightgreen";
            ++score;
        }
        else
        {
            q19.parentElement.style.borderColor = "Crimson";
        }
    }
    else
    {
        q19.parentElement.style.borderColor = "Crimson";
    }

//aimer

    var q20 = document.getElementById("q20");

    if (q20.hasChildNodes()) 
    {
        cq20 = q20.childNodes[0];

        if(cq20.id == "aimer")
        {
            q20.parentElement.style.borderColor = "lightgreen";
            ++score;
        }
        else
        {
            q20.parentElement.style.borderColor = "Crimson";
        }
    }
    else
    {
        q20.parentElement.style.borderColor = "Crimson";
    }

//détester

    var q21 = document.getElementById("q21");

    if (q21.hasChildNodes()) 
    {
        cq21 = q21.childNodes[0];

        if(cq21.id == "detester")
        {
            q21.parentElement.style.borderColor = "lightgreen";
            ++score;
        }
        else
        {
            q21.parentElement.style.borderColor = "Crimson";
        }
    }
    else
    {
        q21.parentElement.style.borderColor = "Crimson";
    }

//boire

    var q22 = document.getElementById("q22");

    if (q22.hasChildNodes()) 
    {
        cq22 = q22.childNodes[0];

        if(cq22.id == "boire")
        {
            q22.parentElement.style.borderColor = "lightgreen";
            ++score;
        }
        else
        {
            q22.parentElement.style.borderColor = "Crimson";
        }
    }
    else
    {
        q22.parentElement.style.borderColor = "Crimson";
    }

//manger

    var q23 = document.getElementById("q23");

    if (q23.hasChildNodes()) 
    {
        cq23 = q23.childNodes[0];

        if(cq23.id == "manger")
        {
            q23.parentElement.style.borderColor = "lightgreen";
            ++score;
        }
        else
        {
            q23.parentElement.style.borderColor = "Crimson";
        }
    }
    else
    {
        q23.parentElement.style.borderColor = "Crimson";
    }

    alert("Ton Score est de : " + score +"/23");    

}

function ShuffleArray(myArr) 
{      
            var l = myArr.length, temp, index;  
            while (l > 0) {  
               index = Math.floor(Math.random() * l);  
               l--;  
               temp = myArr[l];          
               myArr[l] = myArr[index];          
               myArr[index] = temp;      
            }    
            return myArr;    
}

function Offset(el)
{
    var rect = el.getBoundingClientRect(),
    scrollLeft = window.pageXOffset || document.documentElement.scrollLeft,
    scrollTop = window.pageYOffset || document.documentElement.scrollTop;
    return { top: rect.top + scrollTop, left: rect.left + scrollLeft }
}

function ScrollBottom(){
    window.scrollBy({ top: 200, left: 0, behavior: 'smooth'});
}

function ScrollTop(){
    window.scrollBy({ top: -200, left: 0, behavior: 'smooth'});
}
body{
    background: darksalmon;
}

.fill{
    background: lightgrey;
    position: relative;
    height: 4.5vh;
    width: 14.5vh;
    margin: 0.5vh;
    cursor: pointer;
    text-align: center;
    border: 0.3vh grey dashed ;

}

.empty{
    display: inline-block;
    height: 6vh;
    width: 16vh;
    margin: 1vh;
    border : 0.3vh salmon solid;
    background-color: rgb(245, 245, 245);
    vertical-align: bottom;

}

.reponse{

    
}


.reponses{
    position: relative;
    background-color: rgb(245, 245, 245);
    text-align: center;
    max-width: 190vh;
    margin: 0 auto;
    border-radius: 3vh;
    top:2vh;
}

.hold{
    border : solid grey 0.4vh;
    opacity: 1;
}

.hovered{
    background: #f4f4f4;
    border-style: dashed;
}

.invisible{
    display: none;
}

.questions{
    position: relative;
    margin: 0 auto;
    background-color: white;
    top: 5vh;
    text-align: center;
    max-width: 190vh;
    border-radius: 3vh;
}

.question{
    margin: 4vh 2vh;
    padding: 2vh;
    background-color: darkgrey;
    border: black 1vh solid;
    text-align: center;
    max-width: 25vh;
    max-height: 25vh;
    display: inline-block;

}

.text{
    position: absolute;
    height: 4vh;
    width: 14vh;
    margin: 0.6vh 0.25vh;
    font-size: 2.5vh;
    user-select: none;
    
}

.imageContainer{
    display: inline-block;
    width: 21vh;
    height: 21vh;
    border: grey 0.3vh dashed;
    background-color: lightgrey;
    text-align: center;
}

.image{
    display: block;
    max-width: 20vh;
    max-height: 20vh;
    margin: auto auto;
    position: relative;               
    top: 50%;                         
    transform: translate(0, -50%);
}

.btn{
    position: relative;
    display: block;
    width: 20vh;
    height: 5vh;
    top: 6vh;
    left: 50%;                         
    transform: translate(-50%, 0%);
    font-size: 2vh;
    border: 0.3vh black solid;

}

.mainTitle{

    font-size: 4vh;
    text-align: center;
    background: rgb(245, 245, 245);
    padding: 1vh 1vh;
    margin: auto auto;
    border: 0.3vh dashed darkgrey;
    max-width: 80vh;
}
.btnContainer{
    top:1vh;
    position: relative;
    height: 13vh;
}

.menuLink{
    display: inline-block;
    position: relative;
    font-size: 2vw;
    text-decoration:none;
    color: black;
    margin:auto auto;
    top: 50%;                         
    transform: translate(0, -50%);
}

.menuLinkContainer{
    display: inline-block;
    position: fixed;
    width: 7vw;
    height: 3vw;
    background-color: rgb(245, 245, 245);
    border: 0.3vh solid darkgrey;
    top:1vh;
    left:1vh;
    text-align: center;
    z-index: 1;
}

.scrollSpaceBottom{
    display: inline-block;
    position: fixed;
    width: 100vw;
    height: 15vh;
    top:85vh;
}

.scrollSpaceTop{
    display: inline-block;
    position: fixed;
    width: 100vw;
    height: 15vh;
    bottom: 85vh;
}
<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" content="width=device-width, initial-scale=1.0">
    <link rel="stylesheet" href="style.css" />

    <title>Associe les mots et les images</title>
    
</head>
<body>

<div class="menuLinkContainer"><a href="../MainPage/MainPage.html" class="menuLink">Menu</a></div>

<h1 class="mainTitle">Associe les mots et les images</h1>



<div class="reponses">

    <div class="empty reponse">
        <div class="fill" draggable="true" id = "sale"><div class="text">salé</div></div>
    </div>

    <div class="empty reponse">
        <div class="fill" draggable="true" id = "plein"><div class="text">plein</div></div>
    </div>

    <div class="empty reponse">
        <div class="fill" draggable="true" id = "sucre"><div class="text">sucré</div></div>
    </div>

    <div class="empty reponse">
        <div class="fill" draggable="true" id = "bon"><div class="text">bon</div></div>
    </div>

    <div class="empty reponse">
            <div class="fill" draggable="true" id = "vide"><div class="text">vide</div></div>
    </div>

    <div class="empty reponse">
            <div class="fill" draggable="true" id = "mauvais"><div class="text">mauvais</div></div>
    </div>

    <div class="empty reponse">
            <div class="fill" draggable="true" id = "assiette"><div class="text">l'assiette</div></div>
    </div>

    <div class="empty reponse">
            <div class="fill" draggable="true" id = "tasse"><div class="text">la tasse</div></div>
    </div>

    <div class="empty reponse">
            <div class="fill" draggable="true" id = "verre"><div class="text">le verre</div></div>
    </div>

    <div class="empty reponse">
            <div class="fill" draggable="true" id = "couteau"><div class="text">le couteau</div></div>
    </div>

    <div class="empty reponse">
            <div class="fill" draggable="true" id = "fourchette"><div class="text">la fourchette</div></div>
    </div>

    <div class="empty reponse">
            <div class="fill" draggable="true" id = "cuillere"><div class="text">la cuillère</div></div>
    </div>

    <div class="empty reponse">
            <div class="fill" draggable="true" id = "viande"><div class="text">la viande</div></div>
    </div>

    <div class="empty reponse">
            <div class="fill" draggable="true" id = "poisson"><div class="text">le poisson</div></div>
    </div>

    <div class="empty reponse">
            <div class="fill" draggable="true" id = "fruits"><div class="text">les fruits</div></div>
    </div>

    <div class="empty reponse">
            <div class="fill" draggable="true" id = "legumes"><div class="text">les légumes</div></div>
    </div>

    <div class="empty reponse">
            <div class="fill" draggable="true" id = "pain"><div class="text">le pain</div></div>
    </div>

    <div class="empty reponse">
            <div class="fill" draggable="true" id = "eau"><div class="text">l'eau</div></div>
    </div>

    <div class="empty reponse">
            <div class="fill" draggable="true" id = "lait"><div class="text">le lait</div></div>
    </div>

    <div class="empty reponse">
            <div class="fill" draggable="true" id = "aimer"><div class="text">aimer</div></div>
    </div>

    <div class="empty reponse">
            <div class="fill" draggable="true" id = "detester"><div class="text">détester</div></div>
    </div>

    <div class="empty reponse">
            <div class="fill" draggable="true" id = "boire"><div class="text">boire</div></div>
    </div>

    <div class="empty reponse">
            <div class="fill" draggable="true" id = "manger"><div class="text">manger</div></div>
    </div>

</div>


<div class="questions" id="questions">
    <div class="question" id="ques1">
        <div class="imageContainer"><img src="./img/plein.png" class="image"></div>
        <div class="empty" id="q1"></div>
    </div>

    <div class="question" id="ques2">
        <div class="imageContainer"><img src="./img/bon.png" class="image"></div>
        <div class="empty" id="q2"></div>
    </div>

    <div class="question" id="ques3">
        <div class="imageContainer"><img src="./img/sale.png" class="image"></div>
        <div class="empty" id="q3"></div>
    </div>

    <div class="question" id="ques4">
        <div class="imageContainer"><img src="./img/sucre.png" class="image"></div>
        <div class="empty" id="q4"></div>
    </div>

    <div class="question" id="ques5">
        <div class="imageContainer"><img src="./img/vide.png" class="image"></div>
        <div class="empty" id="q5"></div>
    </div>

    <div class="question" id="ques6">
        <div class="imageContainer"><img src="./img/mauvais.png" class="image"></div>
        <div class="empty" id="q6"></div>
    </div>

    <div class="question" id="ques7">
        <div class="imageContainer"><img src="./img/assiette.png" class="image"></div>
        <div class="empty" id="q7"></div>
    </div>

    <div class="question" id="ques8">
        <div class="imageContainer"><img src="./img/tasse.png" class="image"></div>
        <div class="empty" id="q8"></div>
    </div>

    <div class="question" id="ques9">
        <div class="imageContainer"><img src="./img/verre.png" class="image"></div>
        <div class="empty" id="q9"></div>
    </div>

    <div class="question" id="ques10">
        <div class="imageContainer"><img src="./img/couteau.png" class="image"></div>
        <div class="empty" id="q10"></div>
    </div>

    <div class="question" id="ques11">
        <div class="imageContainer"><img src="./img/fourchette.png" class="image"></div>
        <div class="empty" id="q11"></div>
    </div>

    <div class="question" id="ques12">
        <div class="imageContainer"><img src="./img/cuillere.png" class="image"></div>
        <div class="empty" id="q12"></div>
    </div>

    <div class="question" id="ques13">
        <div class="imageContainer"><img src="./img/viande.png" class="image"></div>
        <div class="empty" id="q13"></div>
    </div>

    <div class="question" id="ques14">
        <div class="imageContainer"><img src="./img/poisson.png" class="image"></div>
        <div class="empty" id="q14"></div>
    </div>

    <div class="question" id="ques15">
        <div class="imageContainer"><img src="./img/fruit.png" class="image"></div>
        <div class="empty" id="q15"></div>
    </div>

    <div class="question" id="ques16">
        <div class="imageContainer"><img src="./img/legume.png" class="image"></div>
        <div class="empty" id="q16"></div>
    </div>

    <div class="question" id="ques17">
        <div class="imageContainer"><img src="./img/pain.png" class="image"></div>
        <div class="empty" id="q17"></div>
    </div>

    <div class="question" id="ques18">
        <div class="imageContainer"><img src="./img/eau.png" class="image"></div>
        <div class="empty" id="q18"></div>
    </div>

    <div class="question" id="ques19">
        <div class="imageContainer"><img src="./img/lait.png" class="image"></div>
        <div class="empty" id="q19"></div>
    </div>

    <div class="question" id="ques20">
        <div class="imageContainer"><img src="./img/aimer.png" class="image"></div>
        <div class="empty" id="q20"></div>
    </div>

    <div class="question" id="ques21">
        <div class="imageContainer"><img src="./img/detester.png" class="image"></div>
        <div class="empty" id="q21"></div>
    </div>

    <div class="question" id="ques22">
        <div class="imageContainer"><img src="./img/boire.png" class="image"></div>
        <div class="empty" id="q22"></div>
    </div>

    <div class="question" id="ques23">
        <div class="imageContainer"><img src="./img/manger.png" class="image"></div>
        <div class="empty" id="q23"></div>
    </div>
</div>

<div id="scrolls">
    <div class="scrollSpaceTop" id="scrollSpaceTop" ondragover="ScrollTop()"></div>
    <div class="scrollSpaceBottom" id="scrollSpaceBottom" ondragover="ScrollBottom()"></div>
</div>

 <div class="btnContainer"><input type="button" value="Valider les réponses" onclick="Validate()" class="btn"></div>
     

<script src="DragnDrop.js"></script>
</body>
</html>


Solution

  • One approach will be to set a data attribute to responses containers like:

    <div data-child="salé" class="empty reponse">
      <div class="fill" data-parent="salé" draggable="true" id = "sale"><div class="text">salé</div></div>
    </div>
    

    Each time you drop an element, you remove the existing one from the answers and reattach back in his possible responses, and attach the new one. This way you know where to attach the removed element back in his place using document selectors.