DavidBLN.de

18. Mai 2010

Zu den eigenen Waffen!

Neulich habe ich mich über den Javascript-Animations-Krebs ausgekotzt. Das Problem, daß zappelnde Animationen (”Slideshows”, “Rotations” und was auch immer) zunehmend mit Javascript realisiert werden, und man so den nervigen, nicht selbst initiierten Bewegungen auf dem ganzen Bildschirm nicht entkommt, habe ich bisher auf Werbetreibende reduziert.

Das war zu kurz gedacht. Es gibt nämlich außerdem dumme(rweise) Internetzbewohner, die keine Werbung (sondern durchaus schlaue oder lustige Sachen) von sich geben, diese dann aber “gut meinend” mit allerlei augenkrebsigem Geblinke anreichern. Es ist ja auch so schön einfach und verlockend, kann man doch mit “jQuery” und sonstigen Plugins mittels weniger Zeilen Code, ja: in manchen Redaktions- oder Blogsystemen sogar schon per vollständig browsergeführtem Plugin, ratz fatz die ganze – eigentlich anspruchsvolle – Seite in einen hyperaktiven Kindergartenzirkus verwandeln. Und nicht mal das muß überhaupt der Fall sein: Manches fertige Blog- oder CM-System beinhaltet ersatzlosen proprietär-javascriptigen Funktionskram, der sich bei deaktiviertem Script zu Barrieren entwickelt, von denen der nicht codeinteressierte Publizierer weder etwas merkt noch weiß (weil er selbst weder programmieren kann oder will, mindestens auf seiner Seite natürlich mit aktiviertem Script unterwegs ist und sich vielleicht auch einfach noch nie mit dem Barrierethema befaßt hat).

Zusammengefaßt muß ich also den ersten Lösungsansatz (Javascript nur auf den Seiten meines Vertrauens einschalten) zwar nicht revidieren, aber relativieren.

Erstens: Er ist doch ziemlich nervig, und zwar selbst obwohl man in Opera für jeden Host und jede IP dieser Welt dediziert konfigurieren kann. Zweitens, und das ist wohl der eigentliche Anlaß für diesen Eintrag: Als Programmierer mit Anspruch an sich selbst kann ich es nicht auf mir sitzen lassen, daß mir da $jemand Gezappel auf den Bildschirm diktieren will, das ich nicht leiden kann. Das wiederum führt zu der Herausforderung: Es muß einen Weg geben, diesen durch Javascript verursachten Krebs mit Javascript zu bekämpfen. So, wie man Allergien besser durch Gewöhnung an die als durch Vermeidung der Auslöser kuriert.

Also, wohlan!

Problemanalyse (erledigt)

Das eigentliche Problem ist nicht die einzelne Animation, denn davon gibt es zu viele. Es wäre unmöglich, sie durch einen Adblocker, Webwasher, Proxomitron oder sonstwie auszufiltern, denn das wäre das vom Email-Spam bekannte Katz-und-Maus-Phänomen. Anders gesagt: Blacklisting ist von Hause aus scheiße. Also muß man die Belästigung erst mal auf den Kern des Problems, den kleinsten gemeinsamen Nenner, reduzieren. Und das ist, nach ordentlichem Überlegen, etwas ganz simples: Aktionen, die geschehen, ohne aktiv von mir ausgelöst worden zu sein. Also alles, was nicht beim Laden einer Seite, beim Tastendrücken oder beim Anklicken von irgendetwas geschieht, sondern zu einem anderen Zeitpunkt.

Lösungsansatz (teilweise erledigt)

Dinge in zeitlichem Versatz zu oder gar gänzlich unabhängig von Benutzeraktionen geschehen zu lassen, geschieht in Javascript so, wie in praktisch allen Programmiersprachen: Durch Timer. Konkret gibt es in Javascript die Methoden setTimeout und setInterval, erstere für einmalige und letztere für regelmäßig zu wiederholende Ereignisse. Soweit ich es bisher beurteilen kann, gibt es auch keinen wirklichen Nutzen dieser beiden Funktionen, außer den eingangs erwähnten, der für den Benutzer am Bildschirm, streng rational betrachtet, keiner ist, noch nicht mal wenn es um Weiterleitungen geht: Entweder, sie geschehen sofort, oder, wenn nicht, dann durch einen Hinweis an den Benutzer und die Möglichkeit, die Weiterleitung durch Klicken selbst auszulösen. (Wer andere Beispiele hat, die das relativieren, her damit.) Konstatiere also:

Weg damit. Aber wie?

Zunächst habe ich versucht, das ganze (schon im Sinne von “mit den eigenen Waffen”) mit einer Datei in Operas “User-Javascript-Ordner” zu lösen. Das wäre so auch die beste Lösung für alle anderen Browser, die eigene JS unterstützen. Leider hat die Sache einen strukturellen Haken: An die Möglichkeit, einmal gesetzte Timer zu stoppen, hat man beim Javascript-Sprachdesign zwar gedacht, indem man die Funktionen clearTimeout und clearInterval schuf. Auf die Idee, daß man wie in meinem Fall aber beliebige Timer, die Fremde setzen, löschen möchte, kam niemand: Ich muß, soweit ich nach stundenlanger Recherche nun weiß, zwingend einen Timer beim Namen kennen, sonst kann ich ihn nicht stoppen. Es gibt keine mir bekannte Funktion, mit der man das System alle existierenden Timer einer Seite auflisten lassen und beim Namen nennen lassen kann. (Falls doch: Bitte sofort melden!)

Timer-Ereignisse abfangen wäre eine Möglichkeit. Nur wie? Ich habe in den mir bekannten Dokumentationen kein “onTimer”-Event gefunden. Außerdem wäre diese Option auch nicht hilfreich, da die Timer weiterhin bestünden und man auf jeden Trigger reagieren müßte, indem man das eigentliche Ziel verbiegt. Auch nicht gut also.

Also muß ich weiter “unten” ansetzen. Schon das setzen eines Timers muß verhindert werden. Das Script also noch vor dem Browser filtern und aus “SetTimeout” und “SetInterval” etwas unschädliches machen, (z.B. “void”), also aus


window.setTimeout("irgendwas()",1000);
window.setInterval("irgendwas()",1000);


window.void("irgendwas()",1000);
window.void("irgendwas()",1000);

machen. Das funktioniert mit der einfachen regulären Ersetzung /set(Timeout|Interval)/void/ auch ganz gut, hat aber schon wieder einen Haken: Funktionen, die ich zwar funktionierend haben will, aber eben nicht erst später sondern jetzt gleich, sind damit verloren. Deshalb müßte


window.setTimeout("irgendwas()",1000);
window.setInterval("irgendwas()",1000);

zu


irgendwas();
irgendwas();

werden. Das ist nur leider so gut wie unmöglich, denn die Aufrufe der beiden nativen Funktionen wird natürlich von vielen Libraries in unvorhersehbar vielen Kombinationen verwendet, was dann wieder zu einem Blacklist-Problem führte.

Der bisherige Ansatz ist also zumindest als Workaround brauchbar, macht aber für bestimmtewiederum viel zu viele Fälle das ebenso lästige Whitelisting von Seiten, die Timer oder auch einfach nur eine Librarie für sinnvolle Funktionen einsetzen, nötig. Außerdem gibt es auch hierbei Hintertüren, die man böswillig umgehen kann und sicher auch beizeiten wird.

Also liegt der nächste Schritt darin, eben doch gezielt jeden eigentlich unbekannten Timer, der gerade aktiv ist, zu finden, um ihn nach bestimmten Kriterien zu beurteilen und ggf. zu deaktivieren. Das aber scheitert, wie oben geschrieben, am Javascript-Design. Jedenfalls am nativen. Daher meine

Frage und Bitte:

Wer immer einen Weg kennt, entweder mittels Javascript selbst oder aber mittels jQuery (bzw. ggf. anderen Libraries) die mit ihnen gesetzten Timer eben doch zu identifizieren, bitte her damit. Danke!


Keine Kommentare »

Noch keine Kommentare.

RSS-Feed für Kommentare zu diesem Artikel. TrackBack-URL

Einen Kommentar hinterlassen