Drag&Drop - Bilder wieder in Ausgangslage zurück

at0m

Grünschnabel
Hallo zusammen!

Ich habe folgendes Skript im Netz gefunden, mit dem ich eine Drag&Drop-Funktion von Bildern realisiert habe.

skript.js
Code:
// Erlaubt es dem Objekt ziehbar/bewegbar zu sein
function allowDrop(ev) {
    ev.preventDefault();
}
        
// Funktion ist zuständig für das Ziehen (Drag)
function drag(ev) {
    ev.dataTransfer.setData("content", ev.target.id);
}
        
// Funktion ist zuständig für das Loslassen (Drop)
function drop(ev) {
    ev.preventDefault();
    // Bild in der Variable "image" zwischenspeichern
    var image = ev.dataTransfer.getData("content");
    // Bild in einen der Kästen verschieben
    ev.target.appendChild(document.getElementById(image));
    
    
    if(image == "4") {
        alert("Ihre Antwort ist richtig!");       
    } else {
        alert('Ihre Antwort ist leider falsch. Bitte klicken Sie auf "Neu Laden" und versuchen Sie es noch mal.');
    }
}

Der entsprechende HTML-Code sieht wie folgt aus:

index.html
HTML:
<!DOCTYPE html>
<html lang="de">
  <head>
    <meta charset="utf-8" />
    <title>Title</title>
    
    <style type="text/css">
        #antwort_box {
            width: 190px;
            height: 30px;
            border: 1px dashed #424242;
            margin-bottom: 30px;
            margin-left: 100px;
        }
        .funktionen_box {
            float: left;
            width: 190px;
            height: 30px;
            margin-right: 5px;
            margin-bottom: 5px;
            border: 1px solid gray;
        }
    </style>
    <script type="text/javascript" src="script.js"></script>
  </head>
  <body>
  
      <div id="antwort_box" name="antwort" ondrop="drop(event)" ondragover="allowDrop(event)">
      </div>
  
      <div class="funktionen_box" ondrop="drop(event)">
          <img src="1.png" alt="bild" id="1" draggable="true" ondragstart="drag(event)"/>
      </div>
      <div class="funktionen_box" ondrop="drop(event)">
          <img src="2.png" alt="bild" id="2" draggable="true" ondragstart="drag(event)"/>
      </div>
      <div class="funktionen_box" ondrop="drop(event)">
          <img src="3.png" alt="bild" id="3" draggable="true" ondragstart="drag(event)"/>
      </div>
      <div class="funktionen_box" ondrop="drop(event)">
          <img src="4.png" alt="bild" id="4" draggable="true" ondragstart="drag(event)"/>
      </div>
      <div class="funktionen_box" ondrop="drop(event)">
          <img src="5.png" alt="bild" id="5" draggable="true" ondragstart="drag(event)"/>
      </div>      
  
  </body>
</html>

Das funktioniert auch so weit. Nur möchte ich auch folgendes realisieren. Wenn bereits ein Bild in den Antwort-Container mit der id "antwort_box" gezogen wurde, soll es nicht möglich sein ein anderes Bild hinenzubewegen, sodass sich diese überlagern. Stattdessen soll es in die Box zurück wandern, in der es war.

Kann mir jemand einen Tipp geben, wie man das hinbekommt?


Gruß
 
Prüfe doch innerhalb der Drag-Funktion ob bereits ein Bild vorhanden ist oder nicht.

Wenn es noch kein Bild gibt führst du die Funktion aus, wenn bereits ein Bild vorhanden ist gibst du einen Hinweis aus und beendest die Funktion mit "return false;"
 
Aber kann man es schon in Drag prüfen? Ich habe da an Drop gedacht und die Funktion wie folgt umgebaut:
Code:
// Erlaubt es dem Objekt ziehbar/bewegbar zu sein
function allowDrop(ev) {
    ev.preventDefault();
}
        
// Funktion ist zuständig für das Ziehen (Drag)
function drag(ev) {
    ev.dataTransfer.setData("content", ev.target.id);
}
        
// Funktion ist zuständig für das Loslassen (Drop)
function drop(ev) {
    ev.preventDefault();
    // Bild in der Variable "image" zwischenspeichern
    var image = ev.dataTransfer.getData("content");
    
    if (ev.target == "") {
        // Bild in einen der Kästen verschieben
        ev.target.appendChild(document.getElementById(image));
        
        if(image == "4") {
            alert("Ihre Antwort ist richtig!");       
        } else {
            alert('Ihre Antwort ist leider falsch. Bitte klicken Sie auf "Neu Laden" und versuchen Sie es noch mal.');
        }
    }
}

Das funktioniert natürlich nicht. Aber wie könnte man das umsetzen? Mir fehlt da irgendwie der Ansatz. Könntest du das vielleicht am Code-Bsiepiel zeigen?
 
Habe zum Prüfen ob ein Bild abgelegt wurde die zusätzliche Variable "check" mit den Wert 0 angelegt. So bald ein Bild in die Antwortbox gelegt wird, wird dieser Variablen der Wert 1 zugewiesen.

Beim Versuch ein Bild zu verschieben wird der Wert dieser Variablen geprüft und entsprechend gehandelt.


Javascript:
// Diese Variable wird auf 1 gesetzt wenn ein Bild abgelegt wurde
var check = 0;

// Erlaubt es dem Objekt ziehbar/bewegbar zu sein
function allowDrop(ev) {
    ev.preventDefault();
}

// Funktion ist zuständig für das Ziehen (Drag)
function drag(ev) {
// Hier wird der Inhalt der Variablen geprüft und wenn bereits ein Bild vorhanden ist
// eine Meldung ausgegeben und die Funktion verlassen
	if(check == 1){
		alert("Das geht nicht!");
		return false;
	}
    ev.dataTransfer.setData("content", ev.target.id);
}

// Funktion ist zuständig für das Loslassen (Drop)
function drop(ev) {
    ev.preventDefault();
    // Bild in der Variable "image" zwischenspeichern
    var image = ev.dataTransfer.getData("content");
    // Bild in einen der Kästen verschieben
    ev.target.appendChild(document.getElementById(image));

// Wenn ein Bild abgelegt wurde, wird die Variabe "check" auf 1 gesetzt
	check = 1;

    if(image == "4") {
        alert("Ihre Antwort ist richtig!");
    } else {
        alert('Ihre Antwort ist leider falsch. Bitte klicken Sie auf "Neu Laden" und versuchen Sie es noch mal.');
    }
}
 
Das ist super! Funktioniert wunderbar! Danke!

Wie sähe so ein Skript aus, wenn man z.B. mehrere Kästen hat, in die man auch mehrere Antworten bewegen kann. Also eine Art Zuordnung.

Beispiel:
HTML:
<div id="antwort_ja_1" name="antwort_ja_1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div id="antwort_ja_2" name="antwort_ja_2" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div id="antwort_ja_3" name="antwort_ja_3" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div id="antwort_nein_1" name="antwort_nein_1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div id="antwort_nein_2" name="antwort_nein_2" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div id="antwort_nein_3" name="antwort_nein_3" ondrop="drop(event)" ondragover="allowDrop(event)"></div>

<br><br><br><br><br>

<div class="antwort_box" ondrop="drop(event)">
  <img src="1.png" alt="1" name="1" id="1" draggable="true" ondragstart="drag(event)"/>
</div>
<div class="antwort_box" ondrop="drop(event)">
  <img src="2.png" alt="2" name="2" id="2" draggable="true" ondragstart="drag(event)"/>
</div>
<div class="antwort_box" ondrop="drop(event)">
  <img src="3.png" alt="3" name="3" id="3" draggable="true" ondragstart="drag(event)"/>
</div>
<div class="antwort_box" ondrop="drop(event)">
  <img src="4.png" alt="4" name="4" id="4" draggable="true" ondragstart="drag(event)"/>
</div>
<div class="antwort_box" ondrop="drop(event)">
  <img src="5.png" alt="5" name="5" id="5" draggable="true" ondragstart="drag(event)"/>
</div>
<div class="antwort_box" ondrop="drop(event)">
  <img src="6.png" alt="6" name="6" id="6" draggable="true" ondragstart="drag(event)"/>
</div>

<script type="text/javascript" src="DaD_script.js"></script>

<p><input type="button" onclick="auswerten()" value="Auswerten"/></p>


Und das DaD_script.js würde dann so aussehen:

Code:
// Erlaubt es dem Objekt ziehbar/bewegbar zu sein
function allowDrop(ev) {
    ev.preventDefault();
}
        
// Funktion ist zuständig für das Ziehen (Drag)
function drag(ev) {
    ev.dataTransfer.setData("content", ev.target.id);
}
        
// Funktion ist zuständig für das Loslassen (Drop)
function drop(ev) {
    ev.preventDefault();
    // Bild in der Variable "image" zwischenspeichern
    var image = ev.dataTransfer.getData("content");
    // Bild in einen der Kästen verscheieben
    ev.target.appendChild(document.getElementById(image));
}


Erst nachdem man auf den Button "auswerten" drückt, wird ausgewertet. Beim Bewegen der Bilder sollte es aber nicht möglich sein Bilder aufeinander zu stapeln.

Die Funktion auswerten() sähe dann wie folgt aus:

Code:
function auswerten() {
    var ja_1 = document.getElementById("antwort_ja_1").getElementsByTagName("img")[0];
    var ja_2 = document.getElementById("antwort_ja_2").getElementsByTagName("img")[0];
    var ja_3 = document.getElementById("antwort_ja_3").getElementsByTagName("img")[0];
    var nein_1 = document.getElementById("antwort_nein_1").getElementsByTagName("img")[0];
    var nein_2 = document.getElementById("antwort_nein_2").getElementsByTagName("img")[0];
    var nein_3 = document.getElementById("antwort_nein_3").getElementsByTagName("img")[0];
    if ((ja_1.id == "2" || ja_1.id == "4" || ja_1.id == "6") &&
        (ja_2.id == "2" || ja_2.id == "4" || ja_2.id == "6") &&
        (ja_3.id == "2" || ja_3.id == "4" || ja_3.id == "6") &&
        (nein_1.id == "1" || nein_1.id == "3" || nein_1.id == "5") &&
        (nein_2.id == "1" || nein_2.id == "3" || nein_2.id == "5") &&
        (nein_3.id == "1" || nein_3.id == "3" || nein_3.id == "5")) {
        alert("Ihre Antwort ist richtig!");
    } else {
        alert("Ihre Antwort ist leider falsch. Bitte klicken Sie auf Neu Laden und versuchen Sie es erneut.");
    }
}


Würde man die Überprüfung dann in DaD_script.js abgelegen? In der drop-Funktion? Wie könnte man das genau umsetzen?
 
Sorry aber ich verstehe nicht so ganz wie der Fragebogen jetzt aussehen soll.

Frage 1:
[ ] - Antwort A
[ ] - Antwort B
[ ] - Antwort C

Frage 2:
[ ] - Antwort A
[ ] - Antwort B
[ ] - Antwort C
[ ] - Antwort D

Frage 3:
[ ] - Antwort A
[ ] - Antwort B

Und jetzt soll für jede Frage eine Antwort ausgewählt werden können!?
 
Sorry, ich habe natürlich völlig vergessen aufzuschreiben, welche Aufgabe ich mir ausgedacht habt. Sie würde in dem letzten von mir aufgeführten Beispiel wie folgt lauten:
Bitte ordnen Sie zu, welche der Zahlen durch zwei teilbar ist und welche nicht (GRÜN: Durch 2 teilbar | ROT: Nicht durch zwei teilbar).

az4x7wgf.png

So würde das dann mit dem von mir zuletzt genannten Code in etwa aussehen. Nun wäre es ja eigentlich möglich die "2" in die erste grüne Box zu bewegen und anschließend die "4" in die gleiche Box. Die "4" würde dann die "2" überschreiben. Was ich nun umzusetzen versuche ist, dass die "4" in Ihre Ausgangsbox verschwindet, wenn vorher bereits eine andere Zahl in der Zielbox abgelegt wurde.

Dafür müsste man die Funktion drop() in DaD_script.js verändern, denke ich. Wie, ist mir aber schleierhaft. Weißt du, wie man das umsetzen könnte?
 
Hier mal mein Vorschlag:

HTML:
<!DOCTYPE html>
<html lang="de">
  <head>
    <meta charset="utf-8" />
    <title>-</title>

    <style type="text/css">
        .antwort_box {
            width: 190px;
            height: 30px;
            border: 1px dashed #424242;
            margin-bottom: 30px;
            margin-left: 20px;
            float: left;
        }
        .funktionen_box {
            width: 190px;
            height: 30px;
            border: 1px solid gray;
            margin-left: 20px;
            margin-bottom: 50px;
            float: left;
        }
    </style>
    <script type="text/javascript" src="script.js"></script>
  </head>
  <body>

<div class="antwort_box" style="background-color: #008000;" id="antwort1" name="antwort1" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div class="antwort_box" style="background-color: #008000;" id="antwort2" name="antwort2" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div class="antwort_box" style="background-color: #008000;" id="antwort3" name="antwort3" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div class="antwort_box" style="background-color: #FF0000;" id="antwort4" name="antwort4" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div class="antwort_box" style="background-color: #FF0000;" id="antwort5" name="antwort5" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div class="antwort_box" style="background-color: #FF0000;" id="antwort6" name="antwort6" ondrop="drop(event)" ondragover="allowDrop(event)"></div>
<div style="clear:both;">&nbsp;</div>
<div class="funktionen_box" ondrop="drop(event)">
	<img src="1.png" alt="bild" id="1" draggable="true" ondragstart="drag(event)"/>
</div>
<div class="funktionen_box" ondrop="drop(event)">
	<img src="2.png" alt="bild" id="2" draggable="true" ondragstart="drag(event)"/>
</div>
<div class="funktionen_box" ondrop="drop(event)">
	<img src="3.png" alt="bild" id="3" draggable="true" ondragstart="drag(event)"/>
</div>
<div class="funktionen_box" ondrop="drop(event)">
	<img src="4.png" alt="bild" id="4" draggable="true" ondragstart="drag(event)"/>
</div>
<div class="funktionen_box" ondrop="drop(event)">
	<img src="5.png" alt="bild" id="5" draggable="true" ondragstart="drag(event)"/>
</div>
<div class="funktionen_box" ondrop="drop(event)">
	<img src="6.png" alt="bild" id="6" draggable="true" ondragstart="drag(event)"/>
</div>
<div style="clear:both;">&nbsp;</div>
<a href="#" onclick="auswerten();">Auswerten</a>
</body>
</html>

Javascript:
function allowDrop(ev) {
    ev.preventDefault();
}

function drag(ev) {
    ev.dataTransfer.setData("content", ev.target.id);
}

function drop(ev) {
    ev.preventDefault();
	if (document.getElementById(ev.target.id).hasChildNodes()) {
		return false;
	}
	switch (ev.target.id) {
		case "antwort1":    break;
		case "antwort2":    break;
		case "antwort3":    break;
		case "antwort4":    break;
		case "antwort5":    break;
		case "antwort6":    break;
		default:            return false;
							break;
	}
    var image = ev.dataTransfer.getData("content");
    ev.target.appendChild(document.getElementById(image));
}
function auswerten() {
ok = 0;
for (a = 1; a <= 3; a++) {
	switch (document.getElementById("antwort" + a).firstChild.id) {
		case "2":   ok++;
					break;
		case "4":   ok++;
					break;
		case "6":	ok++;
					break;
		default:	ok = 0;
					break;
	}
}
if (ok == 3) {
	alert ("Alles richtig.");
} else {
	alert ("Stimmt nicht.");
}
}

Im drop-Ereignis wird nun geprüft ob bereits ein Bild im DIV-Container abgelegt ist oder nicht. Weiter wird geprüft ob das Bild in eine der Antwort Boxen abgelegt wird (sonst wäre es möglich ein Bild auf ein anderes Bild zu legen). Ist dies der Fall wird die Funktion verlassen und dadurch das Drag & Drop abgebrochen.
 
Das funktioniert echt wunderbar! Herzlichen Dank!

Eine kleine Frage habe ich aber noch. :)
Und zwar wird bei mir der Inhalt eines divs, in dem die Frage steht, mit AJAX, in den folgenden Code geladen:

HTML:
        <div id="aufg_5_content">
            <!-- AJAX: Lädt aus der Datei kategorien/kategorie_4/aufg_5/aufg_5.php -->
        </div>
        
        <script src="../../skripte/jquery-1.8.3.min.js" type="text/javascript"></script>
        <script src="../../skripte/aufg_5_ajax.js" type="text/javascript"></script>
        
        <br/>
                
        <p id="aufg_5_button"><input type="button" value="Neu Laden"/></p>
        
        <p><input type="button" onclick="auswertenAufg5()" value="Auswerten"/></p>
        <script type="text/javascript" src="../../skripte/aufg_5_auswerten.js" ></script>


Das AJAX-Skript sieht folgendermaßen aus:

Code:
$(document).ready(function() {
    $('#aufg_5_content').load('aufg_5/aufg_5.php');
    
    $('p#aufg_5_button input').click(function() {
        $('#aufg_5_content').load('aufg_5/aufg_5.php');
    })
});


Das Problem ist, dass das Drag&Drop-Skript zwar funktioniert, die Eigenschaft, dass Bilder nicht übereinander gelegt werden können, funktioniert aber nur, wenn man ein mal auf den Button "Neu Laden" geklickt hat und die Aufgabe mittels AJAX neu reingeladen wird. Woran könnte das wohl liegen?
 
Kann man sich den Fragebogen irgendwo schon anschauen?

Ich kann nicht so wirklich nachvollziehen wann alles klappt und wann nicht. Funktioniert es nicht wenn die Seite das erste Mal geladen wird? "Neu geladen wird die Seite doch immer durch einen Klick auf "Neu laden".
 
Zurück