Clientseitige Vorschau mit Plupload

Plupload bietet seit Version 2 die Möglichkeit, eine Vorschau der ausgewählten Dateien bereits vor dem eigentlich Upload, also beispielsweise in der Warteschlange, anzuzeigen.

Leider ist nicht wirklich dokumentiert, welche Methoden man verwenden muss, damit die Magie stattfindet.
Das jQuery UI Queue Widget unterstützt allerdings glücklicherweise Vorschaubilder, wodurch es nicht allzu schwer ist den entsprechenden Abschnitt im Quelltext zu finden.

Ich habe das mal zusammengefasst:

<div id="container">
    <a id="pickfiles" href="javascript:;">[Select files]</a> 
    <div id="preview"></div>
</div>
var uploader = new plupload.Uploader({
	runtimes : 'html5,flash',
	browse_button : 'pickfiles',
	container: 'container',
	url: "upload.php",
	max_file_size : '10mb',
	filters : [
		{title : "Image files", extensions : "jpg,gif,png"}
	],
	flash_swf_url : 'Moxie.swf'
});

uploader.init();

uploader.bind('FilesAdded', function(up, files) {
    $.each(files, function(){
        
		var img = new mOxie.Image();

		img.onload = function() {
			this.embed($('#preview').get(0), {
				width: 100,
				height: 100,
				crop: true
			});
		};

		img.onembedded = function() {
			this.destroy();
		};

		img.onerror = function() {
			this.destroy();
		};

		img.load(this.getSource());        
        
    });
});

Entscheidend ist die Verwendung von m0xie.Image. Diese Klasse bietet die Methode
embed() an, welche einem die ganze Arbeit abnimmt. Denn damit das Ganze in allen Browsern funktioniert, muss schon einiger Aufwand betrieben werden. Diese Methode fügt automagisch eine Vorschau in den gewünschten Ziel-Container ein. In modernen Browsern ist das eine Canvas, in anderen ein Data-URI oder Flash.

Dem Konstruktor der Klasse Image muss eine Datenquelle, also die gerade hinzugefügte Bilddatei, übergeben werden. Hierfür bietet die Klasse File die Methode getSource() an.

Ein funktionierendes Beispiel gibts hier: http://jsfiddle.net/Ec3te/2/
Ich habe dazu auch was auf StackOverflow geschrieben: http://stackoverflow.com/questions/17339899/plupload-html5-preview-after-fileselect

E-Mail-Validierung für IDN-Domains in HTML5, PHP und Javascript

Tach,

ich habe mich heute mal (wieder) informiert, wie man am besten E-Mail-Adressen auf korrektes Format validiert.

Die Situation

Bisher habe ich in PHP immer den mit Version 5.2.0 eingeführten E-Mail-Filter und in Javascript einen regulären Ausdruck verwendet:

PHP:

function checkEmail($email){
	return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}

Javascript:

function checkEmail(email){
	return email.match(/^[-a-z0-9~!$%^&*_=+}{\'?]+(\.[-a-z0-9~!$%^&*_=+}{\'?]+)*@([a-z0-9_][-a-z0-9_]*(\.[-a-z0-9_]+)*\.(aero|arpa|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org|pro|travel|mobi|[a-z][a-z])|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(:[0-9]{1,5})?$/i);
}

HTML5:

Auch HTML5 bietet die Möglichkeit, ein Eingabefeld des Typs E-Mail zu erzeugen:

<!DOCTYPE html>
<html lang="de">
    <head>
        <title>E-Mail-Validierung</title>
    </head>
    <body>   
        <form>
            <input type="email">
            <input type="submit">
        </form>   
    </body>
</html>

Demo für HTML5 und Javascript.

Das Problem

Das Problem ist nun, dass keine der drei Lösungen IDN-Domains bei E-Mail-Adressen akzeptiert (siehe [1] und [2]). Das heißt Adressen wie foo@bär.de, die durchaus gültig sind, werden als ungültig erkannt.

Die Lösung

Als Lösung muss man also den Domain-Teil in Punycode konvertieren, um danach das Format prüfen zu können.

PHP:

Für PHP kann man hierzu auf das Modul intl bzw. speziell auf die Funktion idn_to_ascii
zurückgreifen.

function checkEmail($email){
	$parts = explode('@', $email);
	return count($parts) == 2 && filter_var($parts[0].'@'.idn_to_ascii($parts[1]), FILTER_VALIDATE_EMAIL) !== false;
}

Javascript:

Für Javascript bin ich auf eine tolle Bibliothek von Mathias Bynens gestoßen. Damit lässt sich das Problem analog zu PHP lösen.

function checkEmail(email){
	var parts = email.split('@');
	if(parts.length != 2){
		return false;
	}
	var converted = parts[0] + '@' + punycode.toASCII(parts[1]);

	return converted.match(/^[-a-z0-9~!$%^&*_=+}{\'?]+(\.[-a-z0-9~!$%^&*_=+}{\'?]+)*@([a-z0-9_][-a-z0-9_]*(\.[-a-z0-9_]+)*\.(aero|arpa|biz|com|coop|edu|gov|info|int|mil|museum|name|net|org|pro|travel|mobi|[a-z][a-z])|([0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}))(:[0-9]{1,5})?$/i);
}

Das Fazit

Mit etwas mehr Aufwand ist es in PHP und Javascript also durchaus möglich IDN-E-Mail-Adressen korrekt zu erkennen. Meiner Meinung nach sollten die PHP-Entwickler ihren E-Mail-Filter erweitern, damit er IDN-Domains akzeptiert.

Für HTML5 gibt es dafür keine Lösung, solange die Browser-Entwickler es nicht berücksichtigen. Eingabefelder vom Typ „url“ können übrigens mit IDN-Domains umgehen. Warum also nicht auch E-Mail-Felder?

Da davon auszugehen ist, dass sich „Umlautdomains“ (wie man so schön sagt) in Zukunft weiter verbreiten werden, wäre es wichtig, dass Browser jetzt schon im vollen Umfang darauf vorbereitet wären.

[1] http://www.php.net/manual/en/filter.filters.validate.php#102398
[2] http://barrow.io/posts/email-validation-of-double-byte-domains/