Jquery

Eine Ajax Abfrage mit jQuery – nestedSortable Beispiel

Ein kleines Beispiel wofür Ajax so alles gut sein kann.
Ich habe hier mal eine Liste die ich per DragnDrop sortieren will. Dazu verwende ich die nestedSortable Funktion, die dankenswerter Weise weiterentwickelt wird.
Damit die Sortierung auch von Dauer ist, wird dann später jede Änderung im Hintergrund per Ajax in eine Datenbank geschrieben.

[DRAGNDROPLISTE]

<ol id="liste" class="sortable">
<li id="myid_1"><div>eins</div>
<ol>
<li id="myid_2"><div>eins eins</div></li>
<li id="myid_3"><div>eins zwei</div></li>
<li id="myid_4"><div>eins drei</div></li>
</ol>
</li>
<li id="myid_5"><div>zwei</div>
<ol>
<li id="myid_6"><div>zwei eins</div></li>
<li id="myid_7"><div>zwei zwei</div></li>
<li id="myid_8"><div>zwei drei</div></li>
</ol>
<li id="myid_9"><div>drei</div>
<ol>
<li id="myid_10"><div>drei eins</div></li>
<li id="myid_11"><div>drei zwei</div></li>
</ol>
</li>
<li id="myid_12"><div>vier</div>
</li>
<li id="myid_13"><div>fünf</div>
<ol>
<li id="myid_14"><div>fünf eins</div></li>
<li id="myid_15"><div>fünf zwei</div></li>
</ol>
</li>
</ol>

( Die Liste enthält einen div Wrapper, der ist für jQuery Erweiterung nestedSortable nötig „handle:div“  )

Um das DragnDrop zu ermöglichen braucht es jQuery , jQueryUI und nestedSortable.js und ein bisschen CSS Styling

<script src="jquery.min.js"></script>
<script src="jquery-ui.min.js"></script>
<script src="jquery.mjs.nestedSortable.js"></script>
<script>
$( document ).ready(function() {
	$('.sortable').nestedSortable({
            handle: 'div',
            items: 'li',
            toleranceElement: '> div'
        });
});
</script>
<style type="text/css">
<!--
ol { list-style:none;}
ol li { background-color:#eee; border:1px solid black; margin:0 5px 5px 0; }
ol li li{ background-color:#ddd;  }
ol li li li{ background-color:#ccc;  }
ol li li li li{ background-color:#bbb;  }
-->
</style>

Hiermit kann man schon, wie im Beispiel oben, die Liste per DragnDrop sortieren.

Und nun kommt noch der Ajax Aufruf hinzu, damit die Datenbank upgedatet werden kann.

$('.sortable').nestedSortable({
  handle: 'div',
  items: 'li',
  toleranceElement: '> div',
  stop: function(e){ 
      toArray = $(this).nestedSortable("toArray", {startDepthCount: 0});
      $.ajax({  type: "POST", 
                url: "listindb.php",
                data: { toArray:toArray },
                success: function(response){  },
                error: function(response){  }
       }); //ajax
   }//stop
}); //nested sortable

Bei jedem Stop einer DragnDrop Aktion wird die neue Reihenfolge abgefragt.

Die toArray Funktion die  nestedSortable  zur Verfügung stellt, erstellt einen Array nach der Art
toArray[n] = {
‚item_id‘: itemId,
‚parent_id‘: parentId,
‚depth‘: depth,
‚left‘: left,
‚right‘: right,
}
Diesen können wir an unser PHP Script senden. data: { toArray:toArray } ==   data:{  Name der Variablen im PHP $_POST Array : Name des Javascript Arrays }

Für obige Liste würde toArray also so aussehen

item_id:null – depth:0 – left:1 – right:30 – parent_id:null
item_id:1 – depth:1 – left:2 – right:9 – parent_id:null
item_id:6 – depth:2 – left:3 – right:4 – parent_id:1
item_id:7 – depth:2 – left:5 – right:6 – parent_id:1
item_id:8 – depth:2 – left:7 – right:8 – parent_id:1
item_id:2 – depth:1 – left:10 – right:15 – parent_id:null
item_id:9 – depth:2 – left:11 – right:12 – parent_id:2
item_id:10 – depth:2 – left:13 – right:14 – parent_id:2
item_id:3 – depth:1 – left:16 – right:17 – parent_id:null
item_id:4 – depth:1 – left:18 – right:21 – parent_id:null
item_id:11 – depth:2 – left:19 – right:20 – parent_id:4
item_id:5 – depth:1 – left:22 – right:29 – parent_id:null
item_id:12 – depth:2 – left:23 – right:24 – parent_id:5
item_id:13 – depth:2 – left:25 – right:26 – parent_id:5
item_id:14 – depth:2 – left:27 – right:28 – parent_id:5

Um eine verwendbare ID jedes li zu übermitteln, trennt nestedSortable die ID automatisch bei einem Unterstrich, darum lauten in meiner Liste die IDs der LIs „myid_“ und dann die ID, die wir auch in der DB wieder verwenden werden.

Hier der PHP Part für die listindb.php.
Eine Datenbankverbindung sollten wir natürlich schon erstellt haben, sonst wird mysql_query nur einen Fehler ergeben.

foreach ($_POST['toArray'] as $key=>$val) 
{
	if (intval($val['item_id'])>0) 
	{
		$ebene = $val['depth'];
		$nummer[$ebene]++;
		$s="UPDATE `liste` SET `nummer`='".$nummer[$ebene]."' ,`ebene`='".$ebene."'  ,`pid`='".$val['parent_id']."' WHERE `id`= '".$val['item_id']."'";
		$r=mysql_query($s);
		if (mysql_error()) $debug .= mysql_error()."<br>";
	}
}
echo $debug;

Wir zählen die Nummer hoch, damit wir auch die richtige Reihenfolge auf jeder Ebene behalten.
Dann tragen wir die „parent_id“ und die „nummer“ in die DB ein. „ebene“ ist in unserem Fall eher optional.
Falls das Updaten nicht klappt geben wir einen „debug“ Meldung zurück an die jQuery Ajax Funktion.

Um die Sache rund zu machen, müssen wir die HTML Liste natürlich auch erst einmal aus der Datenbank erstellen.
Hier das PHP Script für das HTML Dokument, um die <ol> aus der DB zu erstellen.
Dazu lesen wir jedes Element nach seiner „parent_id“ aus, in dem wir bei 0 starten getthelist(0);
Die oberste Ebene bekommt die class=“sortable“.
Die LIs mit gleicher „parent_id“ sind nach „nummer“ sortiert.
Und dann gehen wir, wenn das jeweilige Element Kinder hat (haschilds) , rekursiv nach unten.

getthelist(0);

function getthelist($id){ 
	$res=mysql_query("SELECT * from `liste` WHERE `pid`='".$id."' ORDER BY `nummer`");
	if ($id==0) echo '<ol id="liste" class="sortable">';
	else echo '<ol>';
	while($data=mysql_fetch_array($res)){
		echo '<li id="myid_'.$data['id'].'"><div><span class="ebene">('.$data['ebene'].') </span> <input id="feld_'.$data['id'].'" type="text" class="textfeld" value="'.$data['name'].'" /></div>';
		if (haschilds($data['id']))  getthelist($data['id']);
		echo '</li>';
	}
	echo '</ol>';
}

function haschilds($id){
	$res=mysql_query("SELECT `id` from `liste` WHERE `pid`='".$id."'");
	if (mysql_num_rows($res)>0) return true;
	else return false;
}

Die Liste kann man natürlich noch mit weiteren Ajax Funktionen erweitern. Wie im Ersten Tutorial beschrieben, kann man den Titel jedes LIs bearbeitbar machen.

Und das ganze zusammen als >Download

Und der SQL Dump für die DB:

CREATE TABLE IF NOT EXISTS `liste` (
`id` int(11) NOT NULL,
`pid` int(11) NOT NULL,
`name` varchar(64) COLLATE utf8_unicode_ci NOT NULL,
`nummer` int(11) NOT NULL DEFAULT '0',
`ebene` int(11) NOT NULL
) DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
 
INSERT INTO `liste` (`id`, `pid`, `name`, `nummer`, `ebene`) VALUES
(1, 0, 'eins', 1, 1),
(2, 0, 'zwei', 2, 1),
(3, 0, 'drei', 3, 1),
(4, 0, 'vier', 4, 1),
(5, 0, 'fünf', 5, 1),
(6, 1, 'eins eins', 1, 2),
(7, 1, 'eins zwei', 2, 2),
(8, 1, 'eins drei', 3, 2),
(9, 2, 'zwei eins ', 4, 2),
(10, 2, 'zwei zwei', 5, 2),
(11, 4, 'vier eins', 6, 2),
(12, 5, 'fünf eins', 7, 2),
(13, 5, 'fünf zwei', 8, 2),
(14, 5, 'fünf drei', 9, 2);