Moribundus: DIV-Element bei Drag and Drop klonen

Hallo Zusammen,

ich habe mir auf meiner lokalen Site ein paar Drag and Drop Elemente, mithilfe dieser Lösung HTML5 Drag and Drop gebastelt.

Ich wollte diese DIV-Elemente in eine Tabelle verschiebung um eine Aufgabenverteilung optisch sichtbar zu machen.

Nun möchte ich mir einen quasi "undendlichen Vorrat" an DIV-Elementen basteln, indem ich diese bei start das Vorgangs klone, da hab ich hier schon etwas entsprechendes gefunden <http://de.selfhtml.org/javascript/objekte/node.htm#clone_node@title=SELFHTML CloneNode>.

Nur bin ich gerade erst beim einlesen in Javascript und hab bisher eher mit PHP/Mysql gearbeitet.

Hat jemand eine Idee wie ich die Klonlösung bei dem Drag and Drop Beispiel anwenden könnte?

  1. Hallo,

    ich weiß micht genau, was du vor hast.
    Wozu brauchst du die vielen Divs und was ist dir an cloneNode unklar?

    Viele Grüße
    Siri

    1. Hallo :-9

      ich weiß micht genau, was du vor hast.

      also wie schon beschrieben woltle ich eine Aufgabenverteilung in einer Tabelle sichbar machen, ich werde später mehrere verschiedene DIV-Boxen verwenden und ich möchte wenn ich ein DIV-Element sozusagen aus meinen "Pool" ziehe, das es beim Drag and Drop kopiert statt nur verschoben wird. heißt das das DIV-Element im Pool erhalten bleibt und ich trotzdem eins in meine Tabelle setzen kann.

      Wozu brauchst du die vielen Divs und was ist dir an cloneNode unklar?

      an CloneNode an sich ist mir nichts unklar, das Beispiel was heir zu finden ist ist ja selbsterklärend aber wie ich es am besten in meine Lösung implementiere, da fehlt mir der Ansatz, weil ich wie gesagt im Bereich Javascript noch eher ein blutiger Anfänger bin.

      Beste Grüße

      1. Hallo,

        hier:

        function drop(ev)
        {
        ev.preventDefault();
        var data=ev.dataTransfer.getData("Text");
        ev.target.appendChild(document.getElementById(data));
        }

        clonst du das Element und hängst es mit appendChild an dein target. Dadurch bleibt das original Element erhalten:

        sourceElement = document.getElementById(data);
        sourceElementClone = sourceElement.cloneNode("true");
        ev.target.appendChild(sourceElementClone);

        Viele Grüße
        Siri

        1. Hallo Vielen dank erstmal,

          clonst du das Element und hängst es mit appendChild an dein target. Dadurch bleibt das original Element erhalten:

          sourceElement = document.getElementById(data);
          sourceElementClone = sourceElement.cloneNode("true");

          das war mir soweit klar

          ev.target.appendChild(sourceElementClone);

          aber eben das anhängen wollte ich ja nicht, ich wollte schon das das DIV in den Zielbereich gezogen wird aber das im Quellbereich erhalten wird, damit ich von dort wieder ein DIV in einen anderen Zielbereich ziehen kann, verstehst du?

          In deiner Lösung habe ich dann zwei DIV im Zielbereich...

          1. Hallo,

            In deiner Lösung habe ich dann zwei DIV im Zielbereich...

            Ääääh... nein!
            Wenn du
            ev.target.appendChild(document.getElementById(data));
            weg lässt, dann hast du nur das geclonte Element im Zielbereich.

            Viele Grüße
            Siri

            1. Ääääh... nein!
              Wenn du
              ev.target.appendChild(document.getElementById(data));
              weg lässt, dann hast du nur das geclonte Element im Zielbereich.

              Ah stimmt, im Kreis gedacht,

              Klasse vielen Dank!

              1. noch eine kurze Frage, kann man irgendwie vermeiden das das Target mehr als ein DIV-Element aufnimmt, das heißt irgendwie prüfen ob schon eines Vorhanden ist und es dann verweigern bzw. mit dem neuen ersetzen?

                1. Moin,

                  noch eine kurze Frage, kann man irgendwie vermeiden das das Target mehr als ein DIV-Element aufnimmt, das heißt irgendwie prüfen ob schon eines Vorhanden ist und es dann verweigern bzw. mit dem neuen ersetzen?

                  Ich fand das interessant und habs mal nachgebaut:
                  Beispiel

                  Die Überprüfung, ob schon ein Element im Zieldiv ist sieht bei mir folgendermaßen aus:

                  function drop(ev)  
                  	{  
                  		ev.preventDefault();  
                  		if(ev.target.tagName == "DIV" && ev.target.firstChild == null) { ... }  
                  	}
                  

                  Grüße Marco

                  1. Moin

                    Die Überprüfung, ob schon ein Element im Zieldiv ist sieht bei mir folgendermaßen aus:

                    function drop(ev)

                    {
                    ev.preventDefault();
                    if(ev.target.tagName == "DIV" && ev.target.firstChild == null) { ... }
                    }

                    
                    >   
                      
                    ah ok, nur mithilfe einer IF-Anweisung, die ist auch überall gleich...  
                      
                    wobei ich überlege da wäre ich doch mit einer CASE fast besser dran um nicht nur auf DIV zu prüfen und auch verschiedene alerts auszugeben, je nach Fall, aber ob ich das dann so wie du mit dem target.firstchild verknüpfen kann, müsste ja eigentlich funktionieren?  
                      
                    cool dein Nachgebautes, musste kurz schmunzeln
                    
                    1. Moin,

                      wobei ich überlege da wäre ich doch mit einer CASE fast besser dran um nicht nur auf DIV zu prüfen und auch verschiedene alerts auszugeben, je nach Fall, aber ob ich das dann so wie du mit dem target.firstchild verknüpfen kann, müsste ja eigentlich funktionieren?

                      Das ist richtig. Ich mach das ja nur der Einfachheit halber, UND weil ich keine anderen Elemente habe. Sonst würde ich auf die Klasse prüfen (die bei den Ziel-Divs "destdiv" ist). Die Prüfung auf ev.target.firstChild == null mache ich nur, damit man nich mehrere Items in einen Div schmeißen kann.

                      cool dein Nachgebautes, musste kurz schmunzeln

                      Es gibt schöneres, als für den Garten reichts :-P

                      Grüße Marco

                      1. Das ist richtig. Ich mach das ja nur der Einfachheit halber, UND weil ich keine anderen Elemente habe. Sonst würde ich auf die Klasse prüfen (die bei den Ziel-Divs "destdiv" ist).

                        Auf die Klasse prüfen? Wäre auch eine Möglichkeit und die jeweils saubere Lösung, aber wenn ich das für mehrer verschiedene DIV-Elemente anwenden will, die per CSS verschieden formatiert sind und somit unterschiedliche Klassen haben, wird es auch wieder unsauber... das muss ich mir wohl noch was einfallen lassen...

                        Die Prüfung auf ev.target.firstChild == null mache ich nur, damit man nich mehrere Items in einen Div schmeißen kann.

                        ja das ist schon Sinnvoll, hab ich garnicht drüber nachgedacht...

                        1. Moin,

                          Auf die Klasse prüfen? Wäre auch eine Möglichkeit und die jeweils saubere Lösung, aber wenn ich das für mehrer verschiedene DIV-Elemente anwenden will, die per CSS verschieden formatiert sind und somit unterschiedliche Klassen haben, wird es auch wieder unsauber... das muss ich mir wohl noch was einfallen lassen...

                          Eine Klasse ist nichts zwangsläufig CSS-abhängiges. Du kannst auch eine Klasse nicht formatieren. Beispiel:

                          <div id="div1" class="foo bar drop">...</div>  
                          <div id="asdf" class="foo drop">...</div>
                          

                          Die Klassen foo und bar kannst du mit CSS formatieren, und die Klasse drop nutzen, um zu prüfen, ob etwas dort abgelegt werden kann.

                          Beachte, dass die classList eines Elements ein Array ist, und deine Klasse nicht immer das erste Element sein muss, wie in meiner Abfrage.

                          Grüße Marco

                          1. Auf die Klasse prüfen? Wäre auch eine Möglichkeit und die jeweils saubere Lösung, aber wenn ich das für mehrer verschiedene DIV-Elemente anwenden will, die per CSS verschieden formatiert sind und somit unterschiedliche Klassen haben, wird es auch wieder unsauber... das muss ich mir wohl noch was einfallen lassen...

                            Eine Klasse ist nichts zwangsläufig CSS-abhängiges. Du kannst auch eine Klasse nicht formatieren. Beispiel:

                            <div id="div1" class="foo bar drop">...</div>

                            <div id="asdf" class="foo drop">...</div>

                            
                            >   
                            > Die Klassen `foo`{:.language-css} und `bar`{:.language-css} kannst du mit CSS formatieren, und die Klasse drop nutzen, um zu prüfen, ob etwas dort abgelegt werden kann.  
                            >   
                            > Beachte, dass die classList eines Elements ein Array ist, und deine Klasse nicht immer das erste Element sein muss, wie in meiner Abfrage.  
                              
                              
                            Moin,  
                              
                            stimmt, das hab ich schon mal gesehen, mehrere Klassen in einem Element, wusste aber nicht so recht etwas damit anzufangen, jetzt ergibt das natürlich mehr Sinn , wirft aber auch umso mehr fragen auf...  
                              
                            Dann ist es auf jedenfall besser das über die Klasse zu filtern, Vielen Dank dafür!  
                              
                            Heute früh hab ich ein td-element drag and drop fähig gemacht, um es als Ziel zu verwenden und wollte deine Lösung ebenfalls dafür nutzen, allerdings fiel mir dann auf die fristchild-Bedingung wird in dem Zusammenhang nicht funktionieren, entweder kann ich gar kein div in der td ablegen oder mehrere, was ich ja vermeiden wollte, hast du eine Idee wie ich das lösen könnte?
                            
                            1. Hallo,

                              Heute früh hab ich ein td-element drag and drop fähig gemacht, um es als Ziel zu verwenden und wollte deine Lösung ebenfalls dafür nutzen, allerdings fiel mir dann auf die fristchild-Bedingung wird in dem Zusammenhang nicht funktionieren

                              firstChild muss nicht zwangsläufig ein "HTML-Element" sein. Schau dir mal nodeType an.

                              Viele Grüße
                              Siri

                              1. firstChild muss nicht zwangsläufig ein "HTML-Element" sein. Schau dir mal nodeType an.

                                ok, habe ich, liege damit richtig wenn es aber in dieser Lösung ein Elementknoten ist?

                                1. ok, habe ich, liege damit richtig wenn es aber in dieser Lösung ein Elementknoten ist?

                                  Das kommt ja darauf an, was in der Tabellenzelle schon drin steht, du kannst dir ja den nodeType von firstChild ausgeben lassen.

                                  Heute früh hab ich ein td-element drag and drop fähig gemacht, um es als Ziel zu verwenden und wollte deine Lösung ebenfalls dafür nutzen, allerdings fiel mir dann auf die fristchild-Bedingung wird in dem Zusammenhang nicht funktionieren

                                  Gibt es eine Fehlermeldung?

                                  Viele Grüße
                                  Siri

                                  1. Das kommt ja darauf an, was in der Tabellenzelle schon drin steht, du kannst dir ja den nodeType von firstChild ausgeben lassen.

                                    bisher steht nichts drin, wie kann ich den ausgeben?

                                    Gibt es eine Fehlermeldung?

                                    nein, lasse ich && ev.target.firstChild == null
                                    von if(ev.target.tagName == "TD" && ev.target.firstChild == null) weg dann geht das Drag and Drop aber ich kann mehrere DIV-Elemente in die TD einfügen, lasse ich es stehen geht garnichts...

                                    1. Moin,

                                      lasse ich es stehen geht garnichts...

                                      Dann steht wahrscheinlich zumindest ein Leerzeichen drin. Ich habe mein Beispiel mal abgeändert, so wie hier beschrieben.

                                      Grüße Marco

                                      1. moin,

                                        Dann steht wahrscheinlich zumindest ein Leerzeichen drin.

                                        das hab ich auch gedacht und bin dann auch auf die Lösung gekommen,
                                        es war kein leerzeichen aber ein Zeilenumbruch

                                        ich habe dann einfach mal

                                        <td ondrop="drop(event)" ondragover="allowDrop(event)">  
                                        </td>
                                        

                                        in
                                        <td ondrop="drop(event)" ondragover="allowDrop(event)"></td>
                                        geändert und siehe da es funktionierte...

                                        Ich mache beim schreiben des codes, zu meiner eigenen Übersicht, immer einen Absatz bevor ich ein td, tr oder was auch immer schließe, heißt es etwa das jeder Zeilenumbruch als Kindknoten angesehen wird und dieser dann von nodeType "Text" ist?

                                        1. Ich mache beim schreiben des codes, zu meiner eigenen Übersicht, immer einen Absatz bevor ich ein td, tr oder was auch immer schließe, heißt es etwa das jeder Zeilenumbruch als Kindknoten angesehen wird und dieser dann von nodeType "Text" ist?

                                          Das hängt vom Browser ab. FF machts, IE nicht, bei den anderen weiß ich es nicht. Deshalb habe ich dich daraug gestoßen ;-)

                                          1. Das hängt vom Browser ab. FF machts, IE nicht, bei den anderen weiß ich es nicht. Deshalb habe ich dich daraug gestoßen ;-)

                                            Ja Vielen Dank dafür, jetzt ergibt dass auch einen Sinn, was du von mir wolltest.

                                            1. Hallo nochmal,

                                              ich habe hierzu noch ein kleines Problem...

                                              beim weiterbauen meine Website habe ich mir nun eine recht größere Tabelle angelegt und mehrere verschiedene DIV-Elemente, zur Unterscheidung der einzelnen Aufgaben.

                                              Nun bin ich auf das Problem gestoßen das CloneNode, nach der hier behandelten Variante, ja bei jedem Dropvorgang ausgeführt wird, auch wenn ich die DIV-Elemente innerhalb der Tabelle verschieben möchte.

                                              Ich hab mir schon Gedanken gemacht wo ich ansetzen könnte, ich habe es versucht beim Dragstart, zu klonen aber selbst dann erschaffe ich gleich beim Starten des Vorgangs 2 Elemente und selbst dann war mir klar das das auch immer passiert, nicht nur im Quellbereich.
                                              Dann habe ich mir überlegt, beim Dropvorgang, einfach ein neues DIV-Element zu erstellen statt zu klonen, ohne diese Eigenschaften, aber dies müsste ja wiederum die Drag und Drop-Fähigkeiten haben, und da ich die allowdrop an die TD gebunden habe, bringt mich das auch nicht weiter.

                                              Gibt es eine Möglichkeit CloneNode nur auszuführen wenn ich ein DIV-Element auß den Quellbereich ziehe und nicht wenn ich es später noch hin und her schiebe?

                                              1. Moin,

                                                Nun bin ich auf das Problem gestoßen das CloneNode, nach der hier behandelten Variante, ja bei jedem Dropvorgang ausgeführt wird, auch wenn ich die DIV-Elemente innerhalb der Tabelle verschieben möchte.

                                                Genau das habe ich eigentlich in meinem Beispiel realisiert, guck es einfach nochmal nach. Aus dem Quellbereich kann man die Elemente clonen, innerhalb der anderen divs werden die Elemente nur verschoben.

                                                Grüße Marco

                                                1. Genau das habe ich eigentlich in meinem Beispiel realisiert, guck es einfach nochmal nach. Aus dem Quellbereich kann man die Elemente clonen, innerhalb der anderen divs werden die Elemente nur verschoben.

                                                  Stimmt, hast du.

                                                  Nun ich hab das versucht mal anzuapssen auf meine Variante, hier der entsprechende Code

                                                  <table class="planning"><tr></tr>  
                                                  	<tr>  
                                                  		<td class="planning" ondrop="drop(event)" ondragover="allowDrop(event)"></td>  
                                                  		<td class="planning" ondrop="drop(event)" ondragover="allowDrop(event)"></td>  
                                                  		<td class="planning" ondrop="drop(event)" ondragover="allowDrop(event)"></td>  
                                                  		<td class="planning" ondrop="drop(event)" ondragover="allowDrop(event)"></td>  
                                                  		<td class="planning" ondrop="drop(event)" ondragover="allowDrop(event)"></td>  
                                                  		<td class="planning" ondrop="drop(event)" ondragover="allowDrop(event)"></td>  
                                                  		<td class="planning" ondrop="drop(event)" ondragover="allowDrop(event)"></td>  
                                                  		<td class="planning" ondrop="drop(event)" ondragover="allowDrop(event)"></td>  
                                                  	</tr>  
                                                  	<tr>  
                                                  		<td class="planning" ondrop="drop(event)" ondragover="allowDrop(event)"></td>  
                                                  		<td class="planning" ondrop="drop(event)" ondragover="allowDrop(event)"></td>  
                                                  		<td class="planning" ondrop="drop(event)" ondragover="allowDrop(event)"></td>  
                                                  		<td class="planning" ondrop="drop(event)" ondragover="allowDrop(event)"></td>  
                                                  		<td class="planning" ondrop="drop(event)" ondragover="allowDrop(event)"></td>  
                                                  		<td class="planning" ondrop="drop(event)" ondragover="allowDrop(event)"></td>  
                                                  		<td class="planning" ondrop="drop(event)" ondragover="allowDrop(event)"></td>  
                                                  		<td class="planning" ondrop="drop(event)" ondragover="allowDrop(event)"></td>  
                                                  	</tr>  
                                                  </table>  
                                                    
                                                  <table class="legend">  
                                                  	<tr>  
                                                  		<td>  
                                                  			<div id="drag1" onkeydown="deldiv()" draggable="true" class="activity" ondragstart="drag(event)">FO</div>  
                                                  		</td>  
                                                  	</tr>  
                                                  </table>  
                                                  
                                                  
                                                  function drop(ev)  
                                                  {  
                                                  	ev.preventDefault();  
                                                  	ziel = ev.target.getElementsByClassName('div');  
                                                  	if(ev.target.tagName == "TD" && ziel.length == 0) {  
                                                  		data=ev.dataTransfer.getData("Text");  
                                                  		quellElement = document.getElementById(data);  
                                                  		zieltd = quellElement.parentNode;  
                                                  		if(zieltd.classList[0] != "planning") {  
                                                  			Elementneu = quellElement.cloneNode(true);  
                                                  			newId = Elementneu.id.substring(3);  
                                                  			newId++;  
                                                  			Elementneu.id = "quellElement"+newId;  
                                                  			zieltd.appendChild(Elementneu);  
                                                  		}  
                                                  		ev.target.appendChild(quellElement);  
                                                  	}  
                                                  }
                                                  

                                                  bei mir allerdings funktioniert das nicht so ganz, das verschieben geht einwandfrei aber sobald ich versuche zum dritten mal ein siv in die Tabelle zu ziehen verschiebt er nur das jeweils letzte, bei deinem Beispiel funktioniert das allerdings reibungslos, was hab ich falsch gemacht?

                                                  1. so, hab es doch noch hinbekommen

                                                    function drop(ev)  
                                                    {  
                                                    	ev.preventDefault();  
                                                    	ziel = ev.target.getElementsByTagName('td');  
                                                    	if(ev.target.tagName == "TD" && ziel.length == 0) {  
                                                    		data=ev.dataTransfer.getData("Text");  
                                                    		quellElement = document.getElementById(data);  
                                                    		zieltd = quellElement.parentNode;  
                                                    		if(zieltd.classList[0] != "planning") {  
                                                    			newDiv = quellElement.cloneNode(true);  
                                                    			newId = newDiv.id.substring(4);  
                                                    			newId++;  
                                                    			newDiv.id = "drag"+newId;  
                                                    			zieltd.appendChild(newDiv);  
                                                    		}  
                                                    		ev.target.appendChild(quellElement);  
                                                    	}  
                                                    }
                                                    

                                                    nach ein Blick in den quelltext habe ich gemerkt das die ID´s meines 2. div´s irgendwie komisch war und das mit dem substring(3) hab ich zuerst ganricht gecheckt, aber lange genug den Quellcode anstarren hat mich zu der erkenntnis geführt das er bei dir nach 3 Zeichen abschneidet und eine Zahl vorfindet bei mir allerdings findet er einen Buchstaben und newId++ wird wohl nicht so gut funktionieren...

                                                    Vielen Dank Meister!

                                                    1. Moin,

                                                      nach ein Blick in den quelltext habe ich gemerkt das die ID´s meines 2. div´s irgendwie komisch war

                                                      Es ist immer hilfreich den Quelltext anzugucken und die Javascript-Konsole zu nutzen, um genau nachzuvollziehen, was die Funktion macht und welche Ergebnisse das bringt ;)

                                                      und das mit dem substring(3) hab ich zuerst ganricht gecheckt, aber lange genug den Quellcode anstarren hat mich zu der erkenntnis geführt das er bei dir nach 3 Zeichen abschneidet und eine Zahl vorfindet bei mir allerdings findet er einen Buchstaben und newId++ wird wohl nicht so gut funktionieren...

                                                      Ja, aber immerhin warst du schneller als ich^^

                                                      Vielen Dank Meister!

                                                      Nicht der Rede wert :)

                                                      Grüße Marco

                                                      1. Hallo nochmal,

                                                        ich verzweifel gerade, ich fummel die ganze Zeit an den rubberband und php zeugs rum und dann fällt mir auf das ich ich in meine td´s plötzlich wieder mehr als ein div schieben kann, am Code selber habe ich aber nichts geändert, bzw. finde ich keinen Fehler

                                                        function drop(ev)  
                                                        {  
                                                        	ev.preventDefault();  
                                                        	ziel = ev.target.getElementsByClassName('planning');  
                                                        	if(ev.target.tagName == "TD" && ziel.length == 0) {  
                                                        		data=ev.dataTransfer.getData("Text");  
                                                        		quellElement = document.getElementById(data);  
                                                        		zieltd = quellElement.parentNode;  
                                                        		if(zieltd.classList[0] != "planning") {  
                                                        			newDiv = quellElement.cloneNode(true);  
                                                        			newId = newDiv.id.substring(4);  
                                                        			newId++;  
                                                        			newDiv.id = "drag"+newId;  
                                                        			zieltd.appendChild(newDiv);  
                                                        		}  
                                                        		ev.target.appendChild(quellElement);  
                                                        	}  
                                                        }
                                                        
                                                        <table id="planningtable" class="planning">  
                                                        	<tr>  
                                                        		<td class="planning" ondrop="drop(event)" ondragover="allowDrop(event)"></td>  
                                                        		<td class="planning" ondrop="drop(event)" ondragover="allowDrop(event)"></td>  
                                                        		<td class="planning" ondrop="drop(event)" ondragover="allowDrop(event)"></td>  
                                                        		<td class="planning" ondrop="drop(event)" ondragover="allowDrop(event)"></td>  
                                                        		<td class="planning" ondrop="drop(event)" ondragover="allowDrop(event)"></td>  
                                                        		<td class="planning" ondrop="drop(event)" ondragover="allowDrop(event)"></td>  
                                                        		<td class="planning" ondrop="drop(event)" ondragover="allowDrop(event)"></td>  
                                                        		<td class="planning" ondrop="drop(event)" ondragover="allowDrop(event)"></td>  
                                                        	</tr>  
                                                        </table>  
                                                          
                                                        <table class="legend">  
                                                        	<tr>  
                                                        		<td>  
                                                        			<div id="drag1" onkeydown="deldiv()" draggable="true" class="activity" ondragstart="drag(event)" onclick="$(this).toggleClass(&quot;selected&quot;)" >FO</div>  
                                                        		</td>  
                                                        	</tr>  
                                                        </table> 
                                                        

                                                        eine Ahnung woran das liegen kann?

                                                        1. function drop(ev)

                                                          {
                                                          ev.preventDefault();
                                                          ziel = ev.target.getElementsByClassName('planning');

                                                          }
                                                          }

                                                            
                                                          ok Kommando zurück, falscher Klassenname, hier muss ja die div-klasse rein
                                                          
                                                  2. Moin,

                                                    »» newId = Elementneu.id.substring(3);
                                                    »» newId++;
                                                    »» Elementneu.id = "quellElement"+newId;
                                                    »» zieltd.appendChild(Elementneu);

                                                    Der Fehler liegt hier. Deine IDs haben die Form "drag" + Zahl. Dabei sind aber 4 Zeichen Text und nicht nur 3, wie bei mir (picX). Daher musst du in der ersten Zeile .substring(4) schreiben. Ansonsten ist mir nichts aufgefallen, allerdings kann ich das gerade nicht per Copy&Paste testen (befinde mich hier gerade hinter einem sehr restriktiven Proxy).

                                                    Grüße Marco

                                                    1. »» newId = Elementneu.id.substring(3);
                                                      »» newId++;
                                                      »» Elementneu.id = "quellElement"+newId;
                                                      »» zieltd.appendChild(Elementneu);

                                                      Der Fehler liegt hier. Deine IDs haben die Form "drag" + Zahl. Dabei sind aber 4 Zeichen Text und nicht nur 3, wie bei mir (picX). Daher musst du in der ersten Zeile .substring(4) schreiben. Ansonsten ist mir nichts aufgefallen, allerdings kann ich das gerade nicht per Copy&Paste testen (befinde mich hier gerade hinter einem sehr restriktiven Proxy).

                                                      6 Minuten zu spät :-), wie geschrieben habe ich dann auch gemerkt.
                                                      Funktioniert perfekt.

                                                      kannst du mir noch in dieser Anweisung if(zieltd.classList[0] den Teil mit [0] erklären? classList ist mir soweit klar nur das mit der Null versteh ich nicht ganz.

                                                      1. Moin,

                                                        kannst du mir noch in dieser Anweisung if(zieltd.classList[0] den Teil mit [0] erklären? classList ist mir soweit klar nur das mit der Null versteh ich nicht ganz.

                                                        Ein Element kann mehrere Klassen haben, die mit Leerzeichen getrennt aufgelistet werden:

                                                        <div class="drop red bla">

                                                        Daher ist die Eigenschaft classList in Javascript _immer_ ein Array; in diesem Fall mit nur einem Element, auf das per nullbasiertem Index zugegriffen wird.

                                                        Hättest du mehrere Klassen, oder würdest mehrere erwarten, dann müsstest du die gesamte classList nach der Klasse durchforsten, die dir anzeigt, dass man hier ein Element ablegen kann. Dafür könntest du dir beispielsweise eine Funktion äquivalent zum PHP-Pendant in_array() schreiben:

                                                        function in_array(item,arr) {  
                                                        for(p=0;p<arr.length;p++) if (item == arr[p]) return true;  
                                                        return false;  
                                                        }
                                                        

                                                        und die Prüfung so gestalten:

                                                        if(in_array("planning", zieltd.classList[0])) {

                                                        Das wäre beispielsweise auch für die erste Prüfung eine Alternative, in der du nur auf TD prüfst (und ob schon ein Div drinliegt). Denn momentan könnte man prinzipiell erstmal in alle Tabellen-Zellen auf der Seite ein Element ablegen, in denen kein Div-Element ist.

                                                        Grüße Marco

                                                        1. [latex]Mae  govannen![/latex]

                                                          Dafür könntest du dir beispielsweise eine Funktion äquivalent zum PHP-Pendant in_array() schreiben:

                                                          function in_array(item,arr) {

                                                          for(p=0;p<arr.length;p++) if (item == arr[p]) return true;
                                                          return false;
                                                          }

                                                            
                                                          Probleme dieser Funktion:  
                                                          - p ist eine globale Variable und überschreibt Werte von vorhandene Variablen gleichen Namens  
                                                          - arr.length wird in jedem Schleifendurchlauf neu ermittelt  
                                                          - der Vergleichstest ist nicht typgenau. Man fällt auf die Nase, wenn zwischen beispielsweise 4 und '4' unterscheiden werden muß  
                                                          - Array.prototype.indexOf ist nativ vorhanden, man braucht obiges nur als Fallback für Alt-Browser  
                                                            
                                                          ~~~javascript
                                                          var inArray = (function () {  
                                                          	if (typeof Array.prototype.indexOf == 'function') {  
                                                          		return function (item, arr) {  
                                                          			return arr.indexOf(item) > -1;  
                                                          		};  
                                                          	}  
                                                          	return function (item, arr) {  
                                                          		var i, l = arr.length;  
                                                          		for(i = 0; i < l; i++) {  
                                                          			if (item === arr[i]) return true;  
                                                          		}  
                                                          		return false;  
                                                          	};  
                                                          })();
                                                          

                                                          Stur lächeln und winken, Männer!
                                                          Kai

                                                          --
                                                          „Die Borg würden nicht mal Spaß verstehen, wenn sie einen Vergnügungspark assimiliert hätten!” (B'Elanna Torres)
                                                          SelfHTML-Forum-Stylesheet
                                                          1. Moin,

                                                            Ich muss gestehen, dass ich diese Funktion einfach nur kopiert hatte, und selbst auch nicht einsetze. Sie sollte eher als Beispiel dienen.

                                                            Probleme dieser Funktion:

                                                            • p ist eine globale Variable und überschreibt Werte von vorhandene Variablen gleichen Namens

                                                            Ich dachte Variablen sind nur, wenn sie mit var definiert werden global?

                                                            • arr.length wird in jedem Schleifendurchlauf neu ermittelt

                                                            Was eigentlich nur tragisch ist, wenn das Array sehr viele Elemente hat. Dadurch eingebüßte Performanz sollte doch nicht signifikant sein, oder?

                                                            • der Vergleichstest ist nicht typgenau. Man fällt auf die Nase, wenn zwischen beispielsweise 4 und '4' unterscheiden werden muß

                                                            Das ist mir auch aufgefallen. Allerdings ist das in diesem Fall relativ Wurst, da classList ja in jedem Fall ein Array vom Typ string ist.

                                                            • Array.prototype.indexOf ist nativ vorhanden, man braucht obiges nur als Fallback für Alt-Browser

                                                            Oha, das wusste ich nicht...

                                                            var inArray = (function () {

                                                            [...]
                                                            })();

                                                              
                                                            Wie genau wäre diese Variable (eigentlich ein Objekt, oder?) zu verwenden? In etwa so?  
                                                              
                                                            ~~~javascript
                                                            needle = "test";  
                                                            haystack = array("foo", "bar", "fuzz", "test");  
                                                            result = inarray(needle, haystack);  
                                                            alert(result);  
                                                            
                                                            

                                                            Grüße Marco

                                                            1. [latex]Mae  govannen![/latex]

                                                              Probleme dieser Funktion:

                                                              • p ist eine globale Variable und überschreibt Werte von vorhandene Variablen gleichen Namens

                                                              Ich dachte Variablen sind nur, wenn sie mit var definiert werden global?

                                                              Außerhalb eines Funktionskörpers ist es egal, ob ich var a = 3 oder a = 3 schreibe. Es gibt Unterschiede, die aber _rein für die praktische Verwendung_ irrelevant sind. Kann man schön an folgendem Beispiel sehen:

                                                              var xx;  
                                                                
                                                              function foo() {  
                                                                  xx = 4;  
                                                                  var yy = 6;  
                                                              }  
                                                                
                                                              xx = 2;  
                                                              yy = 3; // nicht deklariert  
                                                              console.log(xx, yy); // Ausgabe: 2 3  
                                                              console.log (window.xx, window.yy)  // Ausgabe: 2 3  
                                                                
                                                              // Erst in Funktionen gibt es einen Unterschied  
                                                              foo()  
                                                              console.log(xx, yy); // Ausgabe: 4 3  
                                                              console.log (window.xx, window.yy)  // Ausgabe: 4 3  
                                                              
                                                              

                                                              In Zukunft wird es möglich sein, auch außerhalb von Funktionen einen eigenen Geltungsbereich festzulegen

                                                              • arr.length wird in jedem Schleifendurchlauf neu ermittelt

                                                              Was eigentlich nur tragisch ist, wenn das Array sehr viele Elemente hat. Dadurch eingebüßte Performanz sollte doch nicht signifikant sein, oder?

                                                              Kommt drauf an. Die meisten heutigen Javascript-Engines der Browser sind i.d.R. sehr schnell, da sollte es wirklich nur etwas ausmachen, wenn die Array-Größe extrem ist. Allerdings sind etwas ältere Engines, insbesondere die des Internet-Exploders in sehr vielen Bereichen langsam bis extrem langsam (ob das für diesen speziellen Fall der Array-Länge gilt, weiß ich nicht, ist mir auch keinen Test wert). Aber weshalb sollte man es darauf ankommen lassen, wenn die Optimierung derart einfach ist? Für alle Fälle, in denen das Array nur durchlaufen und nicht modifiziert wird, setze ich einmalig eine Variable und nutze diese.

                                                              • der Vergleichstest ist nicht typgenau. Man fällt auf die Nase, wenn zwischen beispielsweise 4 und '4' unterscheiden werden muß

                                                              Das ist mir auch aufgefallen. Allerdings ist das in diesem Fall relativ Wurst, da classList ja in jedem Fall ein Array vom Typ string ist.

                                                              Ja. Aber man legt sich eine solche Hilfs-Funktion üblicherweise zu, um sie dann generell projektübergreifend verwenden zu können. Und spätestens dann kann es diese Probleme geben.

                                                              Wie genau wäre diese Variable (eigentlich ein Objekt, oder?) zu verwenden? In etwa so?

                                                              In Javascript ist alles ein Objekt (außer den „Primitives“ wie Zahlen, Strings, true, false,..) ;)
                                                              inArray ist hier genauso ein Funktions-Objekt, wie es auch bei function inArray() {} eines ist. Insofern ändert sich an der Verwendung absolut nichts.

                                                              needle = "test";

                                                              haystack = array("foo", "bar", "fuzz", "test");
                                                              result = inarray(needle, haystack);
                                                              alert(result);

                                                                
                                                              array() gibt es in JS nicht, das war PHP ;)  
                                                                
                                                              Stur lächeln und winken, Männer!  
                                                              Kai
                                                              
                                                              -- 
                                                              Wir sind die Schlumpf. Widerschlumpf ist schlumpflos. Wir werden Sie einschlumpfen.  
                                                                
                                                              [SelfHTML-Forum-Stylesheet](http://selfhtml.knrs.de/#h_stylesheet)
                                                              
                                                              1. Moin,

                                                                Außerhalb eines Funktionskörpers ist es egal, ob ich var a = 3 oder a = 3 schreibe. Es gibt Unterschiede, die aber _rein für die praktische Verwendung_ irrelevant sind. Kann man schön an folgendem Beispiel sehen:

                                                                var xx;

                                                                function foo() {
                                                                    xx = 4;
                                                                    var yy = 6;
                                                                }
                                                                xx = 2;
                                                                yy = 3; // nicht deklariert
                                                                console.log(xx, yy); // Ausgabe: 2 3
                                                                console.log (window.xx, window.yy)  // Ausgabe: 2 3
                                                                // Erst in Funktionen gibt es einen Unterschied
                                                                foo()
                                                                console.log(xx, yy); // Ausgabe: 4 3
                                                                console.log (window.xx, window.yy)  // Ausgabe: 4 3

                                                                
                                                                > In Zukunft wird es möglich sein, auch außerhalb von Funktionen einen eigenen Geltungsbereich festzulegen  
                                                                  
                                                                Danke für deine Ausführungen. Das war mir so nicht bewusst.  
                                                                  
                                                                
                                                                > Aber weshalb sollte man es darauf ankommen lassen, wenn die Optimierung derart einfach ist? Für alle Fälle, in denen das Array nur durchlaufen und nicht modifiziert wird, setze ich einmalig eine Variable und nutze diese.  
                                                                
                                                                [...]  
                                                                
                                                                > Ja. Aber man legt sich eine solche Hilfs-Funktion üblicherweise zu, um sie dann generell projektübergreifend verwenden zu können. Und spätestens dann kann es diese Probleme geben.  
                                                                  
                                                                Das stimmt natürlich. Die globalere Denkweise fehlt mir bei Javascript etwas, weil ich, wenn ich überhaupt Javascript genutzt habe, bisher für jede Seite eigens angepasste Skripte verwendet habe (und das auch nur sporadisch).  
                                                                  
                                                                
                                                                > In Javascript ist alles ein Objekt (außer den „Primitives“ wie Zahlen, Strings, true, false,..) ;)  
                                                                > inArray ist hier genauso ein Funktions-Objekt, wie es auch bei `function inArray() {}`{:.language-javascript} eines ist. Insofern ändert sich an der Verwendung absolut nichts.  
                                                                  
                                                                Ja. Klassenlose Objektorientiertheit, hab ich irgendwo gelesen. Das soll wohl in der Form nur selten der Fall sein; ich finde das ganz angenehm.  
                                                                  
                                                                
                                                                > array() gibt es in JS nicht, das war PHP ;)  
                                                                  
                                                                Wiedermal mit der Syntax gepatzt^^ Es müsste natürlich  
                                                                  
                                                                `haystack = new Array("foo", "bar", "fuzz", "test");`{:.language-javascript}  
                                                                  
                                                                heißen. Oder gibt es da auch eine modernere Schreibweise?  
                                                                  
                                                                  
                                                                Grüße Marco
                                                                
                                                                1. [latex]Mae  govannen![/latex]

                                                                  Wiedermal mit der Syntax gepatzt^^ Es müsste natürlich

                                                                  haystack = new Array("foo", "bar", "fuzz", "test");

                                                                  heißen. Oder gibt es da auch eine modernere Schreibweise?

                                                                  Ja, mit var davor. SCNR ;)

                                                                  Die (zumeist) beste Schreibweise ist als Array-Literal:
                                                                  var haystack = ["foo", "bar", "fuzz", "test"];

                                                                  Stur lächeln und winken, Männer!
                                                                  Kai

                                                                  --
                                                                  „Die Borg würden nicht mal Spaß verstehen, wenn sie einen Vergnügungspark assimiliert hätten!” (B'Elanna Torres)
                                                                  SelfHTML-Forum-Stylesheet
                                                                  1. Moin,

                                                                    Ja, mit var davor. SCNR ;)

                                                                    Verdammt. Ich bemüh mich^^

                                                                    Die (zumeist) beste Schreibweise ist als Array-Literal:
                                                                    var haystack = ["foo", "bar", "fuzz", "test"];

                                                                    Gibt es einen relevanten Unterschied zwischen dem und new Array(); oder ist das eine Style-Frage?

                                                                    Grüße Marco

                                                                    1. [latex]Mae  govannen![/latex]

                                                                      Die (zumeist) beste Schreibweise ist als Array-Literal:
                                                                      var haystack = ["foo", "bar", "fuzz", "test"];

                                                                      Gibt es einen relevanten Unterschied zwischen dem und new Array(); oder ist das eine Style-Frage?

                                                                      Ja. Ja.

                                                                      Wenn ich das noch recht in Erinnerung habe, sind die internen Vorgänge in der Verarbeitung nicht genau gleich, aber ich habe nicht viel Ahnung von Javascript.

                                                                      Aber allein die inkonsistente Verhaltensweise des Konstruktors ist ein Grund, die Literal-Schreibweise zu wählen.

                                                                      var foo = [1, 2] // Array mit zwei Einträgen: Wert von foo[0] ist 1, foo[1] ist 2  
                                                                      var foo = new Array(1, 2) // Array mit zwei Einträgen: wert von foo[0] ist 1, foo[1] ist 2
                                                                      

                                                                      so weit, so erwartet.

                                                                      ABER:

                                                                      var foo = [8]  // Array mit einem Eintrag, Wert von foo[0] ist 8  
                                                                      var foo = new Array(8)  // Array mit 8 Einträgen, Werte von foo[0] bis foo[7] sind jew. undefined
                                                                      

                                                                      Stur lächeln und winken, Männer!
                                                                      Kai

                                                                      --
                                                                      Unsere Identität entnehmen Sie bitte dem beigefügten Auszug aus den Personenstandsbüchern. Gegen die Assimilierung in unser Kollektiv ist nach dem ABGB (§666, Abs. 3/IV) kein Rechtsmittel zulässig. Wir bitten um Ihr Verständnis.
                                                                      SelfHTML-Forum-Stylesheet
                                    2. Das kommt ja darauf an, was in der Tabellenzelle schon drin steht, du kannst dir ja den nodeType von firstChild ausgeben lassen.

                                      bisher steht nichts drin, wie kann ich den ausgeben?

                                      alert(ev.target.firstChild.nodeType+"-"+ev.target.firstChild.nodeName)

                                      und dann schaust du http://de.selfhtml.org/javascript/objekte/node.htm#node_type@title=hier.

                                2. Moin,

                                  ok, habe ich, liege damit richtig wenn es aber in dieser Lösung ein Elementknoten ist?

                                  Am allerbesten ist es, wenn du dir mal alles in einer Developerkonsole anguckst. Ich mache das beispielsweise so: Ich schreibe das Grundgerüst der Seite und seh sie mir im Chrome an. Dann öffne ich die Konsole (F12) und spiele mit Javascript herum.
                                  Dann kannst du gucken, was wirklich das firstChild deiner Tabellenzelle ist, welche Klassen sie hat (classList), welche Funktion richtig und welche falsch geht, und so weiter.

                                  Schon, wenn in einem Element (quasi hier deine Zelle) ein Leerzeichen steht, gibt es ein firstChild. Soetwas muss man beachten.

                                  Eine Lösung wäre beispielsweise, deine Zelle auszuwählen und zu fragen, ob schon ein Div-Element darin liegt. In meinem Fall würde das so aussehen:

                                  	function drop(ev)  
                                  	{  
                                  		ev.preventDefault();  
                                  		anz = ev.target.getElementsByTagName('img');		  
                                  		if(ev.target.tagName == "DIV" && anz.length == 0) {  
                                  			data=ev.dataTransfer.getData("Text");  
                                  			pic = document.getElementById(data);  
                                  			div = pic.parentNode;  
                                  			if(div.classList[0] != "destdiv") {  
                                  				newPic = pic.cloneNode(true);  
                                  				newId = newPic.id.substring(3);  
                                  				newId++;  
                                  				newPic.id = "pic"+newId;  
                                  				div.appendChild(newPic);  
                                  			}  
                                  			ev.target.appendChild(pic);  
                                  		}
                                  

                                  Aber das muss natürlich auf den entsprechenden Anwendungsfall abgestimmt werden.

                                  Grüße Marco

                2. noch eine kurze Frage, kann man irgendwie vermeiden das das Target mehr als ein DIV-Element aufnimmt, das heißt irgendwie prüfen ob schon eines Vorhanden ist und es dann verweigern bzw. mit dem neuen ersetzen?

                  Schau dir mal

                  childNodes
                  getElementById
                  getElementsByTagName
                  getElementsByName

                  an und überleg dir, was für deine Zwecke geeignet ist.