Die Idee
Von Angelika bekam ich zum Geburtstag eine Binary Clock vom Typ "Samui Moon". Nicht sehr viel später kam mir die Idee, diese Art der Uhrzeitanzeige auf der Site zu verwenden. Mir ist zumindest bisher noch nichts untergekommen.
Natürlich musste ein Image her, dieses aber "on-the-fly" auf dem Server zu generieren wollte ich mir - noch - nicht antun. Daher die Idee, die Images der einzelnen Digits zusammenzustellen.
Verwendung der Image-Dateien
Für die Binärdarstellung der Stunden sind vier Stellen notwendig, da auch die Originaluhr von 0 bis 12 zählt. Jede Stelle kann entweder an oder aus sein. Die Images beginnen mit dem Buchstaben "h" für hour, danach kommt die Stellennummer (1..4) und dann folgt entweder "1" für den Zustand "ein", oder "0" für "aus". 1h bzw. 13h resultiert also in der Datei "h11.png". Damit werden insgesamt die Bilder "h40.png", "h30.png", "h20.png" und "h11.png" verwendet. Für 17h ergibt sich somit "h40.png", "h31.png", "h20.png" und "h11.png", da es ja 5h ist.
Für die Binärdarstellung der Minuten sind sechs Stellen notwendig. Die Bilder beginnen mit dem Buchstaben "m" und haben sonst die gleiche Benennung wie die Stunden. 28 Minuten sind damit "m60.png", "m51.png", "m41.png", "m31.png", "m20.png" und "m10.png".
binaryClockSetViewMode(0) ; writeBinaryClock() ;
Mit diesen Images hat man also großen Spielraum. Wenn sich die Images für Stunden und Minuten nicht unterscheiden müssen, braucht man entsprechend acht Dateien weniger und das einleitende Zeichen (m bzw. h) nicht. Da aber die Stunden um zwei Stellen weniger haben und eine zentrierte Anzeige gewünscht ist, gibt es die Datei "bcf.png". Sie repräsentiert die Leerstelle (space).
binaryClockSetViewMode(1) ; writeBinaryClock() ;
Die Extremvariante kommt mit zwei Images aus. Eines für ein. Diese Datei heißt "01.png". Ein weiteres Image für aus. Diese Datei heißt "00.png". Natürlich ist wieder "bcf.png" dabei, da die Stunden um zwei Stellen weniger haben.
binaryClockSetViewMode(2) ; writeBinaryClock() ;
Version 1.1.0
David hat mich durch seine Anregung auf eine Erweiterung gebracht. Unterscheiden sich nämlich die Images für Stunden und Minuten nicht, kann man sich insgesamt ein paar Images sparen. Das kommt auch dem Betrachter zu Gute.
Danach war der Weg zur Extremvariante nicht mehr weit. Denn warum sollten nicht auch zwei Images für "ein" und "aus" reichen?
Die Version 1.1.0 gibt es im Download.
Die Programmierung
Es war ein verregneter Sonntag Nachmittag, cirka 14 Uhr. Mit JavaScript bin ich nicht so sonderlich bewandert. Gerade deshalb habe ich mich zuerst auf die Suche nach einer Unittest Möglichkeit begeben und sie in JsUnit auch gefunden. Damit stand dem XProgramming nichts mehr im Wege.
Ich brauchte Routinen zum Prüfen von gültigen Minuten und Stunden. Also zuerst die Tests für die Minuten.
function testValidMinutes() { assertEquals("Too small not detected", false, isValidMinute(-1)) ; assertEquals("Too big not detected", false, isValidMinute(60)) ; assertEquals("Invalid format", false, isValidMinute("hellO")) ; assertEquals("Invalid null", false, isValidMinute(null)) ; assertEquals("one minute", true, isValidMinute(1)) ; assertEquals("59 minutes", true, isValidMinute(59)) ; }
Der Umwandlung ins Binärformat widmete ich mich anschliessend. Klar gibt es mit "object.toString(2)" eine einfache Möglichkeit, eine Zahl in seine Binärdarstellung umzuwandeln. Das wollte ich aber unter anderem auch deshalb nicht, weil führende Nullen (Images) fehlen. Zusätzlich brauchte ich - getreu dem Original - für die Stunden nur vier Stellen, aber für die Stunden sechs stellen. Zuerst also wieder der Test...
function testToBinaryString() { assertEquals("8-4", "1000", toBinaryString(8, 4)) ; assertEquals("8-5", "01000", toBinaryString(8, 5)) ; assertEquals("7-4", "0111", toBinaryString(7, 4)) ; assertEquals("0-0", "0", toBinaryString(0, 0)) ; assertEquals("0-1", "0", toBinaryString(0, 1)) ; assertEquals("1-1", "1", toBinaryString(1, 1)) ; }
Damit widmete ich mich der Umwandlung von Minuten/Stunden ins Binärformat. Bei den Stunden galt es zu berücksichtigen, dass es nur eine 12h Darstellung gibt.
Jetzt konnte ich mich dem lustigen Teil zuwenden, nämlich der Wandlung von der Binärdarstellung in die für die Aneinanderreihung der Images. Damit das ganze aber ordentlich testbar wird, folgt nicht sofort die Wandlung in einen kompletten Pfad mit Images und dergleichen, sondern in den Image-Namen alleine. Für jede Stelle also zwei Images, eines für den eingeschalteten und eines für den ausgeschalteten Zustandes eines Digits. Das erhöht auch die Flexibilität im Sinne von Skins.
function testBuildHoursImageNames() { assertEquals("zero", "h40 h30 h20 h10", buildHoursImageNames(0)) ; assertEquals("seven", "h40 h31 h21 h11", buildHoursImageNames(7)) ; assertEquals("twelve", "h41 h31 h20 h10", buildHoursImageNames(12)) ; assertEquals("thirteen", "h40 h30 h20 h11", buildHoursImageNames(13)) ; }
Damit war der Weg zur Integration ins html schon fast abgeschlossen. Das Zusammenstellen der img Tags war aber trotzdem eine Prüfung wert.
function testBuildImageTag() { assertEquals("zero", '<img src="./h40.png"><img src="./h30.png">' + '<img src="./h20.png"><img src="./h10.png">', buildImageTag(buildHoursImageNames(0))) ; }
Integration ins HTML
Der komplizierte Teil war erledigt, so dachte ich. Jetzt brauchst nur noch das
Javascript aufrufen und dafür sorgen, dass es regelmässig aktualisiert wird.
Allerdings war gerade das der zeitraubendste Teil der Programmierung. Den bis jetzt
waren erst 3h (inklusive der Image-Erstellung mit Gimp)
vergangen. Nach 2h der Suche im Internet fand ich dann doch noch eine einfache und
für viele Browser kompatible Lösung durch die Verwendung von
"getElementById.innerHTML".
Unschön an dieser Lösung ist die explizite Verknüpfung des Programmcodes mit der id "clock" im HTML Text. Aber das empfinde ich für die erste Version als verschmerzbar.
Download
Viel Vergnügen mit BinaryClock-1_1_0.zip. Die vorherige Version gibt es unter BinaryClock-1_0_0.zip. Das Archiv enthät auch den Quelltext zum Unittest. Das enthaltene index.html zeigt die Verwendung. Das Archiv muss nur entpackt werden, danach index.html im Browser aufrufen. Wie in binaryClock.js erwähnt, ist der Quelltext frei verfügbar.
Für Kommentare steht der Blog zur Verfügung.