Webdesign-Blog

Hier finden sich vor allem Tipps, Tricks und Code-Schnipsel aus unserem Arbeitsalltag, die (in der Regel) nicht dutzendfach bei Google auftauchen, wenn man danach sucht. Viel Spaß!

Vorlage: Outlook HTML-Signatur mit Bild

Eine funktionierende HTML-Signatur mit Bild in Outlook zu erstellen birgt gewisse Herausforderungen. Mit dieser Vorlage (ZIP-Datei 32 KB) und der folgenden Kurzanleitung sollte das aber deutlich leichter von der Hand gehen:

  1. Signatur mit dem Namen „Mein Mail Footer“ in Outlook anlegen wie hier im JOC Blog beschrieben.
  2. Die Dateien aus der Vorlage in C:\Users\BENUTZERNAME\AppData\Roaming\Microsoft\Signatures kopieren.
  3. Inhalte in Mein-Mail-Footer.htm wie gewünscht anpassen und individualisieren. Hier gibt es ein ausführliches Tutorial zur Erstellung responsiver HTML-Mails.
  4. Grafiken in Mein-Mail-Footer-Dateien\filelist.xml aktualisieren.
  5. Falls die Signatur einen anderen Namen haben soll als „Mein Mail Footer“ alle Vorkommnisse von Mein-Mail-Footer-Dateien und Mein-Mail-Footer.htm entsprechend anpassen.
mehr lesen

Tipp: Boot-Camp-Meldung „Beim Kopieren der Windows-Installationsdateien ist ein Fehler aufgetreten.“

Beim Versuch Windows 10 per Boot Camp Assistent zu installieren kann es vorkommen, dass dieser die Installation mit der wenig aussagekräftigen Meldung abbricht:

Boot Camp-Installation fehlgeschlagen

Beim Kopieren der Windows-Installationsdateien ist ein Fehler aufgetreten.

Der Grund dafür ist, dass das Kopieren der Datei install.wim vom Windows-ISO-Image auf die vom Boot Camp Assistenten angelegten Partition OSXRESERVED fehlschlägt. Diese Partition ist mit FAT32 formatiert und kann keine Dateien größer 4 GB verarbeiten. Bei vielen Windows-Installationen ist die Datei install.wim jedoch größer. Genauer wird das Problem in diesem Artikel Using larger Windows 10 ISOs with Boot Camp Assistant von Twocanoes Software erklärt.

Um die Verwirrung für den Benutzer komplett zu machen, hängt Boot Camp anschließend mit der Meldung:

Partitionen zurücksetzen

Warte bis der Boot Camp Assistent die erstellten Partitionen entfernt hat …

Mit folgenden Schritten kommt man doch noch zum Ziel:

  1. Mac neu starten und mit dem Boot Camp Assistenten die Festplatte wieder zu einer Partition zusammenfassen:
  2. Die Software Boot Camp ISO Converter von Twocanoes Software laden und damit das Windows-Image anpassen:
  3. Boot Camp Assistent erneut starten und das angepasste Windows-Image verwenden

 

mehr lesen

PHP: Eigene Log-Dateien für Tests

Mit der folgenden Funktion lassen sich eigene Log-Files für Tests oder Debugging sichern. In diesem Beispiel werden die Werte der globalen PHP-Variablen $_GET und $_POST gesichert.

<?php

function write_test_log()
{
	// Parameter bestimmen
	$file_path='';
	$file_name='test.log';		

	// Datei öffnen / anlegen
	$handle=fopen($file_path.$file_name, 'a');

	// Daten zusammenstellen: URL
	$full_url = (isset($_SERVER['HTTPS']) ? 'https':'http').'://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'];

	// Daten zusammenstellen: $_GET
	ob_start();
	print_r($_GET);
	$output_GET=ob_get_clean();

	// Daten zusammenstellen: $_POST
	ob_start();
	print_r($_POST);
	$output_POST=ob_get_clean();

	// Daten sichern
	fwrite($handle, date('d.m.Y H:i:s').' ------------------------------'.chr(10).chr(10));
	fwrite($handle, 'URL: '.$full_url.chr(10).chr(10));
	fwrite($handle, '$_GET:'.chr(10));
	fwrite($handle, $output_GET.chr(10).chr(10));
	fwrite($handle, '$_POST:'.chr(10));
	fwrite($handle, $output_POST.chr(10));

	// Datei schließen
	fclose($handle);
}
if($_GET or $_POST) write_test_log();
mehr lesen

jQuery: Verwendung von DOMNodeInserted zur Anpassung dynamischer Inhalte

Manchmal ist es notwendig dynamisch erzeugte Elemente zu manipulieren, die zum Zeitpunkt von $(document).ready() oder $(window).load() noch nicht vorhanden sind. Dafür ist das Event $('body').on('DOMNodeInserted') sehr nützlich.

Im folgenden Beispiel wird ein von Magnific Popup dynamisch erzeugtes YouTube-Iframe auf die No-Cookie-Variante von YouTube geändert:

jQuery(document).ready(function($)
{
	// Event-Listener für DOMNodeInserted
	$('body').on('DOMNodeInserted', function()
	{
		// Prüfen, ob das gesuchte Iframe ins DOM eingefügt wurde
		var mfp_iframe=$(this).find('iframe.mfp-iframe');
		if(mfp_iframe.length)
		{
			// Parameter vorbereiten
			var src=mfp_iframe.attr('src');
			var src_no_cookie=src.replace('youtube.com', 'youtube-nocookie.com');

			// Iframe anpassen
			mfp_iframe.attr('src', src_no_cookie);
			mfp_iframe.attr('rel', '0');
		}
	});
});
mehr lesen

WordPress: Ausgabetexte aus Themes und Plugins ändern

Manchmal sind Wörter oder Formulierungen in Themes beziehungsweise Plugins enthalten, die einem einfach nicht gefallen. Falls es sich hierbei um eine Übersetzung handelt, kann diese mit dem Plugin Loco Translate ändern.

Ansonsten kann man mit der folgenden kleinen PHP-Funktion beliebige Ausgabetexte aus Themes und Plugins ändern:

function my_text_strings( $translated_text, $text, $domain )
{
	switch ( $translated_text )
	{
		case 'Dieser Text ist nicht schön :-(':
			$translated_text = __( 'Dieser Text ist viel besser :-)', $domain );
		break;
	}

	return $translated_text;
}
add_filter('gettext', 'my_text_strings', 20, 3);
mehr lesen

WordPress: Benutzer per PHP anlegen

Manchmal kommt es vor, dass man die FTP-Zugangsdaten zu einer Website hat, aber keinen WordPress-Zugang. Der Kunde kennt sich nicht aus und der Webdesigner, der die Seite mal vor langer Zeit erstellt hat, ist nicht mehr greifbar. In so einem Fall leistet diese kleine PHP-Funktion in den functions.php sehr gute Dienste:

function add_admin_user()
{
	$login = 'myself';
	$passw = 'very#secret';
	$email = 'me@example.com';

	if ( !username_exists( $login )  && !email_exists( $email ) ) {
		$user_id = wp_create_user( $login, $passw, $email );
		$user = new WP_User( $user_id );
		$user->set_role( 'administrator' );
	}
}
add_action('init','add_admin_user');
mehr lesen

JavaScript: URL-Parameter abfragen

Mit dieser kleinen Funktion lassen sich in JavaScript URL-Parameter / Query-Strings abfragen:

// URL-Parameter abfragen
function getUrlParameterByName(name, url)
{
	if (!url) url = window.location.href;
	name = name.replace(/[\[\]]/g, "\\$&");
	var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"), results = regex.exec(url);
	if (!results) return null;
	if (!results[2]) return '';
	return decodeURIComponent(results[2].replace(/\+/g, " "));
}

alert(getUrlParameterByName('mein-url-parameter'));
mehr lesen

PHP: ZIP-Archive extrahieren

Trotz immer schneller werdenden Internet-Verbindungen dauert das Hochladen von Verzeichnissen mit tausenden von Dateien und Unterverzeichnissen, wie das zum Beispiel bei kompletten WordPress-Installationen oder komplexen Themes der Fall ist, immer noch seine Zeit.

Deutlich schneller ist es, statt dessen ein ZIP-Archiv hochzuladen. Falls man auf dem Server keine SSH-Zugang hat, lässt sich die ZIP-Datei mit folgendem kleinen PHP-Skript zu extrahieren.

<?php 
// Dateiname bestimmen (muss hier im selben Verzeichnis liegen)
$file="meine-datei.zip";

// Absoluten Pfad bestimmen
$path=pathinfo(realpath($file), PATHINFO_DIRNAME);

// ZIP-Datei öffnen und prüfen
$zip=new ZipArchive;
$res=$zip->open($file);
if ($res===TRUE)
{
	// ZIP-Datei extrahieren
	$zip->extractTo($path);
	$zip->close();

	// Erfolgsmeldung
	echo("<h2>Erfolg :-)</h2>");
	echo("<p><code><strong>$file</strong></code> erforgreich in das Verzeichnis <code><strong>$path</strong></code> endpackt.</p>");
}
// Fehlermeldung
else
{
	echo("<h2>Fehler :-(</h2>");
	echo("<p><code><strong>$file</strong></code> konnte nicht geöffnet werden.</p>");
}
mehr lesen

WordPress: Seitenweite Suche mit Omnisearch und Search Everything

Leider verfügt  WordPress über keine seitenweite Suche, die in allen Post Types gleichzeitig sucht. Das ist aber vor allem bei großen Seiten sehr praktisch. Zum Glück lässt sich diese Funktion relativ einfach mit den Plugins Jetpack Omnisearch und Search Everything nachrüsten:

Schritt 1: Jetpack installieren

Jetpack installieren und Omnisearch aktivieren:

Jetpack Omnisearch

Tipp: Man muss Jetpack nicht zwingend mit WordPress.com verbinden, Omnisearch lässt sich auch im Development Mode verwenden. Dazu einfach die Zeile define('JETPACK_DEV_DEBUG', true); in die wp-config.php einfügen.

mehr lesen…

mehr lesen

JavaScript: Session-Daten mit JavaScript

Vor allem bei Websites mit aktivem Caching, die nicht bei jedem Aufruf dynamisch neu erstellt werden, kann es praktisch sein, Nutzereingaben mit den JavaScript-Funktionen sessionStorage.setItem() und sessionStorage.getItem() zu sichern. Hier ein einfaches Beispiel:

// Beispiel: Verwendung sessionStorage.setItem()
$('#my_alert .close').click(function() {
	sessionStorage.setItem('popup', 'closed');
});

// Beispiel: Verwendung sessionStorage.getItem()
if(sessionStorage.getItem('popup')=='closed') {
	$('#my_alert').remove();
}
mehr lesen

jQuery: Events und Statusabfragen für responsives Webdesign

Mit dieser kleinen Funktion lassen sich in JavaScript URL-Parameter / Query-Strings abfragen:

// URL-Parameter abfragen
function getUrlParameterByName(name, url)
{
	if (!url) url = window.location.href;
	name = name.replace(/[\[\]]/g, "\\$&");
	var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"), results = regex.exec(url);
	if (!results) return null;
	if (!results[2]) return '';
	return decodeURIComponent(results[2].replace(/\+/g, " "));
}

alert(getUrlParameterByName('mein-url-parameter'));
mehr lesen

jQuery: HTML-Formular per AJAX senden

So lässt sich ein bestehendes HTML-Formular samt aller Input-Felder mit jQuery per AJAX senden:

jQuery(document).ready(function($)
{
	$("#my_form").submit(function(event) {
		// Standard-Aktion abbrechen
		event.preventDefault();	

		// Formular per AJAX senden
		var form=$(this);
		$.ajax({
			type: 'POST',
			url: form.prop('action'),
			data : form.serialize(),
			dataType: 'json',
			encode: true
		}).done(function(data) {
			// Aktionen bei Erfolg
			console.log('done: '+data);
		}).fail(function(data) {
			// Aktionen bei einem Fehler
			console.log('fail: '+data);			
		});
	});
});
mehr lesen

PHP: Zeilenanzahl großer Dateien ermitteln

Auf Linux/Unix-Systemen lässt sich die Zeilenanzahl (sehr) großer Textdateien mit exec() und wc -l ermitteln:

$logfile_location='logs/my_logfile.txt';
if(file_exists($logfile_location)) $logfile_lines=intval(exec("wc -l ".$logfile_location));
else $logfile_lines=0;
mehr lesen

WordPress: Sprache und Übersetzung in PHP anpassen

Die Spracheinstellungen lassen sich in WordPress nicht nur über die Einstellungen sondern auch über den Filter add_filter(‘locale’, …) in den functions.php dynamisch anpassen. Die folgende Funktion zum Beispiel setzt Französisch als Sprache für die Website wohingegen der WordPress-Adminbereich auf deutsch ausgegeben wird:

// WordPress Locale setzen
function set_locale_frontend($locale)
{
	if(is_admin()) return 'de_DE';
	else return 'fr_FR'
}
add_filter('locale', 'set_locale_frontend');

Das kann für Multisite-Übersetzungen sehr praktisch sein, wenn man den Adminbereich nicht in der Übersetzungssprache bedienen will.

Mit der Funktion load_textdomain() lässt sich wiederum eine weitere Übersetzung laden:

echo(__('Hallo Welt!', 'meine_text_domain')); // Bonjour tout le monde!

load_textdomain('medianotions', get_stylesheet_directory().'/languages/en_GB.mo');

echo(__('Hallo Welt!', 'meine_text_domain')); // Hello world!

Bezüglich erstellen und bearbeiten von Übersetzungsdateien ist das Plugin Loco Translate das Mittel der Wahl:

Loco-Translate

mehr lesen

WordPress: robots.txt dynamisch anpassen

Die robots.txt wird in WordPress dynamisch erzeugt. Die einfachste Möglichkeit diese anzupassen ist, eine statische robots.txt in das Root-Verzeichnis der WordPress-Installation anzulegen. Die andere, flexiblere Möglichkeit ist in der functions.php mit folgendem Filter zu arbeiten:

// robots.txt anpassen
function robots_mod( $output, $public )
{
	if($public)
	{
		$output .= "Allow: /*.js$\n";
		$output .= "Allow: /*.css$\n";
	}
	
	return $output;
}
add_filter('robots_txt', 'robots_mod', 10, 2);

Damit ist es möglich die Ausgabe der robots.txt mit einer eigenen Logik zu verknüpfen:

// robots.txt anpassen
function robots_mod( $output, $public )
{
	if($_SERVER['HTTP_HOST']=='hide-from-search-engines.com') $output = "Disallow: /\n";
	
	return $output;
}
add_filter('robots_txt', 'robots_mod', 10, 2);

Performance-Tipp: Die robots.txt wird von Suchmaschinen zum Teil sehr oft aufgerufen. Falls das verwendete Caching-Plugin die robots.txt nicht abdeckt und man keine dynamische Anpassung benötigt, bietet es sich an die robots.txt als statische Text-Datei im Webroot-Verzeichs zu hinterlegen.

mehr lesen

PHP: Mit strpos_all() alle Vorkommnisse in einem String finden

Mit dieser Funktion lassen sich alle Vorkommnisse in von $needle in $haystack finden. Zurückgegeben wird ein Array mit den Positionen:

function strpos_all($haystack, $needle)
{
	$lastPos = 0;
	$positions = array();

	while (($lastPos = strpos($haystack, $needle, $lastPos))!== false) {
	    $positions[] = $lastPos;
	    $lastPos = $lastPos + strlen($needle);
	}

	return $positions;
}

// Aufruf
$str_positions=strpos_all('a', 'abcd ab abcdefg abcde');
mehr lesen

Website-Zoom mit jQuery und CSS

Mit der CSS-Eigenschaft transform: scale() und etwas jQuery lässt sich ziemlich gut das ein- und auszoomen einer Website simulieren. Das ist für alle praktisch, die Ihren Benutzern entsprechende Buttons auf ihrer Website anbieten wollen. Hier unsere Lösung:

<!-- Trigger -->
<ul id="zoom_triggers">
	<li><a id="zoom_in">Vergrößern</a></li>
	<li><a id="zoom_out">Verkleinern</a></li>
	<li><a id="zoom_reset">Zurücksetzen</a></li>
</ul>

<script>
	jQuery(document).ready(function($)
	{
		// Zoom-Level setzen
		var zoom_level=100;

		// Click-Events
		$('#zoom_in').click(function() { zoom_page(10, $(this)) });
		$('#zoom_out').click(function() { zoom_page(-10, $(this)) });
		$('#zoom_reset').click(function() { zoom_page(0, $(this)) });

		// Zoom-Funktion
		function zoom_page(step, trigger)
		{
			// Nur zwei Schritte ein- beziehungsweise ausblenden
			if(zoom_level>=120 && step>0 || zoom_level<=80 && step<0) return;

			// Zoom berechnen / zurücksetzen
			if(step==0) zoom_level=100;
			else zoom_level=zoom_level+step;
			
			// Zoom per CSS setzen
			$('body').css({
				transform: 'scale('+(zoom_level/100)+')', // Zoom anpassen
				transformOrigin: '50% 0' // Ausgangspunkt für transform scale setzen
			});

			// Seitenbreite am Zoom anpassen
			if(zoom_level>100) $('body').css({ width: (zoom_level*1.2)+'%' });
			else $('body').css({ width: '100%' });

			// Trigger deaktivieren / aktivieren (per CSS entsprechend optisch kennzeichnen)
			if(zoom_level>=120 || zoom_level<=80) trigger.addClass('disabled');
			else trigger.parents('ul').find('.disabled').removeClass('disabled');
			if(zoom_level!=100) $('#zoom_reset').removeClass('disabled');
			else $('#zoom_reset').addClass('disabled');
		}
	});
</script>
mehr lesen

PHP: file_put_contents() via FTP mit ftp_file_put_contents()

Die robots.txt wird in WordPress dynamisch erzeugt. Die einfachste Möglichkeit diese anzupassen ist, eine statische robots.txt in das Root-Verzeichnis der WordPress-Installation anzulegen. Die andere, flexiblere Möglichkeit ist in der functions.php mit folgendem Filter zu arbeiten:

// robots.txt anpassen
function robots_mod( $output, $public )
{
	if($public)
	{
		$output .= "Allow: /*.js$\n";
		$output .= "Allow: /*.css$\n";
	}
	
	return $output;
}
add_filter('robots_txt', 'robots_mod', 10, 2);

Damit ist es möglich die Ausgabe der robots.txt mit einer eigenen Logik zu verknüpfen:

// robots.txt anpassen
function robots_mod( $output, $public )
{
	if($_SERVER['HTTP_HOST']=='hide-from-search-engines.com') $output = "Disallow: /\n";
	
	return $output;
}
add_filter('robots_txt', 'robots_mod', 10, 2);

Performance-Tipp: Die robots.txt wird von Suchmaschinen zum Teil sehr oft aufgerufen. Falls das verwendete Caching-Plugin die robots.txt nicht abdeckt und man keine dynamische Anpassung benötigt, bietet es sich an die robots.txt als statische Text-Datei im Webroot-Verzeichs zu hinterlegen.

mehr lesen

PHP: XSS-Attacken auf bestehenden Websites verhindern

Eine bestehende, eventuell komplexere Website nachträglich vor Cross-Site-Scripting-Attacken (XSS) zur sichern, kann sich als sehr aufwändig erweisen. Mit diesem PHP-Skript, dass bei jedem Aufruf der Website vor allen anderen Funktionen ausgeführt werden sollte, lassen sich die meisten Angriffsszenarien entschärfen.

function xss_protect($string)
{
	// nur Strings prüfen
	if(!is_string($string)) return $string;

	// eventuelle Kodierung berücksichtigen
	$string=urldecode($string);

	// Ausführbaren Code entfernen
	$string=strip_tags($string);
	$string=htmlspecialchars($string);		
	$string=filter_var($string, FILTER_SANITIZE_STRING);		

	return $string;
}
if(is_array($_GET)) $_GET = array_map("xss_protect", $_GET);
if(is_array($_POST)) $_POST = array_map("xss_protect", $_POST);
if(is_array($_REQUEST)) $_REQUEST = array_map("xss_protect", $_REQUEST);
$_SERVER['REQUEST_URI'] = array_map("xss_protect", $_SERVER['REQUEST_URI']);
$_SERVER['REDIRECT_QUERY_STRING'] = array_map("xss_protect", $_SERVER['REDIRECT_QUERY_STRING']);
$_SERVER['QUERY_STRING'] = array_map("xss_protect", $_SERVER['QUERY_STRING']);
mehr lesen

Tipp: mit draGGradients einfach radiale CSS-Verläufe erstellen

Die robots.txt wird in WordPress dynamisch erzeugt. Die einfachste Möglichkeit diese anzupassen ist, eine statische robots.txt in das Root-Verzeichnis der WordPress-Installation anzulegen. Die andere, flexiblere Möglichkeit ist in der functions.php mit folgendem Filter zu arbeiten:

// robots.txt anpassen
function robots_mod( $output, $public )
{
	if($public)
	{
		$output .= "Allow: /*.js$\n";
		$output .= "Allow: /*.css$\n";
	}
	
	return $output;
}
add_filter('robots_txt', 'robots_mod', 10, 2);

Damit ist es möglich die Ausgabe der robots.txt mit einer eigenen Logik zu verknüpfen:

// robots.txt anpassen
function robots_mod( $output, $public )
{
	if($_SERVER['HTTP_HOST']=='hide-from-search-engines.com') $output = "Disallow: /\n";
	
	return $output;
}
add_filter('robots_txt', 'robots_mod', 10, 2);

Performance-Tipp: Die robots.txt wird von Suchmaschinen zum Teil sehr oft aufgerufen. Falls das verwendete Caching-Plugin die robots.txt nicht abdeckt und man keine dynamische Anpassung benötigt, bietet es sich an die robots.txt als statische Text-Datei im Webroot-Verzeichs zu hinterlegen.

mehr lesen

Tipp: Einfach zur individuellen Google-Maps-Integration mit dem MapBuildr

Eine bestehende, eventuell komplexere Website nachträglich vor Cross-Site-Scripting-Attacken (XSS) zur sichern, kann sich als sehr aufwändig erweisen. Mit diesem PHP-Skript, dass bei jedem Aufruf der Website vor allen anderen Funktionen ausgeführt werden sollte, lassen sich die meisten Angriffsszenarien entschärfen.

function xss_protect($string)
{
	// nur Strings prüfen
	if(!is_string($string)) return $string;

	// eventuelle Kodierung berücksichtigen
	$string=urldecode($string);

	// Ausführbaren Code entfernen
	$string=strip_tags($string);
	$string=htmlspecialchars($string);		
	$string=filter_var($string, FILTER_SANITIZE_STRING);		

	return $string;
}
if(is_array($_GET)) $_GET = array_map("xss_protect", $_GET);
if(is_array($_POST)) $_POST = array_map("xss_protect", $_POST);
if(is_array($_REQUEST)) $_REQUEST = array_map("xss_protect", $_REQUEST);
$_SERVER['REQUEST_URI'] = array_map("xss_protect", $_SERVER['REQUEST_URI']);
$_SERVER['REDIRECT_QUERY_STRING'] = array_map("xss_protect", $_SERVER['REDIRECT_QUERY_STRING']);
$_SERVER['QUERY_STRING'] = array_map("xss_protect", $_SERVER['QUERY_STRING']);
mehr lesen

WordPress: Browser und OS als CSS-Klassen im Body-Tag

Zum Glück benötigt man als Web-Entwickler Browser-Weichen mittlerweile nicht mehr so oft wie früher. Trotzdem kommt es immer noch vor, dass Darstellungsunterschiede angepasst werden müssen. Mit diesen beiden Funktionen in der functions.php lassen sich die wichtigsten Browser und Betriebssysteme als CSS-Klassen in den Body-Tag einbinden:

// Client-Eigenschaften bestimmen
function detect_client_properties()
{
	// Client: Browser
	if(!isset($_SESSION['CLIENT_BROWSER']))
	{
		if(strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 7')) $browser='ie_7';
		elseif(strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 8')) $browser='ie_8';
		elseif(strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 9')) $browser='ie_9';
		elseif(strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 10')) $browser='ie_10';
		elseif(strpos($_SERVER['HTTP_USER_AGENT'], 'Trident') and strpos($_SERVER['HTTP_USER_AGENT'], 'rv:11')) $browser='ie_11';
		elseif(strpos($_SERVER['HTTP_USER_AGENT'], 'Chrome')) $browser='chrome';
		elseif(strpos($_SERVER['HTTP_USER_AGENT'], 'Safari')) $browser='safari';
		elseif(strpos($_SERVER['HTTP_USER_AGENT'], 'Firefox')) $browser='firefox';
		else $browser=false;

		if($browser) $_SESSION['CLIENT_BROWSER']=$browser;
		else $_SESSION['CLIENT_BROWSER']=false;
	}		

	// Client: Betriebssystem
	if(!isset($_SESSION['CLIENT_OS']))
	{
		if(strpos($_SERVER['HTTP_USER_AGENT'], 'Macintosh')) $os='mac';
		elseif(strpos($_SERVER['HTTP_USER_AGENT'], 'Windows')) $os='win';
		elseif(strpos($_SERVER['HTTP_USER_AGENT'], 'iPhone')) $os='ios';
		elseif(strpos($_SERVER['HTTP_USER_AGENT'], 'iPad')) $os='ios';
		else $os=false;

		if($os) $_SESSION['CLIENT_OS']=$os;
		else $_SESSION['CLIENT_OS']=false;
	}

	// Client: Mobile
	if(!isset($_SESSION['CLIENT_IS_MOBILE']))
	{
		if(wp_is_mobile()) $_SESSION['CLIENT_IS_MOBILE']=true;
		else $_SESSION['CLIENT_IS_MOBILE']=false;
	}
}
add_action('init', 'detect_client_properties', 0);

// Body-CSS-Klassen ergänzen
function additional_body_classes($classes)
{
	// Browser
	if($_SESSION['CLIENT_BROWSER']) $classes[]=$_SESSION['CLIENT_BROWSER'];

	// Betriebssystem
	if($_SESSION['CLIENT_OS']) $classes[]=$_SESSION['CLIENT_OS'];

	// Mobile
	if($_SESSION['CLIENT_IS_MOBILE']) $classes[]='mobile';

	return $classes;
}
add_filter('body_class', 'additional_body_classes', 99);

Auf ähnliche Weise lassen sich auch weitere CSS-Klassen im Body-Tag einfügen, zum Beispiel die aktuelle Sprache bei mehrsprachigen Websites oder aktuelle Kategorien, Templates, Parent-Seite usw.

mehr lesen

WordPress: Eigene Bildgrößen definieren

Zum Glück benötigt man als Web-Entwickler Browser-Weichen mittlerweile nicht mehr so oft wie früher. Trotzdem kommt es immer noch vor, dass Darstellungsunterschiede angepasst werden müssen. Mit diesen beiden Funktionen in der functions.php lassen sich die wichtigsten Browser und Betriebssysteme als CSS-Klassen in den Body-Tag einbinden:

// Client-Eigenschaften bestimmen
function detect_client_properties()
{
	// Client: Browser
	if(!isset($_SESSION['CLIENT_BROWSER']))
	{
		if(strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 7')) $browser='ie_7';
		elseif(strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 8')) $browser='ie_8';
		elseif(strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 9')) $browser='ie_9';
		elseif(strpos($_SERVER['HTTP_USER_AGENT'], 'MSIE 10')) $browser='ie_10';
		elseif(strpos($_SERVER['HTTP_USER_AGENT'], 'Trident') and strpos($_SERVER['HTTP_USER_AGENT'], 'rv:11')) $browser='ie_11';
		elseif(strpos($_SERVER['HTTP_USER_AGENT'], 'Chrome')) $browser='chrome';
		elseif(strpos($_SERVER['HTTP_USER_AGENT'], 'Safari')) $browser='safari';
		elseif(strpos($_SERVER['HTTP_USER_AGENT'], 'Firefox')) $browser='firefox';
		else $browser=false;

		if($browser) $_SESSION['CLIENT_BROWSER']=$browser;
		else $_SESSION['CLIENT_BROWSER']=false;
	}		

	// Client: Betriebssystem
	if(!isset($_SESSION['CLIENT_OS']))
	{
		if(strpos($_SERVER['HTTP_USER_AGENT'], 'Macintosh')) $os='mac';
		elseif(strpos($_SERVER['HTTP_USER_AGENT'], 'Windows')) $os='win';
		elseif(strpos($_SERVER['HTTP_USER_AGENT'], 'iPhone')) $os='ios';
		elseif(strpos($_SERVER['HTTP_USER_AGENT'], 'iPad')) $os='ios';
		else $os=false;

		if($os) $_SESSION['CLIENT_OS']=$os;
		else $_SESSION['CLIENT_OS']=false;
	}

	// Client: Mobile
	if(!isset($_SESSION['CLIENT_IS_MOBILE']))
	{
		if(wp_is_mobile()) $_SESSION['CLIENT_IS_MOBILE']=true;
		else $_SESSION['CLIENT_IS_MOBILE']=false;
	}
}
add_action('init', 'detect_client_properties', 0);

// Body-CSS-Klassen ergänzen
function additional_body_classes($classes)
{
	// Browser
	if($_SESSION['CLIENT_BROWSER']) $classes[]=$_SESSION['CLIENT_BROWSER'];

	// Betriebssystem
	if($_SESSION['CLIENT_OS']) $classes[]=$_SESSION['CLIENT_OS'];

	// Mobile
	if($_SESSION['CLIENT_IS_MOBILE']) $classes[]='mobile';

	return $classes;
}
add_filter('body_class', 'additional_body_classes', 99);

Auf ähnliche Weise lassen sich auch weitere CSS-Klassen im Body-Tag einfügen, zum Beispiel die aktuelle Sprache bei mehrsprachigen Websites oder aktuelle Kategorien, Templates, Parent-Seite usw.

mehr lesen

PHP: HTTP / HTTPS bestimmen

Update 26. Mai 2014: Der Server-Port für HTTPS-Verbindungen muss je nach Server-Konfiguration nicht zwingend 443 sein.

So lässt sich mit PHP bestimmen ob eine Website über HTTP oder HTTPS aufgerufen wird:

// HTTP / HTTPS bestimmen
if(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS']!='off' or $_SERVER['SERVER_PORT']==443) $protocol='https';
else $protocol='http';
mehr lesen

Tipp: Syntax-Highlighting für WordPress mit PRISM

Update 26. Mai 2014: Der Server-Port für HTTPS-Verbindungen muss je nach Server-Konfiguration nicht zwingend 443 sein.

So lässt sich mit PHP bestimmen ob eine Website über HTTP oder HTTPS aufgerufen wird:

// HTTP / HTTPS bestimmen
if(!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS']!='off' or $_SERVER['SERVER_PORT']==443) $protocol='https';
else $protocol='http';
mehr lesen

WordPress: P-Tags um Shortcodes entfernen

Mit diesen beiden Filteraufrufen in der functions.php werden Shortcodes auch in Beitrags­zusammen­fassungen und Widgets ausgeführt:

// Shortcodes in der Zusammenfassung ausführen
add_filter('the_excerpt', 'do_shortcode');

// Shortcodes in Widgets ausführen
add_filter('widget_text', 'do_shortcode');
mehr lesen

Gravity Forms: deutsche Lokalisierung für die Datumsauswahl (Datepicker)

Für alle die ein Gravity-Forms Datumsfeld (Datepicker) verwenden und diesen aber nicht mit der englischen Lokalisierung belassen wollen, gibt es eine einfache Lösung. Gravity Forms nutzt den jQuery-Datepicker mit Lokalisierungen für viele Sprachen. Also einfach jQuery-Datepicker laden und die entsprechende Lokalisierungsdatei mit wp_enqueue_script() im Theme einbinden:

function my_theme_resources()
{
    // jQuery UI Datepicker-Lokalisierung laden
    wp_enqueue_script('jquery-ui-datepicker-de', get_stylesheet_directory().'/libs/jquery.ui.datepicker-de.min.js', array('jquery-ui-datepicker'));
}
add_action('wp_enqueue_scripts', 'my_theme_resources');
mehr lesen

Tipp: WordPress-Spickzettel für eigene Themes

Für alle die ein Gravity-Forms Datumsfeld (Datepicker) verwenden und diesen aber nicht mit der englischen Lokalisierung belassen wollen, gibt es eine einfache Lösung. Gravity Forms nutzt den jQuery-Datepicker mit Lokalisierungen für viele Sprachen. Also einfach jQuery-Datepicker laden und die entsprechende Lokalisierungsdatei mit wp_enqueue_script() im Theme einbinden:

function my_theme_resources()
{
    // jQuery UI Datepicker-Lokalisierung laden
    wp_enqueue_script('jquery-ui-datepicker-de', get_stylesheet_directory().'/libs/jquery.ui.datepicker-de.min.js', array('jquery-ui-datepicker'));
}
add_action('wp_enqueue_scripts', 'my_theme_resources');
mehr lesen