hi,
für eine optische Spielerei möchte ich ein einzelnes Zeichen aus dem Textinhalt eines Dokumentes zufällig auswählen und gesondert formatieren. Dies soll darüber hinaus mehrmals hintereinander geschehen (zeitverzögert). Berücksichtigt werden sollen natürlich nur "sichtbare" Zeichen, also kein Whitespace, und ein bereits vorher derart selektiertes Zeichen soll natürlich später nicht erneut behandelt werden.
Erst mal aus allen Textknoten zufällig einen auswählen, und aus diesem dann zufällig ein Zeichen auszuwählen ergibt keine Gleichverteilung der Wahrscheinlichkeit für die Auswahl eines Zeichens, da Textknoten natürlich unterschiedlich lange Inhalte haben.
Ich sehe bisher zwei Möglichkeiten:
Möglichkeit 1:
- Gesamtzahl aller (relevanten) Textzeichen wird ermittelt - Knotenstruktur wird einmal rekursiv durchlaufen, um die Gesamtanzahl der Zeichen zu ermitteln.
- Zufallswert x ermitteln, 0 <= x < Gesamtanzahl Zeichen
- Anschließend Knotenstruktur noch einmal rekursiv durchlaufen, dabei "mitzählen", und abbrechen wenn der Textknoten erreicht wurde, der das x-te Zeichen enthält.
Vorteil: Einfach zu implementieren, durch erneutes rekursives Durchlaufen bei jedem Aufruf stellt auch die Nicht-Berücksichtigung bereits behandelter Zeichen kein größeres Problem dar.
Nachteil: Höchst unperformant.
Möglichkeit 2:
- Knotenstruktur einmal rekursiv durchlaufen, dabei in einem Array die Referenz auf jeden Textknoten ablegen sowie die Anzahl der Zeichen des aktuellen Textknotens plus der der Vorgänger.
- Anschließend "gewichtete" Zufallsauswahl nach der Anzahl der Zeichen: Zufallswert 0 <= x < Gesamtanzahl Zeichen; In Schleife Array so lange durchlaufen, wie gespeicherte Anzahl der Zeichen < Zufallswert.
Vorteil: Performanter, wenn Array mit Textknoten nur einmal ermittelt werden müsste.
Nachteil: Zum gesonderten Formatieren eines einzelnen Zeichens werden die Textknoten gesplittet, Zeichen als neuer Textknoten mit einem Span umgeben - Resultat: Ein Textknoten mit einem Zeichen, der aus dem Array entfernt werden müsste, um dieses Zeichen nicht erneut behandeln zu müssen. Bis zu zwei neue Textknoten (vor/nach ausgeschnittenem Zeichen), die an die richtige Position ins Arrays eingefügt werden müssten. Anschließend Neuberechnung der "Anzahl Zeichen bis zu diesem Knoten einschließlich" für alle nachfolgenden Textknoten nötig. Erfordert nicht unbedingt erneutes rekursives Durchlaufen des DOM-Baumes, sollte durch Dekrementierung der Werte für alle nachfolgenden Textknoten um eins erreichbar sein.
Beide Möglichkeiten nicht sonderlich schön bzw. "effektiv".
Möglichkeit 2 aufwendiger in der Implementierung, dafür etwas performanter.
Zusätzlicher Nachteil Möglichkeit 2: Es werden vermutlich neue Inhalte per AJAX hinzugeladen werden, da müsste also auch bei dieser Möglichkeit das Array neu aufgebaut werden, wenn diese neuen Inhalte bei der nächsten Auswahl mitberücksichtigt werden sollen (dynamische Erweiterung des Arrays um die hinzugekommenen Textknoten wird mir zu aufwendig in der Implementierung).
Fällt jemandem noch eine "einfachere", performantere Möglichkeit ein?
innerHTML stellt keine Alternative dar - abgesehen davon, dass man da mit ebenfalls unperformanten regulären Ausdrücken oder einem eigenen Parser Tags von Textinhalt trennen müsste, würden Entities ein weiteres Problem darstellen - > sind vier Zeichen, die ein sichtbares Zeichen repräsentieren.
gruß,
wahsaga
--
/voodoo.css:
#GeorgeWBush { position:absolute; bottom:-6ft; }