Data URIs vs. CSS-Sprites

CSS-Sprites sind eine elegante Möglichkeit um GET-Requests zu minimieren und daruch den Seitenaufbau zu beschleunigen. Dabei werden viele kleine Symbole in einer großen Grafik zusammengefasst und via CSS  immer nur der passende Ausschnitt der Grafik gezeigt. Eine andere Möglichkeit, GET-Requests zu sparen, besteht in der Verwendung des Data URI scheme.

<img src="data:image/png;base64,iVBORw0KGgoAAAANSU[...]FTkSuQmCC" alt="" />

Statt einer URL wird  direkt der Dateiinhalt Base64-Kodiert angegeben. Das Bild wird also mit dem HTML-Quelltext mitgeladen. Es ist kein separater GET-Request notwendig. Das funktioniert selbstverständlich analog in CSS-Dateien  und selbstverständlich nicht mit dem IE6/7.

body { background: url('data:image/png;base64,iVBOR[..]QmCC'); }

Der fehlende IE6/7 Support mag ein Grund für die geringe Verbreitung des Data URI scheme sein. Erschwerend hinzu kommt die Tatsache, dass das Laden des (langen) Base64-Strings das weitere Rendering der Webseite zunächst blockiert. Die Base64-Darstellung ist im übrigen ca. 1/3 größer als die binäre und kann selbstverständlich nicht vom Browser gecached werden.

PHP-Skript im Hintergrund ausführen #2

Die bereits erwähnte Methode über Content-Length funktioniert zwar etwas hakelig, ist aber in Webspace-Umgebungen oft die einzige Methode ein PHP-Skript im Hintergrund auszuführen.

Eine andere Methode (neben dem Cronjob) besteht darin, über exec einen Hintergrundprozess zu starten. Beispiel (Linux only):

<?php exec('/usr/bin/php -f /var/www/cron.php > /dev/null &') ?>

Mit -f wird die auszuführende Datei angegeben. In Shared-Hosting-Umgebungen wird man keinen Zugriff auf die php-binary haben. Wget hingegen sollte verfügbar oder zumindest installierbar sein. Mit wget kann man prima “Cronjobs” über HTTP-GET im Hintergrund anstoßen:

<?php exec('wget -bq -o /dev/null -O /dev/null -t 1 http://www.example.org/cron.php') ?>

Wget’s Parameter sind case-sensitive. -b sorgt dafür, dass der wget-Prozess im Hintergrund ausgeführt wird, -q unterdrückt jegliche Ausgabe, -o leitet die heruntergeladene Datei nach /dev/null, -O schreibt das Logfile ebenfalls ins Nirvana und -t 1 unternimmt nur einen Versuch die folgende URL aufzurufen.

reCAPTCHA Tricks ;)

reCAPTCHA ist ein sehr verbreiteter Captcha-Service der von Google betrieben wird. Viele Webseiten zeigen via reCAPTCHA-Webservice diese Captchas an, um Ihre menschlichen Besucher von Bots zu unterscheiden. Das Besondere: mit reCAPTCHA werden Bücher digitalisiert, bzw. OCR-Ergebnisse überprüft. Zur Lösung muss der Benutzer zwei Wörter eingeben, wovon aber nur eines bei reCAPTCHA bekannt ist. Beide Wörter stammen aus einem Buch-Scan (Google Books – aber auch andere). Das bekannte Wort wurde bereits durch reCAPTCHA-Benutzer bestätigt oder hat grundsätzlich eine hohe OCR-Genaugigkeit – das unbekannte hat eine niedrige Genauigkeit.

Beide Wörter werden zusätzlich verformt. Früher wurden auch verschiedene Objekte oder Striche über die Texte gelegt. Zur erfolgreichen Lösung reicht die Übereinstimmung des bekannten Wortes. Die Eingaben zum anderen Wort werden lediglich erfasst und bei entsprechender Häufung dazu verwendet das OCR-Ergebnis zu korrigieren bzw. zu bestätigen.

Das erklärt auch, warum bei reCAPTCHA teilweise wirre Worte erscheinen.

In diesem Fall genügt es einfach das zweite Wort einzugeben. Das erste kann frei erfunden werden. Captcha gelöst! Wer also nicht beim Digitalisieren behilflich sein will, der hält sich nicht lange mit dem entziffern auf, sondern gibt irgendetwas ein – das bekannte Wort (und nur darauf kommt es an) ist meist ohne viel Rätseln lesbar.

Apples consolidated.db visualisieren

Es wurde wohl schon genug über das Speichern von Bewegungsdaten auf Apples iPhone geschrieben. Nur eins noch: Mit Hilfe dieser Webseite kann man die consolidated.db (die böse Datei, in der all die Bewegungsdaten gespeichert sind) parsen, und übersichtlich in einer Google-Map darstellen. Das ganze passiert zu 100% Clientseitig mit Javascript. Ausgewählt werden kann direkt der iTunes-Backup-Ordner, oder besser, nur die consolidated.db via Drag&Drop. Bei meinen Tests hat das ausschließlich mit Google-Chrome funktioniert.

Besitzer eines Jailbroken iPhones finden die besagte Datei via scp in

/private/var/root/Library/Cache/locationd/consolidated.db

Übrigens: die Smartphone-Plattform der Datenkrake Goole scheint Apple da in nichts nachzustehen – zumindest beim Datensammeln. Deshalb rate ich allen ihre Häme besser zurückzuhalten ;)

jQuerys $-Funktion

Wie wir alle wissen, werden Variablen in JavaScript nicht mit einem vorangestellten Dollarzeichen kenntlich gemacht. Insofern ist das Dollarzeichen für Javascript einfach nur das 36. Zeichen der ASCII-Tabelle. Und zudem ein gültiges Zeichen für Funktionsnamen (selbiges gilt neben allen Buchstaben und Zahlen auch für den Unterstrich).

function Framework(id) {
    return document.getElementById(id);
}
 
var $ = Framework;

Jetzt ist $() ein Alias für die Funktion Framework(). Benutzt werden kann das jetzt schon wie bei jQuery:

var nav = $('nav');

Um es Framework zu nennen, ist es wohl noch etwas dünn. Erweitern wir unser Framework also um eine handliche Datumsfunktion. Analog zu jQuery, gibt diese Funktion die aktuelle Zeit zurück.

Framework.now = function() {
    return (new Date).getTime();
}
 
$.now(); // 1301227135 (unix timestamp)

Das ist immer noch recht lasch! Weiter geht’s: Mit Javascripts Prototype Object ist es möglich einer Klasse eine gewisse Eigenschaft/Methode zu geben, die automatisch alle Instanzen dieses Objektes ebenfalls haben. Damit kann man z.B. jedem JS-Array eine each()-Methode verpassen, oder alle HTML-Elemente um Funktionen erweitern. Letzteres nehmen wir mal als Beispiel:

Element.prototype.addClass = function(className) {
    this.className += ' ' + className;
}
$('myDiv').addClass('foo');

Das Chaining von Methoden hat jQuery bekannt gemacht. Nichts leichter als das! Dazu muss die jeweilige Methode nur das Objekt selbst zurückgeben. Wir passen also unsere “addClass” Methode an und erstellen eine weitere um das Chaining zu testen.

Element.prototype.addClass = function(className) {
    this.className += ' ' + className;
    return this;
}
Element.prototype.content = function(content) {
    this.innerHTML = content;
    return this;
}
$('myDiv').addClass('foo').content('bar');

Das ist jetzt natürlich alles nicht elegant gelöst und bestimmt auch nicht Cross-Browser tauglich (ich rede mit dir, IE!), verdeutlicht aber was so prinzipiell hinter einen Javascript-Framework steckt. Hier nochmal am Stück und mit gehighlightetem hervorgehobenem Syntax.

Merke: jQuery ist nur ein JavaScript-Framework. Mit jQuery kann man also auf keinen Fall mehr Dinge tun, als mit reinem Javascript selbst. Mit jQuery geht das meist nur einfacher und vor allem konsistenter zwischen verschiedenen Browser-Versionen.