Durch einen bei css-tricks veröffentlichten Artikel wurde ich dazu inspiriert, mich kurz in viererlei Sachen zu üben:
- CSS mit Transitions und Pseudo-Elementen
- möglichst wenig HTML-Markup
- keine Bilder verwenden
- einfaches JavaScript ohne jQuery & Co
Herausgekommen ist einer sehr einfache To-Do-Liste im Notizbuch-Stil. Kleine Spielerei, aber ein bisschen was habe ich gelernt. Vor allem, dass man JavaScript völlig neu lernen muss, wenn man sonst nur den Umgang mit jQuery gewohnt ist.
Es folgt ein kleiner Walkthrough.
Ziel…
… sieht so aus:
Wie gesagt, eine To-Do-Liste im Notizbuch-Stil. Hellgrauer Hintergrund, erledigte Aufgaben werden markiert und ein paar Hover- und Klick-Effekte.
HTML
Eine einfache Liste. Da man das Ganze eventuell um eine weitere Liste für gelöschte Aufgaben o.ä. erweitern möchte, verwenden wir eine Klasse statt einer ID.
1 2 3 4 5 6 7 8 9 10 11 12 13 | <ul class="list"> <li>Frühstück</li> <li>Facebook checken</li> <li>Rasieren</li> <li>Müll runterbringen</li> <li>Mama anrufen</li> <li>Twittern, dass ich Mama angerufen habe</li> <li>über Kontostand wundern</li> <li>Fernsehprogramm durchstöbern</li> <li>einen sehr langen Aufgabentext ausdenken, um die Einzeiligkeit zu demonstrieren</li> <li>Gute Nacht Geschichte anhören</li> <li>Schäfchen zählen und zZz</li> </ul> |
That’s it.
JavaScript
Ich komme erst zum JavaScript, weil wir hier lediglich Klassen wechseln. Um das Styling kümmern wir uns im Anschluss.
Eine Aufgabe hat 2 mögliche Zustände: erledigt oder unerledigt. Im ersteren Fall soll das entsprechende Listen-Element die Klasse done erhalten. Falls es doch wieder als unerledigt markiert werden soll, muss die Klasse gelöscht werden.
In jQuery würde man wohl sowas in der Art schreiben:
1 2 3 | $('.list li').click(function(){ $(this).toggleClass('done'); }); |
Da ich aber für so eine popelige To-Do-Liste keine extra Bibliothek einbinden möchte, soll das Ganze doch bitte über natives JavaScript realisiert werden. Hier der Code dafür, Erklärung ist drunter.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | function addLinkEvt() { // getElementsByClassName returns nodeList we have to walk through! var lists = document.getElementsByClassName('list'); for (var i = 0; i < lists.length; i++) { var listElements = lists[i].getElementsByTagName('li'); for (var j = 0; j < listElements.length; j++) { listElements[j].addEventListener('click', toggleDoneClass, false); } } } function toggleDoneClass(e) { var elem = e.target; var doneClass = 'done'; elem.className = (elem.className == '') ? doneClass : ''; } window.onload = addLinkEvt; |
Im Nachhinein nur logisch. Wenn man aber wie bereits erwähnt sonst nur mit jQuery unterwegs ist, stößt man auf ein paar Stolpersteine. Zuerst holen wir uns mit getElementsByClassName('list') alle Listen. Danach schauen wir mit einer for-Schleife auf alle Listen-Elemente und fügen ein Klick-Event hinzu. Die dabei aufgerufene Funktion toggleDoneClass() imitiert dann das Verhalten von jQuery’s toggleClass().
Zu guter Letzt müssen wir mit onload noch sicherstellen, dass das Event-Binding auch durchgeführt wird.
CSS
Jetzt zum lustigen Teil
Interessant sind dabei die Transitions, wenn man über eine Aufgabe fährt, das Zusammenspiel von Häkchen und X beim Markieren der Aufgaben sowie der roten Doppelrand ohne zusätzliches Markup.
Ich zeige euch jetzt einfach mal das CSS komplett. Die Kommentare sollten alles verständlich machen. Hoffentlich stört ihr euch nicht an dem Englisch. Habe ich mir so angewöhnt
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 | body { background-color:#f5f5f5; width:600px; margin:0 auto; padding:0; } .list { position:relative; /* so our red line will be positioned correctly */ color:#555; font-size:22px; padding:0; width:500px; font-family:courier, monospace; border:1px solid #dedede; } /* red border on the left side */ .list:before { content:""; position:absolute; z-index:99; top:-1px; left:40px; height:100%; width:2px; /* important for doubled border to work */ border-left:1px solid #ffaa9f; border-right:1px solid #ffaa9f; } .list li { position:relative; /* so ✔/✖ will be positioned correctly */ list-style:none; height:auto; padding:10px 10px 10px 80px; border-bottom:1px dotted #ccc; cursor:pointer; /* following 3 lines will prevent our list elements from being multiline */ overflow: hidden; white-space: nowrap; text-overflow: ellipsis; } /* green background for tasks marked "done" */ .list li.done { background-color:#dfd; } /* get rid of the last line's bottom-border */ .list li:last-child { border-bottom:none; } /* fancy new css transitions */ .list li:hover { background-color:#f0f0f0; -webkit-transition:all 0.2s; -moz-transition:all 0.2s; -ms-transition:all 0.2s; -o-transition:all 0.2s; } /* show ✔ on hover */ .list li:hover:before { content:"✔"; color:#090; position:absolute; top:10px; left:12px; } /* keep green background for done tasks on hover */ .list li.done:hover { background-color:#dfd; } /* permanently show ✔ for tasks marked "done" */ .list li.done:before { content:"✔"; color:#090; position:absolute; top:10px; left:12px; } /* show red ✖ on hover if task is marked "done" */ .list li.done:hover:before { content:"✖"; color:#c00; } |
Die Symbole für Haken und Kreuz (einzeln, nicht in Kombination) gibt’s hier. Übrigens einer meiner Lieblings One-Page-Apps.
Demo…
Wie man also sieht: eine simple To-Do-Liste ohne Grafiken und ohne externe Dateien. Für mich eine schöne Übung. Ließe sich – wie eingangs erwähnt – auch noch ein wenig erweitern. Das überlasse ich aber euch
Seht euch auch bei Interesse die Kommentare zum Original-Artikel an. Der Artikel selbst war btw ein Gastbeitrag eines – wait for it – 14-Jährigen! Das Einzige, was ich in dem Alter am Rechner gemacht hab, war das verzweifelte Sammeln von S-K-A-T-E bei Tony Hawk’s Pro Skater 2


31. März 2012 um 19:32 Uhr
Gefällt mir übrigens super gut der Artikel
Hab’s dir bisher noch nicht gesagt
31. März 2012 um 19:33 Uhr
Freut mich
7. Dezember 2012 um 21:09 Uhr
Schöner Beitrag
Ich hab die Liste eben auch noch ein wenig modifiziert.
So schaut das bis jetzt aus : http://jsfiddle.net/Akkumulator/jJUmB/41/embedded/result/
10. Dezember 2012 um 09:10 Uhr
Wow, gefällt mir richtig gut. Die Sache mit der automatischen Ordnung und vor allem dem Verschieben ist ziemlich cool.
Das Eingabefeld hätte ich wohl eher weiß gehalten. Gelb als Signalfarbe ist für die Drop-Area beim Verschieben der Todos genau richtig, beim Eingabefeld funktioniert weiß mMn besser. Der Plus-Button ist bei mir ein wenig nach unten verrutscht. Und die unten angepriesene Wischgeste funktioniert bei mir nicht (oder ist stelle mich zu doof an
).
Bis auf diese kleinen Schönheitsfehler eine ordentliche Erweiterung dieses kleinen Experiments, vielen Dank
10. Dezember 2012 um 20:51 Uhr
Danke für deine Anregungen.
Bezüglich der gelben Hintergrundfarbe stimme ich dir zu, weiß passt da wohl besser.
Das mit dem Button ist mir auch schon aufgefallen. Ich habe dazu das: http://christophzillgens.com/en/articles/equal-height-input-and-button-elements-in-firefox-and-safari
)
gefunden. Hilft aber z. B. im Chrome nix…
Da die Elemente im CSS die gleiche Höhe haben weiss ich auch nicht woher das kommt… (Anregungen Wilkommen
Das Wischen ist vor allem fürs Touch Device gedacht. Funktioniert bei mir aber auch am Desktop.
Da ich am Wochenende etwas Zeit hatte, hab ich gleich noch ne für touch optimierte Liste erstellt
http://www.screenr.com/ZDh7
Geblieben ist die Schriftart und die Idee einer ToDo Liste
10. Dezember 2012 um 22:07 Uhr
Zu dem Button-Problem: lass einfach beide Elemente links floaten, also sowohl das input als auch den Button. Die <ul> danach musst du dann entsprechend clear:both setzen.
Gibt es eigentlich einen Grund dafür, dass du button statt input[type="submit"] genommen hast? Dachte ersteres wäre irgendwann ausgestorben, sehe es aber in letzter Zeit immer öfter.
Wischen funzt bei mir im Chrome wie gesagt nicht, keine Ahnung warum.
Zur Touch-Liste: in dir steckt viel Dev-Energie, nutze sie sinnvoll
Die App wirkt etwas laggy, kann aber auch gern an der Screencast-Software liegen. Was hast du benutzt?
Beim nächsten Mal wäre vielleicht auch ein Finger-Tracker ganz sinnvoll, damit man genau sieht, was dein “Eingabegerät” macht.
Viele Grüße und danke für’s Teilen,
Enno
11. Dezember 2012 um 14:21 Uhr
Hab den Button in Input umgewandelt, somit kann man die Eingabe auch mit ‘return” am Smartphone abschicken.
Den Screencast hab ich schnell mit http://www.screenr.com/ in Verbindung mit Airplay gemacht. Das laggen liegt in der tat am Screencast