Drag und Drop Dynamisch zufügen und Position bestimmen

Hi,

ich hab jetzt schon länger mitgelesen und es hat mir ebenfalls unter den Nägeln gebrannt, mich an einer Umsetzung zu versuchen.

Meine Vorgehensweise:
  • Ich würde für jede Position ein sortable Element erstellen und dieses mit der Ausgangsliste an Spielern verbinden.
  • Jedes solches Positionsfeld kann zwei Spieler aufnehmen.
  • Das Positionsfeld kann mittels Drag/Drop auf einem entsprechenden Element platziert werden.
  • Die Spieler können aufgrund der Verbindung der sortable Elemente in beide Richtungen ausgetauscht werden

Zur Demonstration habe ich hier eine kleine Anwendung erstellt.

Ciao
Quaese
 
Boh, das ist ja der Hammer. Ich quaele mich rum und Du erstellst in der Zwischenzeit mal eben diese geniale Demo? Hut ab !

Ich muss mir das Ganze mal in Ruhe anschauen und hoffentlich verstehe ich auch alles was ich sehe. Vielen Dank das Du aufgezeigt hast, dass es machbar ist. Ich war wirklich am Verzweifeln.

Gruss Bicko
 
Hi alle zusammen,

Nach nun einigen Tagen des ausprobierens muss ich leider feststellen, dass ich es so doch nicht hinbekomme. Die Lösung von Quaese ist zwar sehr interessant, aber vielleicht doch zu komplex für meine Zwecke. Eines der Probleme wäre sicherlich das ich die Information, wo sich ein Spieler befindet (im Sturm, Verteidigung) nicht so einfach eausbekomme. Ich habe zwar Koordinaten, aber damit rauslesen, welche Position er spielt? Ich hatte es ja so gedacht, dass ich meine Aufstellung zusammenklicke, wer hat gespielt, wer wurde eingewechselt und wann und das geht dann in die DB.

Ich möchte also nur 11 Felder haben und dort dann Auswechselspieler jeweils neben den Namen des auszuwechselnen ziehen können. Wie gesagt, Quaese's Lösung ist genial, es übersteigt jedoch meinen Wissenstands um dieses weiter auszubauen. Ich habe also versucht das Ganze zu verstehen und umzubauen. Doch leider scheitere ich daran.

Hier mal mein Gedankengang:

  • Ich habe meine Liste an Spielern:
HTML:
<ul id="spieler_liste">
	<li class="cl_head_li">TORWART</li>
	<li id="torwart_id">
  	  <ul class="sort_list">
    	    <li class="cl_tw"><div id="sp_01">Torwart 1</div></li>
    	    <li class="cl_tw"><div id="sp_02">Torwart 2</div></li>
          </ul>
        </li>
	<li class="cl_head_li">ABWEHR</li>
	<li id="abwehr_id">
  	  <ul class="sort_list">
    	     <li class="cl_aw"><div id="sp_03">Abwehr 1</div></li>
	     <li class="cl_aw"><div id="sp_04">Abwehr 2</div></li>
	     <li class="cl_aw"><div id="sp_05">Abwehr 3</div></li>
         </ul>
       </li>
</ul>
  • Ich habe mein 11 Positionsfelder, dort werden die Spieler reingezogen (am Besten wäre, es wird auf den Namen des Spieler geklickt und dieser erscheint im ersten Positionsfeld)
HTML:
<div id="spielfeld">
    <ul></ul> // Dies 11 mal
    <ul></ul>
</div>

$(function(){
    $('#spielfeld >ul').addClass('cl_new_pos 
     ui-draggable ui-draggable-dragging sort_list ui-sortable'); 
})
  • Nun wird die Spielerliste draggable gemacht
HTML:
// -- Positionsliste draggable machen?
  $('.sort_list li').draggable({
    helper: 'clone',
    revert: 'invalid',
    opacity: 0.8,
    grid: [10, 10],
    stop: function(evt, ui){
    	$(this).empty();
    }
  });

  • Nun werden die Positionsfelder droppable gemacht, damit ein Spieler abgelegt werden kann
HTML:
  // -- Spieler kann auf Position abgelegt werden
  $('.cl_new_pos').droppable({
  	accept: '.sort_list li',
        drop: function(evt, ui){
        }
});

Und nun scheitert jeglicher Versuch. Die Idee das man einen 2. Spieler auf ein Feld ziehen kann, dieses sich dann vergrössert und man nach klick auf den Spieler noch eine Zeit eingeben kann finde ich eigentlich ganz gut. Doch wenn ich den gesamten Bereich der Ursprünglich $('#spielfeld').droppable({ war auf cl_new_pos ändere geht es natürlich nicht so einfach. Ich kann ganz im Gegenteil so viele Spieler wie ich will auf mein cl_new_pos legen. if($(this).find('li').length>2) wird ignoriert, ich denke sogar das der überhaupt nicht soweit kommt.

Das ist wirklich eine harte Nuss für einen Anfänger, aber ich würde es so gerne umsetzen. Wie geht Ihr an eine solche Sache? Was muss ich dabei bedenken und wo liegen vielleicht meine Gedankenfehler? Ich versuche eine Linie reinzubekommen, an der ich mich orientieren kann. Ich hoffe nochmal ein paar Tips von Euch zu bekommen.

Vielen Dank im Voraus !! Gruss Bicko
 
Moin,

etwas spät, aber nicht vergessen :-)

Mal ein paar Gedankenansätze:

*sortable's kann man löschen und neu anlegen.
*Markup kann man ändern.

Du musst also nicht gleich beim 1x alles fertig implementieren.

Zuerst reichen ja 2 einfache Listen, eine mit allen Spielern, und eine leere.
Da kannst du von A nach B sortieren.

Hast du das 11x gemacht, kannst du eine neues sortable initiieren.

Angenommen, die Liste mit den 11 ausgewählten Spielern hätte nicht eine einfache Struktur wie jene:
Code:
<ul><li>Spieler</li></ul>

...sondern so:
Code:
<ul><li><ul><li>Spieler</li></ul></li></ul>
...dann hättest du schon mal einen grossen Schritt getan. Du könntest nämlich die innere <ul/> sortierbar machen. Dort wird der Einwechselspieler hereingeschoben.

Ändern kannst du diese Struktur per wrapInner(), das kapselt einen Knoten in eine neue übergeordnete Struktur ein.

Wie bekommst du nun raus, wer rein ist und wer raus soll?
Gebe den Spielern Klassen!

Beim 1. Sortable gebe den aufgestellten Spielern irgendeinen Klassennamen.

Beim 2. Sortable(Auswechslung) entferne aus dem Elternknoten des einsortierten Spielers den Spieler, der den besagten Klassennamen hat, und gebe dem neu einsortierten Spieler danach wiederum den Klassennamen.

Fertig :-)

Wie das en Detail geht, kannst du hier mal beobachten.

http://doktormolle.de/temp/364622/

...ich hab die wichtigen Sachen im Skript kommentiert. Falls Fragen sind, frag :)
 
Hi Sven,

Vielen Dank für Dein Script. Deine Lösung klappt wirklich sehr gut. Ich habe mich jetzt rangemacht das Ganze mit AJAX zu erweitern, es klappt zwar noch nicht so ganz, aber ich wollte mich mal melden und wenigstens mitteilen, dass ich mich mit Deiner Lösung auseinandersetze.

Ich muss ja mehrere Daten übertragen.

1. Alle 11 Spieler der Anfangsformation
2. Wer kam rein und wer ging raus

Für den Punkt 1 habe ich überlegt das der AJAX Aufruf passieren sollte, sobald die 11 Spieler ausgewählt wurden.
HTML:
if($(this.wrapper).find('.ingame .player').length==11)
{
  var playerList = {}
  playerList.playername = $('.ingame').text();
  
$.ajax({
            url: 'ajax.php',
            contentType: "application/json; charset=utf-8",
            dataType: "json",
            data: playerList,
            success: function(data) {
                               alert('OK.');
                         }
         });

//nur für die Optik
   $(this.wrapper)
      .find('.ingame')
      .addClass('ready');

Ich Prinzip brauche ich dafür ja alle Listenelemente der Klasse ingame. So wie ich es jetzt jedoch mache, werden die Daten als String übertragen, das ist schlecht, denn in meinem PHP Script wäre es sicherlich einfacher das Ganze als Array zu empfangen.

Daran sitze ich momentan also noch und versuche rauszubekommen, wie ich eine komplette Liste in ein Array bekomme oder ist der Gedankenansatz völlig verkehrt?

Nochmal vielen Dank für Deine Hilfe !!

Gruss Bicko
 
Ich hab das mal in die Demo eingebaut, du findest dort folgende Sachen:

Zeile 222:
Code:
//MAP:Aufstellung

und weiter unten Zeile 263
Code:
//MAP:Auswechslung

der nachfolgende Code(bis zum alert) erzeugt jeweils ein Objekt namens "map" mit den notwendigen Daten.
Das kannst du per AJAX verschicken :)
 
Hi Sven,

Oh man, darauf haette ich wirklich selber kommen muessen, wobei ich das sogar mal angedacht hatte... in PHP wuerde ich mir ein Array ja auch ueber eine Schleife zusammenbauen. Schoen bloed.

Ich wuesste gar nicht, was ich ohne Deine ausgiebige Hilfe machen wuerde. Mir ist das zwar wirklich peinlich, aber ich muss zugeben, dass man so eine Menge lernen kann.

Na ja, nun bin ich wieder dran, Dein Script zu erweitern und fuer jeden der es verfolgt, hier meine Fortsetzung die hoffentlich zu gebrauchen ist.

1. Den Ajax Part um das Ganze in die DB zu bekommen:

Code:
 $.ajax({
             url: 'ajax.php',
             contentType: "application/json; charset=utf-8",
             dataType: "json",
             data: map,
             success: function(data) {
                alert('OK.');
             }
         });
In der ajax.php benutze ich dann eine foreach Schleife fuer das Array

2. Dann fuege ich jetzt noch einen Muelleimer ein, falls man mal den falschen Spieler ausgewaehlt hat. Dafuer habe ich mir gedacht als erstes in der "Funktion für Aufstellung" den Spieler draggable zu machen:

Code:
//Funktion für Aufstellung
nominate:function(player)
{
   //für Wechsel Spieler mit einer weiteren <ul> umschliessen,
   // die dann auch Auswechselspieler aufnimmmt
                player.wrapInner($('<ul><li/></ul>'))
                  .find('li')
                    .addClass('player');

// Spieler draggable machen, damit dieser in den Trash verschoben werden kann
// aber nur erstes li und nicht .player von li
$(this.wrapper)
    .find('.ingame li').not('.player')
       .draggable();

3. Dann folgt der Muelleimer:
HTML:
// Mülleimer
              $('#trash_id').droppable({
              	accept: '.ingame li',
                drop: function(evt, ui){
                     // Klasse entfernen, da der Spieler ja wieder in Auswahlliste zurueck soll
                     ui.draggable.find('li').removeClass('player');
                     // Spieler zurueck in the Auswahlliste
                     ui.draggable.find('li').appendTo('.pool');

                     ui.draggable.fadeOut(250, function(){
                  	  window.setTimeout(function(){ui.draggable.remove();}, 800);
                    });
                }
              });

Das scheint alles soweit zu funktionieren oder sieht jemand noch einen Denkfehler?

Obwohl habe gerade selber noch etwas gefunden, wenn alle 11 Spieler ausgewaehlt wurden und dann 1 Spieler entfernt wird, wird dies ignoriert, bedeutet wenn ich einen weiteren Spieler in die Aufstellung ziehe ist dies nun ein Auswechselspieler. Ich werde weiter daran arbeiten und diesen Post updaten, sobald ich dafuer eine Loesung habe. Ich muss dann ja auch nochmal per AJAX die DB updaten, falls sich etwas nach den 11 Spielern geaendert hat.

Update folgt also, hoffe das ist okay.

Nochmal vielen Dank an Sven !
 
Obwohl habe gerade selber noch etwas gefunden, wenn alle 11 Spieler ausgewaehlt wurden und dann 1 Spieler entfernt wird, wird dies ignoriert, bedeutet wenn ich einen weiteren Spieler in die Aufstellung ziehe ist dies nun ein Auswechselspieler.

Das klingt zumindest vom spieltechnischen Aspekt her logisch.:eek:

Sobald 11 Spieler aufgestellt wurden, wird ja da nichts mehr rumgewurschtelt...es wird entweder ausgewechselt oder gibt eine rote Karte, und im letzteren Fall würde da ja nicht wieder auf 11 aufgefüllt. Genauso in dem Fall, dass das Limit an Auswechselungen erreicht wurde und jemand sich verletzt verabschieden muss.
 
Zuletzt bearbeitet:
Hi,

So, ich hoffe Ihr langweilt Euch nicht mit diesem Thema, aber es gibt ein weiteres Update und eine neue Frage...

1. Ich habe einen "Fertig" Button und erst wenn man den klickt, wird die Mannschaft via AJAX in die DB geschrieben (Das Ganze auch in einer eigenen Function)

2. Ich habe den ausgewaehlten Spielern einen "Doppelclick" Event zugewiesen. Das Ganze habe ich so versucht:

Code:
//initialisierung
init:function()
{
    $(this.wrapper).find(".ingame .name").live('dblclick', function(event,ui){
          _this.addGoals(this);
    });

Dann habe ich meine addGoals Function
Code:
// Funktion für Tore zufuegen (Aus dem 1. Script)
addGoals:function(player)
{

    var strInsert = $(player).find('span').html();
    strInsert = (strInsert!=null)? strInsert.replace(/[ \(\)\.]/g, "") : "";
    var strGoal = prompt("Wieviele Tore geschossen?", strInsert);
    // entferne den vorherigen span tag, gilt wenn erneut doppelclick
    $(player).find('span').remove();
    if(strGoal==null || strGoal=="") return;

    $(player).append($('<span>').html(" ("+strGoal+"Tor(e))"));
},

Damit kann ich nun also Tore hinzufuegen. Klappt auch... fast. Der span tag wird in den span tag vom spieler geschoben also so:
<span class="name">Gomez <span>2 Tore</span></span>
Mmh, habe alles Moegliche probiert aber komme einfach nicht drauf, wie ich es in den div tag bekomme. Ist der Ansatz ueberhaupt richtig? Bin ja noch sehr unerfahren mit jQuery.

**
Loesung gefunden:

Code:
$(player).parent("div").append($('<span class="goal">').html(" ("+strGoal+"Tor(e))"));


Nun muss ich noch rausfinden wie ich aus meiner saveFinalTeam:function(player) auf die Information ueber die Auswechslungen zugreifen kann, das wird vermutlich nochmal schwierig.


Gruss Bicko
 
Zuletzt bearbeitet:
@Sven

Bei der Analyse deines Scripts sind mir zwei Sachen aufgefallen:

1. Syntaxfehler beim Objekt map für Auswechslungen
Du schliesst die Komponente _in mit einem Komma ab, was der IE mit einer Fehlermeldung quittiert.

2. Globale Variable in der Methode substitute
Du deklarierst die Variable playerOut global. Wenn ich es richtig überblicke, würde eine lokale ausreichen.

Ciao
Quaese
 
Zurück