jQuery UI, Ajax animierter Ladebalken

Mit Hilfe von PHP und JavaScript kann man einen Tollen animierten Ladebalken erstellen. Sehr interessant, wenn man mit PHP Aktionen durchführen möchte, die über 5 Sekunden dauern.

 

Das schöne ist das man dank Ajax Technologie den Anwender immer auf dem neusten Stand halten kann.


Als JavaScript Framework setze ich jQuery mit der Erweiterung jQuery UI. Den Datenaustausch zwischen Javascript und PHP mache ich mittels JSON, wodurch man PHP Objekte direkt als Javascript Objekte übergeben kann. Außerdem lassen sich dadurch bequem mehrere Daten übertragen.
[ad#adsense]

Fangen wir an!

Als aller erstes sollte man sich nun jQuery und jQuery UI herunterladen. Als nächstes erstellt man sich eine index.php welche das Standard HTML Gerüst enthält. Im Bereich bindet man nun die JavaScript Libary und die dazu gehörigen CSS Dateien ein.

<link type="text/css" href="./css/ui-lightness/jquery-ui-1.8.13.custom.css" rel="stylesheet" />

<script type="text/javascript" src="./js/jquery-1.5.1.min.js"></script>
<script type="text/javascript" src="./js/jquery-ui-1.8.13.custom.min.js"></script>

Im Body Teil unserer index.php bauen wir zwei Div Platzhalter ein. Der eine wird unsere Progressbar, der andere zeigt nacher eine Nachricht an, welche wir im PHP Code generieren. Wichtig ist, das wir beiden Divs IDs geben, nur dadurch können wir nach im JavaScript Code die beiden Divs wieder finden.

<!--Die Progressbar-->
<div id="progressbar"></div>

<!-- Div Platzhalter für eigene von PHP generierte Nachrichten -->
<div id="message">Lädt...</div>

Als nächstes kümmern wir uns um die PHP Seite. Die Datei, die für uns die eigentlich lange dauernde Aktion ausführen soll ist die ajax.php. Diese werden wir auch per JavaScript ansprechen und genau diese Datei soll uns mithilfe von einem JSON Objekt den aktuellen prozentualen Status und eine von uns aus PHP generierte Nachricht zurück geben, sodass wir sie auf der Webseite dem User darstellen können und informieren können, wie weit sein Prozess fortgeschritten ist.

Dazu erstellen wir die ajax.php und fügen folgenden Inhalt ein:

$zufall = rand(1,3); // Zufällige länge der Aktion simulieren

sleep($zufall); // Simulieren einer langen Aktion...

Diese zwei Zeilen sind nur dafür da eine lange Aktion zu simulieren, welche nacher irgendwelche langsamen Datenbank abfragen, Backup Funktion usw. sein können.

Als nächstes bauen wir unser php_array, welches wir später als JSON Objekt umwandeln. Das php_array enthält den Index status, in dem wir die aktuellen Fortschritt in Prozent rein schreiben. Natürlich kann man sich die indexe frei aussuchen ;).

Unser index Status bekommt noch eine kleine wenn überprüfung, denn bei 100% ist Schluss, so ist sicher gestellt, das wir nie über 100% kommen.

// Unser $php_array ist ein Array, welches nacher als JSON Objekt ausgeben wird
// Enthält unseren Prozessfortschritt, als Prozentwert
$php_array['status'] = $_GET['status']+($zufall*3);

// Bei 100% ist Schluss ;)
if($php_array['status']>100) {
	$php_array['status'] = 100;
}

Als zweiten Teil, wollen wir eine von PHP generierte Nachricht an den Benutzer auch noch übergeben. Dafür legen wir einfach einen neuen Index zu den bereits bestehenden $php_array an, den wir message nennen. Dort können wir unsere Nachricht angeben.

// Eine von Nachricht an dem Benutzer aus PHP
if($php_array['status'] != 100) {
	$php_array['message'] = 'Aktueller Status <b>'.$php_array['status'].'%</b> von 100%, Differenz: '.(100-$php_array['status']);
} else {
	$php_array['message'] = 'Juhu endlich geschafft! ;)';
}

[ad#adsense]
Zum Schluss des ganzen, müssen wir nur das PHP Array in ein JSON Objekt umwandeln, das geht mit folgender kleinen PHP Zeile:

// Ausgabe des PHP Arrays als JSON Objekt
echo json_encode($php_array);

Das gibt folgenden String zurück:

{"status":90,"message":"Aktueller Status <b>90%<\/b> von 100%, Differenz: 10"}

Das ist der String den wir in JavaScript brauchen. Nun geht es zu dem JavaScript Code, da unsere Background PHP Datei soweit fertig ist. Als aller erstes wollen wir unseren html div in eine Progressbar umwandeln. Diesen Befehl gibt es nur wenn jQuery + jQuery UI eingebaut ist. value sagt unserer Progressbar, wieviel % sie nun hat, zum Start macht es Sinn ihn auf 0% zu setzen, da wir ja unser PHP Skript noch gar nicht arbeiten lassen haben.

$("#progressbar").progressbar({
	value: 0 
});

Als nächstes kommt die JavaScript Funktion load(), diese ruft die ajax.php mit einem Parameter auf, der Parameter ist unser aktueller Status. Dazu nutzen wir die Funktion ajax von jQuery. Als Einstellung gibt es dort unteranderem die url, welche der aufzurufenden Datei entspricht. Das ist bei unseren Fall, wie schon zuvor gesagt, die ajax.php.

url: './ajax.php?status='+$( "#progressbar" ).progressbar( "value" ),

Als nächstes kommt die Eigenschaft success, dort hinterlegen wir die Funktion, die aufgerufen werden soll, wenn der Request erfolgreich war, also wenn wir den Inhalt von der ajax.php zurück bekommen haben. Als Parameter von der Funktion, wird jQuery unseren Inhalt von den Ajax Request zurück geben, also in unserem Fall heißt der Parameter data.
Da unsere PHP Datei ein json Objekt zurück gibt, machen wir eine neue Variable ajax und fügen wir das JSON Objekt hinzu, das machen wir in dem wir ein eval ausführen, mit dem zurück gegeben String von PHP, der sich in der Variable data befindet.

ajax = eval('(' + data + ')');

Nun können wir mithilfe von ajax.index auf die zuvor in PHP erstellten Indexe zu greifen. In z.B. ajax.status ist der prozentuale Status, den wir in PHP errechnet haben.
[ad#adsense]
Mit hilfe von ajax!=false überprüfen wir in der if Bedingung, ob wir überhaupt ein JSON Objekt erhalten haben. Der Progressbar geben wir ihren neuen Prozentsatz mithilfe von:

$("#progressbar").progressbar({
	value: ajax.status
});

Und danach aktualisieren wir den Div, der unsere PHP Message darstellen sollen.

$("#message").html( ajax.message );

Und zum guten Schluss, rufen wir unsere Funktion recursiv auf, solange wir noch nicht 100% haben.

if(ajax.status!=100) {
	load();
}

Die ganze load() Funktion:

function load() {
	$.ajax({
		// Welche URL soll aufgerufen werden?
		url: './ajax.php?status='+$( "#progressbar" ).progressbar( "value" ),
		// Wird ausgeführt, wenn die Datei erfolgreich requestet wurde
		success: function(data) {
			/** 
			* PHP liefert ein JSON Objekt zurück, welches wir im
			* JavaScript Code ausführen müssen, um ein Objekt zu erhalten.
			* Danach können wir mittels ajax.message und ajax.status auf unser
			* zuvor erstelltes PHP Array zu greifen. Wenn ein neuer Index im PHP Array
			* hinzugefügt wird, können wir mittels ajax.neuerIndex auch im JS darauf
			* zu greifen.
			**/
			
			ajax = eval('(' + data + ')');
			
			// Überprüfen, ob ein JS Objekt da ist.
			if(ajax!=false) {
				// Updaten unserer Progressbar auf den aktuellen Stand
				$("#progressbar").progressbar({
					value: ajax.status
				});
				
				// Die von PHP generierte Meldung dem Benutzer darstellen
				$("#message").html( ajax.message );
				
				// Solange wir nicht 100% haben müssen wir die Datei nochmal aufrufen...
				if(ajax.status!=100) {
					load();
				}
			}
		}
	});
}

Und nochmal beide erstellten Dateien zum Schluss:

Die index.php

Die gesamte index.php

<html>
	<head>
		<title>jQuery UI Progressbar</title>
		<link type="text/css" href="./css/ui-lightness/jquery-ui-1.8.13.custom.css" rel="stylesheet" />
		
		<script type="text/javascript" src="./js/jquery-1.5.1.min.js"></script>
		<script type="text/javascript" src="./js/jquery-ui-1.8.13.custom.min.js"></script>
		<script type="text/javascript">
			$(function(){
				/* Progessbar definieren */
				$("#progressbar").progressbar({
					value: 0 
				});
				
				// Funktion, die das Laden anstupst
				function load() {
					$.ajax({
						// Welche URL soll aufgerufen werden?
						url: './ajax.php?status='+$( "#progressbar" ).progressbar( "value" ),
						// Wird ausgeführt, wenn die Datei erfolgreich requestet wurde
						success: function(data) {
							/** 
							* PHP liefert ein JSON Objekt zurück, welches wir im
							* JavaScript Code ausführen müssen, um ein Objekt zu erhalten.
							* Danach können wir mittels ajax.message und ajax.status auf unser
							* zuvor erstelltes PHP Array zu greifen. Wenn ein neuer Index im PHP Array
							* hinzugefügt wird, können wir mittels ajax.neuerIndex auch im JS darauf
							* zu greifen.
							**/
							
							ajax = eval('(' + data + ')');
							
							// Überprüfen, ob ein JS Objekt da ist.
							if(ajax!=false) {
								// Updaten unserer Progressbar auf den aktuellen Stand
								$("#progressbar").progressbar({
									value: ajax.status
								});
								
								// Die von PHP generierte Meldung dem Benutzer darstellen
								$("#message").html( ajax.message );
								
								// Solange wir nicht 100% haben müssen wir die Datei nochmal aufrufen...
								if(ajax.status!=100) {
									load();
								}
							}
						}
					});
				}
				
				load(); // Das erste Starten unserer Funktion
			});
		</script>
		
		<style>
			/* Größe für die Progressbar */
			#progressbar {
				width:300px;
				height: 20px;
			}
		</style>
	</head>
	<body>
		Lädt: 
		<!--Die Progressbar-->
		<div id="progressbar"></div>
		
		<!-- Div Platzhalter für eigene von PHP generierte Nachrichten -->
		<div id="message">Lädt...</div>
	</body>
</html>	

Die ajax.php

Die gesamte ajax.php

<?php

$zufall = rand(1,3); // Zufällige länge der Aktion simulieren

sleep($zufall); // Simulieren einer langen Aktion...

// Unser $php_array ist ein Array, welches nacher als JSON Objekt ausgeben wird
// Enthält unseren Prozessfortschritt, als Prozentwert
$php_array['status'] = $_GET['status']+($zufall*3);

// Bei 100% ist Schluss ;)
if($php_array['status']>100) {
	$php_array['status'] = 100;
}

// Eine von Nachricht an dem Benutzer aus PHP
if($php_array['status'] != 100) {
	$php_array['message'] = 'Aktueller Status <b>'.$php_array['status'].'%</b> von 100%, Differenz: '.(100-$php_array['status']);
} else {
	$php_array['message'] = 'Juhu endlich geschafft! ;)';
}


// Ausgabe des PHP Arrays als JSON Objekt
echo json_encode($php_array);


Comments

16 responses to “jQuery UI, Ajax animierter Ladebalken”

  1. Sehr schön geschrieben das ganze.
    Gibt es auch eine Möglichkeit, dass wenn in der ajax.php ein Fehler aufgetreten ist (Beispiel: Parse Error), dieser auch in der index.php angezeigt wird?

    Gruß und Danke,
    $foo

  2. Hallo,

    ich hab euer Tutorial mal nach gebastelt und wollte euch mal etwas Kritik dazu da lassen, hoffe damit haben es Andere leichter beim Nachbasteln.

    1) In die HTML-Seite muss noch eine Stylesheetdatei ( jquery-ui-1.8.13.custom.css ) eingebunden werden, diese wird im Tutorial nicht erwähnt ist aber am Ende bei den downloadbaren Seiten drin. Wenn man also mit bastelt und nicht downloaded wundert man sich. Auch die Progressbar bekommt CSS-Angaben ab:
    <style>
    /* Größe für die Progressbar */
    #progressbar {
    width:300px;
    height: 20px;
    }
    </style>

    3) Wenn man mit bastelt und nicht downloaded gibt es genau an dieser Stelle bei mir ein Problem:
    <div id=”progressbar”></div>

    <!– Div Platzhalter für eigene von PHP generierte Nachrichten –>
    <div id=”message”>Lädt…</div>

    Bei mir passiert es das der weiße Hintergrund in einer Zeile ist und der Ladebalken in der Nächsten. Seltsam ist das schon, die Lösung ist aber sehr einfach.
    <div id=”progressbar”></div><div id=”message”>Lädt…</div>

    2) Ein Codebeispiel wäre klasse, wie man das Warten durch z.B. 4 Funktionen austauschen könnte. So das er nach jeder Funktion die Progressbar aktualisiert.

    2) Die Installation von JQuery-UI sollte Bilder, CSS-Dateien und JS-Dateien bei euch ablegen. Bei mir war beim ersten Versuch nicht alles da.

  3. Vielen Dank für die Antwort, sobald ich etwas Zeit habe, werde ich diese Punkte berücksichtigen und das Tutorial überarbeiten.

    Gruß
    danza

  4. Sorry, aber entweder ich verstehe etwas nicht richtig, oder das Skript ist totaler Blödsinn.

    Das mag alles in der Simulation wunderbar funktionieren. Aber es scheitert ja schon daran, dass ich in der Realität kein $zufall berechnen lasse, welches ich zu $_GET[‘status’] hinzuaddieren könnte.

    Auch wird das PHP-Skript hier ja mehrfach aufgerufen, was auch die lange Aktion mehrfach ausführen würde. Und mal ganz abgesehen davon bekomme ich die allererste Progress-Information ja auch erst, wenn die lange Aktion bereits beendet wurde.

    Das einzige was ich mir funktionierend vorstellen könnte wäre, wenn die lange Aktion z.B. eine Datenbank-Abfrage ist, dass man erstmal die Anzahl der Datenbankeinträge ausliest, und die dann stückweise abarbeitet. Dann sollte man aber zusätzlich die ID des letzen Datenbankeintrages oder ähnliches übergeben, um dann jeweils die Abfrage an der Stelle fortsetzen zu können. Das Ergebnis der Abfrage müsste man dann auch mit Javascript zwischenspeichern und zum Schluss ausgeben.

  5. Hallo Tel,

    das hier ist nur eine Vereinfachung, du hast natürlich recht das es so keinen Sinn macht.

    Man bräucht:

    – Eine Datei/Funktion (z.B. slowFunction.php), welche angestoßen wird und die lange Operation ausführt wird und irgendwo ihren Fortschritt/Status meldet. Welche z.B. deine lange Datenbank Aktion ausführt.

    – Die index.php die dem User den nötigen JS/HTML Source Code bereitstellt, in der die Fortschritte gespeichert werden.

    – Die ajax.php, die parktisch die Kupplung zwischen dem langen Prozess (slowFunction.php) ist und dem User interface (index.php). Die ajax.php würde den Status von der slowFunction.php auslesen und der index.php, dem User interface anzeigen, sodass der mögliche Nutzer Feedback bekäme.

    Wie du merkst wurde hier die Datei weggelassen, welche die langsame Funktion ausführt. Hier wurde nur das Prinzip vom Datenaustausch zwischen Server und Client dargestellt mithilfe von JSON.

  6. Andreas Avatar

    Besteht die Möglichkeit, dass du mal ein Beispiel erstellst, wo folgendes passieren soll:

    – Aufruf der Seite
    – Ladebalken anzeigen
    – mysql query im Hintergrund ausführen
    – Ladebalken nach 100% verschwinden lassen und Tabelle mit Mysql Werten anzeigen

    Wäre suüper cool!!!! Danke dir

  7. Das Problem ist das man von MySQL Abfragen keinen Status ermitteln kann, deshalb keine Progressbar von einer MySQL Abfrage machen kann.

    Man könnte allerdings dem User visuell vortäuschen einen Ladebalken und direkt danach die nachgeladenen Daten per Ajax anzeigen.

    Ein Tutorial dazu wäre Vorstellbar in den nächsten 2-3 Tagen.

    Gruß
    Jannik

  8. Hey Jannik,

    ich will nicht drängeln, aber ich schau nunmehr täglich vorbei, ob das von Andreas vorgeschlagene Tutorial mit der MYSQL-Implentierung schon hier zu sehen ist :)))

    LG alexander

  9. hi. wie würde der code den aussehen wenn man z.b. 50 bilder runterladen will

    $picture = "http://www.computerbase.de/design/logo.png?20111211";
    for ($i=1; $i<=50; $i++)
    {
    copy($picture, 'test/'.$i.'.jpg');
    }

    das mit dem zufall ist klar. aber wie kann man das so lösen`?

  10. Es gibt ein neues Tutorial über jQuery in Verbindung mit MySQL Datenbanken: http://d4nza.de/blog/tutorials/jquery-ajax-mysql-tabellen-editieren-tutorial

  11. Hallo,

    können Sie mir beschreiben wo ich eine MYSQL anweisung hinzufügen muss für einen Eintrag, wenn der Fortschrittsbalken fertig geladen ist.

    MFG nico

Leave a Reply

Your email address will not be published. Required fields are marked *

This site uses Akismet to reduce spam. Learn how your comment data is processed.