CSS3: SASS, Compass und PIE

Nach einer längeren Pause gibt es heute ein paar kurze Notizen zum Thema CSS3 und Internet Explorer.

Aber der Reihe nach.

SASS

So schön CSS ist, so alt und stupide ist der Spielraum zum entwickeln und konzipieren. CSS kann keine Vererbung, keine Strukturierungen, keine Kapselungen bzw. Mixins. Das einzige, was CSS kann: eine Aneinanderreihung von Tags, bspw. #element ul > li

Mit SASS ist das alles möglich. Es sind hierarchische Strukturen möglich, man kann Mixins (Kurzanweisungen für ein Set von Funktionen/Attributen, Stichwort: Browser-Cross-Features) oder endlich Variablen im CSS nutzen. Der Code-Syntax ist dabei eine Erweiterung von CSS3* (d.h. CSS selber ist weiterhin möglich) und wird üblicherweise in .scss-Dateien abgelegt. Jedes öffentlich zugängliche Stylesheet muss dann in ein „normales“ CSS umgeschrieben werden, das erledigt SASS wahlweise auf Knopfdruck oder mit einem Watchdog (Befehl watch). Mit letzterem geschieht die Generierung on-the-fly, d.h. man kann zwischen SCSS und Browser genauso wechseln wie beim guten alten CSS.

* So lange man natürlich kein CSS3 nutzt, ist man auch CSS2 kompatibel.

Compass

Als Erweiterung für SASS gedacht, erweitert Compass das Funktionsspektrum um einige hilfreiche CSS(3)-Features. Die Referenz zeigt stets den aktuellen Stand und auf GitHub sind die Sourcen offen zugänglich. Um beispielsweise die mittlerweile zahlreichen (6!) vendor-spezifischen Anweisungen eines linearen Gradienten (hier: weiß zu schwarz) zu erzeugen, reicht das simple Mixin linear-gradient(color-stops(white, black)).

Nett: Als Pull bekam das Projekt auch schließlich einen experimentellen Hack, damit Gradienten out-of-the-box im IE6-8 funktionieren. So funktioniert Open Source.

PIE

CSS3PIE ist eine winzige Library, die in Form einer HTC (so genannte HTML Components, eine microsoft-spezifische JavaScript-Datei) weitestgehend die CSS3-Features border-radius, box-shadow und linear-gradient bereitstellt.

In Compass ist PIE optional verfügbar. Mit der Ergänzung einer Zeile SCSS-Code ist damit ein runder, schattierter Button real.

Beispiele

Da war noch was…

CSS3PIE wurde dieses Jahr ein Teil von Sencha. Da ist es nicht verwunderlich, dass Sencha selber für ihren Theme-Generator (Bestandteil der Sencha SDK Tools)  für ExtJS/SenchaTouch auf Compass, PhantomJS u.a. setzt.

Autodiscovery der Searchengine in Google Chrome + OpenSearch

Unter dem Titel „Suche in Chrome per type=search anmelden“ fand ich die Tage einen netten Hinweis von Markus. Es geht darum, dass der Chrome automatisch Suchmaschinen hinzufügt. Auch ich dachte bisher, dass Google einfach nur eine gute Liste eingepflegt hat (bspw. mit amazon.de), aber mitnichten: Die Amazon.de-Suchmaschine ist bei mir nur deswegen drin, weil ich die Amazonseite besucht habe und Chrome dort eine Suchmaschine „gefunden“ hat. Aber warum gerade Amazon.de? Warum dict.cc?

Markus erster Hinweis war, dass es mit dem neuen HTML-Inputfeld-Typ „search“ zusammenhängt. Ein anderer Kommentator brachte noch OpenSearch ins Spiel.. und als meine ersten Tests überhaupt nicht fruchteten, setzte ich mich mal genauer an das Thema heran. Den Großteil des Ergebnisses habe ich bereits in Markus‘ Beitrag als Kommentar geschrieben.

OpenSearch

Beginnen wir mit OpenSearch: Dies ist ein — noch nicht standardisierter — Entwurf für ein Dokument, welches die Metainformationen einer Suchmaschine beschreibt: Name, Beschreibung, URL-Pattern, Sprache, usw.

Ein solches OSDD (OpenSearch Description Document) sieht dabei vereinfacht und exemplarisch so aus:

<OpenSearchDescription xmlns="http://a9.com/-/spec/opensearch/1.1/">
<ShortName>Example</ShortName>
<Description>My example search engine</Description>
<InputEncoding>UTF-8</InputEncoding>
<Image height="16" width="16" type="image/x-icon">http://example.org/favicon.ico</Image>
<Url type="text/html" template="http://example.org/index.html#search={searchTerms}"/>
</OpenSearchDescription>

Damit ein Browser die OSDD auch finden kann, muss sie innerhalb des HTML-Heads als Metainformation eingefügt werden:

<link title="Example" type="application/opensearchdescription+xml" rel="search" href="http://example.org/opensearch.xml">

Voilá! Ein Firefox findet damit bereits die Suchmaschine und bietet, wenn man auf den kleinen Pfeil unter dem aktuellen Suchmaschinen-Icon klickt, das Hinzufügen der neuen an. Das gilt im Übrigen auch für den Internet Explorer 8. Ab FF 2 und IE7 kann zudem explizit auf eine solche OSDD per JavaScript verwiesen werden:

window.external.AddSearchProvider("http://example.org/opensearch.xml");

Autodiscovery Mode in Chrome

Google Chrome erkennt auch diese OSDD, stellt aber zur Zeit keine geeignete UI wie etwa Firefox oder Internet Explorer zur Verfügung. Vielmehr werden hier die Suchmaschinen automatisch erkannt, eingetragen und über die kombinierte Adress- und Suchleiste zur Verfügung gestellt.

Der Trigger für den Autodiscovery Mode ist dabei zwar ein INPUT-Field mit dem Typ „search“ oder wahlweise mit dem Typ „text“ und dem Namen „s“. Der eigentliche Clou Witz an der Sache ist jedoch, dass Chrome dieses HTML-Element explizit auf der Startseite der Domain erwartet. Es muss also auf der example.org/index.html oder example.org/startseite.jsp auftauchen. Funktioniert die OSDD prinzipiell von allen Seiten aus, so funktioniert der Autodiscovery Mode in keinem (virtuellen) Unterverzeichnis.

Interessanterweise spielt es aber keine Rolle, wie lange die Seite angezeigt wird. Liegt also bspw. eine example.org/index.html vor, die einen Meta-Refresh nach 0 Sekunden (sprich: sofort) macht, dann funktioniert der Autodiscovery Mode dennoch. Zusätzlich kann man das Formular auch unsichtbar machen, dies hat keine Auswirkungen.

Im Grunde reicht also dieses Schnippselchen, sofern man keine adäquate oder sinnvolle Startseite hat:

<form style="display: none;"><input type="search" name="s" /></form>

Die eigentliche Konfiguration holt sich Chrome wiederum aus der OSDD.

Drawbacks

  • Apple Safari scheint bis dato keinerlei native Unterstützung für OSDD oder vergleichbares zu haben. Am nächsten kommt das Plugin Inquisitor.
  • Internet Explorer 9 scheint auf den ersten Blick keine Unterstützung für OSDD zu haben. Evtl. habe ich es aber auch noch nicht gefunden?
  • Opera hat auch keine Unterstützung.
  • Spezialfall: Im Verbund mit einem Suchparameter via Hash (Ajax/RIAs) wird bei Firefox nur der location.hash ausgetauscht (die Applikation bleibt). Google hingegen veranlasst einen kompletten neuen Request auf location.href, womit die gesamte Applikation neu geladen wird.

tl;dr: in a nutshell und lost facts

  • Die opensearch.xml stellt Metainformationen für eine Suchmaschine bereit und muss auf der HTML-Seite verlinkt werden.
  • Für den Autodiscovery Mode von Chrome muss auf einer Seite im Domain-Root ein INPUT-Feld „type=search“ oder „name=s“ vorhanden sein.
  • Das Formular respektive Feld muss weder für den Benutzer sichtbar sein (CSS), noch lange angezeigt werden (Redirect nach 0 Sekunden).
  • Manuelles Hinzufügen über eine API in nahezu allen aktuellen Browsern möglich.
  • Es können mehrere Suchmaschinen je Seite verwaltet werden (betrifft OSDD).

Links

Update: Martin Thoma hat einen englischen Artikel (http://martin-thoma.com/search-engine-autodiscovery/) geschrieben, der auf diesem basiert. Ergänzende Informationen sind zum Beispiel die aktualisierten Kompatibilitäten (IE7).

git-svn vs. svn mv

Da staunte ich nicht schlecht, als das schlichte Wechseln zwischen Branches meines Git-Repositories (via git-svn) keine Wirkung auf den Editor hatte. Wieso waren auf einmal alle Dateien und Versionsangaben die selben? Hatte ich aus Versehen etwas falsches committet? Hatte der Release-Branch jetzt auch die Trunk/Developer-Version? Oh Graus!

Nein, hatte er nicht. Sowohl die Subversion-Timeline als auch das eigentliche Repository zeigten alles korrekt an — Puh! Das bedeutetet jedoch, das aus irgendeinem Grunde die Synchronisation mit Git in die Hose gegangen war. Leider brachte auch das Re-Syncen nichts.

Erst das nähere Betrachten in einem visuellen Darstellung mit Hilfe von GitX brachte eine Erkenntnis: Aus irgendeinem Grunde war an einem bestimmten Tag X zwischen zwei Commits ein Merge des Release-Branches in den Hauptzweig „master/trunk“ geschehen. Da ich mich an eine solche Aktivität nicht erinnern konnte (abgesehen der Tatsache, dass mir das mit git-svn auch als Kunststück vorkam), ergab das ein großes Fragezeichen… bis ich dann sah, was die besagten Commits in der SVN-Timeline waren.

Aus historischen und situationsabhängigen Gründen wurde damals ein unkonventionelle Weg eingeschlagen werden: Aus /trunk wurde Release 1.0; /trunk wurde verschoben (bzw. gelöscht, außerhalb des Standard-SVN-Schema) und schließlich /branches/new-release nach /trunk verschoben. An dieser Stelle verschluckt sich die Git-SVN-Bridge, und alle drei Branches verschmelzen zu einem gleichen Tree (nämlich den Master/Trunk).

Und die Lösung des Problems? Einmal abgesehen davon, dass natürlich die Aktion im SVN-Repository nicht gerade brilliant war, lässt sich dies über die .git/config lösen. (Hinweis: Ein einfaches git remote rm löst das Problem nicht, weil es git-svn remotes sind.)

[svn-remote "1.1-RELEASE"]
    url = svn+ssh://your-server/home/svn/project-name/branches/1.1-RELEASE

fetch = :refs/remotes/1.1-RELEASE
oder auch

[svn-remote "1.1-RELEASE"]
    url = svn+ssh://your-server/home/svn
    fetch = project-name/branches/1.1-RELEASE:refs/remotes/1.1-RELEASE

IE9 – 99% von was?

IE9 HTML5 Tests 99%… Bogus

IE9 has none of them, nor does it have any validation, or ranges or the new types… and worst of all for my Uploader widget, still, after all these years, does not support multiple file uploads. So the 99% isn’t 99% of all HTML5 features — it’s 99% of the tests that IE implemented. This is like writing your own test and bragging that you passed it.

Ein (weiterer) schöner Artikel über den Bullshit Microsofts. Obwohl der IE9 grundlegende und zahlreiche neue Features von HTML5 implementiert, fehlen im Vergleich zu den anderen Browsern noch etliche.. abgesehen davon, das auch diese noch nicht alles implementiert haben.

Insofern ist die Aussage einer 99% HTML5 (Test)-Abdeckung genauso viel aussagekräftig, wie das Entwickeln und Nutzen von 99 Testfällen bei Hunderten Fallunterscheidungen.

Wetten, dass demnächst etliche Zeitungen, Magazine oder gar Blogs von der überragenden HTML5-Kompatibilität der IE9 berichten werden?

{DEVELOPERS SHAME DAY}

Cem hat kürzlich den Developers Shame Day ins Leben gerufen.

Als Stichtag würde ich den 3.11.2010 vorschlagen. Ich stelle mir vor, dass an diesem Tag alle Entwickler, die ein Blog oder eine Seite betreiben, ein kleines Stück Code präsentieren, dass aus heutiger (oder vielleicht auch damaliger) Sicht total hirnverbrannt ist. Ein Stück Code, dass uns selbst die Schamröte ins Gesicht steigen lässt. Dabei ist egal, ob es sich um PHP, JavaScript, CSS, HTML, Java, C oder sonst etwas handelt. Es muss nur von euch sein und es darf nicht verändert werden (umeventuell doch als total verrückter Hund dazustehen ). Ein kleiner erläuternder Text sollte natürlich auch nicht fehlen.

Und das ist mein Beitrag, wohl einer meiner ersten Gehversuche in PHP. Der Quellcode entstammt einer Datei namens „functions.inc.php“ [sic!]. Und es scheint so ;), also wäre es eine größere Anwendung gewesen, ich habe jedoch echt keine Ahnung mehr welche — vielleicht die erste PHP-Homepage in Eigenentwicklung? Die Datei hatte sich irgendwie auf meine „Informatik-Diskette“ [sic!] (Oberstufenkurs) verirrt, von der ich tatsächlich noch ein Abbild hatte. Der Rest der Programmiersünden muss entweder (m)einen Backup-Aufräumaktionen oder einem vor einigen Jahren aufgetreten Backupmediumfehler zum Opfen gefallen sein. Zu meiner Verteidigung kann ich wohl nur sagen hoffen, dass dies einer erste Spielversion war und nie „produktiv“ wurde.

Listing

Bitte in voller Länge genießen. Jede Zeile ist ein Genuss. *ankoppfass*

Unverändert, nur Benutzername/Passwort habe ich ausgeixt.

Datei: functions.inc.php (von 2002 oder 2003)

<?php
//conf.inc.php
//please don't change this file manually - go to your admin-area to change settings!!!
$listname="Meine Linkliste";
$listname2="Downloads";
$linkwidth="100%";
$addpagewidth="50%";
$catorder="name";
$incatsort="Hits";
$perpage="5";
$max_search="10";
$adminpw="a";
$max_desc_leng="500";
$html="ON";
$language="german.lang";
$timeformat="1";
 @include("global/$language"); // language-file
 @include("../global/$language"); // language-file
//connect.inc.php
// DON'T CHANGE THIS FILE MANUALLY - EDIT ONLY VIA ADMIN-AREA
$server="localhost";
$user="xxx";
$pass="xxx";
$mydb="xxx";
$db_prefix="xl_";
$db_prefix2="dl_";
function JPDiv ($a,$b) {
  $i=0;
  $j=0;
  while($j==0) {
    if(($a/($b*($i+1)))>1) {
      $i++;
    } else {
      $j = 1;
    }
  }
return $i;
}
function JPDatumZeit ($a) {
  $JPTag = array("Sonntag","Montag","Dienstag","Mittwoch","Donnerstag","Freitag","Samstag");
  $JPMonat = array("Januar","Februar","März","April","Mai","Juni","Juli","August","September","Oktober","November","Dezember");
  $JPDatumTag = $JPTag[date("w",$a)];
  $JPDatumMonat = $JPMonat[date("n",$a)-1];
  $JPDatumJahr = date("Y",$a);
  $JPZeit = date("H:i:s",$a);
  $b = $JPDatumTag . ", " . date("j") . ". " . $JPDatumMonat . " " . $JPDatumJahr . " [" . $JPZeit . "]";
return $b;
}
function JPDatumZeit2 ($a) {
  $JPDatumJahr = date("Y",$a);
  $JPZeit = date("H:i:s",$a);
  $b = date("j") . "." . date("w",$a)+1 . "." . $JPDatumJahr . " [" . $JPZeit . "]";
return $b;
}
class my_zugriff{
//Variablen für Zugangsdaten
var $user="xxx";		//Benutzername für den MySQL-Zugang
var $password="xxx";		//Passwort
var $host="localhost";	//Name (IP-Adr.) des Rechners mit MySQL
var $dbname="xxx"; 	//Name der Datenbank
//Weitere Variablen
var $db_verbindung=false; //Speichert die Verbindungskennung
var $sql_result=false; //Speichert die Kennung eines ausgewerteten SQL-Befehls
//Konstruktor definieren
function my_zugriff(){
   //Funktion verbinden wird bei Aufruf der Klasse ausgeführt
	 $this->verbinden();
}
//Falls keine Verbindung besteht,
//Verbindung aufbauen und Datenbank als Standard definieren
function verbinden(){
if ($this->db_verbindung==false){
   $this->db_verbindung = @mysql_connect($this->host, $this->user, $this->password);
   if(empty($this->db_verbindung)){
      $this->fehler("Beim Verbinden");
   }
   $auswahl = @mysql_select_db($this->dbname, $this->db_verbindung);
   if(empty ($auswahl)){
      $this->fehler("Beim Ausw&auml;hlen der DB");
   }
   return $this->db_verbindung;
}
}
//Gibt Fehlermeldung aus und beendet das Skript
function fehler($fehlerpunkt){
    echo $fehlerpunkt . " ist ein Fehler aufgetreten!<br>";
		echo mysql_error() . "<br>"; //Fehlerbezeichnung
		echo mysql_errno();	 	 		//Fehlernummer
		echo "</body></html>";		//Html-Tags schließen
		exit;
}
//SQL-Befehl ausführen
function sql_befehl($sql){
$this->sql_result = @mysql_query($sql, $this->db_verbindung);
if (empty($this->sql_result)){
	 $this->fehler("Beim Senden der Abfrage");
}
return $this->sql_result;
}
//Falls zuvor ein SQL-Befehl ausgeführt wurde,
//wird hier das Array mit den Datensätzen ausgegeben
function sql_daten(){
if(!empty($this->sql_result)){
		$sql_array=@mysql_fetch_array($this->sql_result);
		return $sql_array;
}else{
		$this->fehler("Beim Ausgeben der Datens&auml;tze");
}
}
//eig. Fkt
function sql_num_rows($sql){
$this->sql_befehl($sql);
$rows = MYSQL_NUM_ROWS($this->sql_result);
return $rows;
}
}
$db=new my_zugriff();
$db->sql_befehl("SELECT elem_string FROM elem_global WHERE elem_name='JPmyVersion'");
$myVersion_now = $db->sql_daten();
 $JPmyVersion = $myVersion_now[0];
?>

Selbstreflexion

  • Struktur: globale Variablen
  • Struktur/Aufbau: als Script noch okay, aber als Include? Oweh..
  • Includes mittendrin
  • Variabel- und Funktionsnamen multilingual
  • Inhalt der Funktionen..
  • kein gängiger Codestyle (ja, der Blog zeigt’s richtig an)
  • Inline-SQL(!)

Kurzum: What the hell…?

Weitere via Google oder Twitter oder Facebook.

Beauty Of The Web?

Nun ja, Microsoft stellt seinen neuen Internet Explorer 9 Beta vor. Und da man heutzutage nicht einfach mehr ein Produkt vorstellt, gibt es dazu gleich eine komplette eigene Seite. www.BeautyOfTheWeb.com

Wie gut der Browser jetzt ist, werden wir in den nächsten Tagen merken. Zu der Seite sei gesagt: Rein technisch scheint sie voll aufneuen Technologien zu setzen bzw. ohne Flash und Silverlight auszukommen. Die Seite ist schnell und auch ohne IE benutzbar. Im Gegensatz zu Apple haben sie es auch tunlichst vermieden, irgendwelche Browser künstlich auszuschließen, oder sollte ich etwas übersehen haben?

Mit Silverlight war es wohl schwieriger, mit Flash wohl unmöglich, noch mehr Performance rauszukitzeln. Schließlich soll der Browser IE9 ja zeigen, wie gut er ist. Also, keine Plugins, sondern pure HTML-Magie. Und CSS-Magie. Und Javascript-Magie.

Ein Schlag in Adobes Gesicht.

[Howto] Maven: Wie man eine ausführbare Jar in eine Java-Webanwendung (War) via Webstart integriert.

Die Situation

Es bestehen zwei lauffähige, fertige Projekte in Maven, welche beide auch vollwertige Artefakte bilden können.

Zum einen die Webanwendung — nennen wir sie hier mal webportal — mit einem WAR-Artefakt, etwa für einen Tomcat. Ob das Artefakt als Snapshot oder Release gemacht wird, ob es nur generiert oder auch in ein Repository deployt wird, ist hierbei nicht von weiterer Bedeutung.

Zum anderen die normale Clientanwendung — nennen wir sie doch einfach userclient — mit einem JAR-Artefakt. Wichtig ist natürlich, dass hier eine startfähige Main-Klasse vorhanden ist. Dies sollte jedoch der Regelfall sein, daher nur der formale Hinweis.

Zusammengefasst, und der Auftrag an dieses Howto ist also: Wie konfiguriert und erweitert man den Buildzyklus in welchem Projekt an welcher Stelle am geschicktesten, um auf einfachem Wege die JAR-Datei userclient in die Webanwendung webportal als Java Webstart zu integrieren. Dabei ist es hilfreich, wenn man via pom.xml (und natürlich der Macht der Properties) die Versionen spezifizieren kann. Der gesamte Prozess von auswählen, signieren und ausliefern soll dabei automatisch und ohne weiteres Eingreifen des Entwicklers geschehen können. Idealerweise sollte das ganze auch optional sein — dazu gibt es dann mehr unter „Optimierungen und Verbesserungen“.

„[Howto] Maven: Wie man eine ausführbare Jar in eine Java-Webanwendung (War) via Webstart integriert.“ weiterlesen

Nette HTML5 Techdemo

The Wilderness Downtime

… ist eine rein HTML5-Anwendung, welche sich auf Basis einer Adresse, den dazugehörigen Google Earth und Google StreetView Daten einen Musicclip „rendert“. Sehr kreative Idee!

Funktioniert mit einem aktuellen Chrome, Chromium oder auch Safari. Wohl aber dem, der ein bisschen Power im Arsch/Rechner hat.

Entstammt aus den Google Experiments, und der Chrome ist auch zu empfehlen (vor allem bei leistungsschwächeren Rechnern).

Safari Extension: HTML5-Video für Tagesschau.de

Die Tagesschau hat in den letzten Tagen ihre Video-Ausgabe-Formate etwas erweitert. Neben dem Format Ogg wurde auch etwas die Benutzerführung (in meinen Augen) verbessert.

Wie auch immer: Ich habe auf die Schnelle eine Extension geschrieben, welche die Flash-Player auf Tagesschau.de automatisch in entsprechende HTML5-Tags umwandelt. Der Code ist zur freien Verfügung unter GitHub einsehbar, der Download ist ebenfalls dort unter Downloads zu finden.

Beispiel anhand der Seite http://www.tagesschau.de/ausland/swift172.html

Tagesschau mit Flash
Tagesschau mit Flash
Tagesschau mit HTML5
Tagesschau mit HTML5

Der Code ist wenig-bis-gar-nicht dokumentiert, sollte aber bei der mehr oder weniger jQuery-Trivilität nicht notwendig sein. Eine Adaption für Chrome/Firefox sollte einfach sein. Wie man im Code sieht, habe ich sogar das Ogg-Format ausgelesen.

Resultat: HTML
Resultat: HTML

Anregungen sind gerne willkommen.

Derzeit werden nur die Filme auf normalen Artikeln ausgetauscht; keine Sidebars, mutmaßlich auch keine Extra- oder Spezialseiten. Außerdem ist – derzeit – die Kodierung auf H.264-High und Ogg fest eingestellt. Flash lädt im Vergleich immer H.264-Medium.