Ich habe hier ein *ganz* seltsames Phänomen.
Ich ersetze per Greasemonkey in einem bestimmten Teil einer Seite Namen
in einem Text durch Links.
Das mache ich so:
text.innerHTML=text.innerHTML.replace(/(Name:) (\S+)/g,
"$1 <a href=\"find.php?name=$2\">$2</a>")
Das klappte auch ganz hervorragend, bis jetzt da ein Umlaut drin ist.
Plötzlich entsteht sowas:
<a href="find.php?name=Sch%C3%A4fer">Schäfer</a>
Es wird also das eine $2 als UTF-8 eingebaut. Interessanterweise
passiert das nicht, wenn ich das statt "href" z.B. "class" ersetze.
Es scheint also so, als hat das innerHTML da ein gewisses Eigenleben...
Ist dieses Verhalten ein Bug oder ein Feature?
Ist das irgendwo dokumentiert? (Ich habe nichts passendes gefunden.)
Und last but not least, wie schaffe ich es, dass er in meinem obigen
Problem einen korrekten Link erzeugt? (Mit dem UTF-8 kann das Skript
nichts anfangen.)
Theoretisch sollten doch die ganzen Firefox-Innereien offen sein.
Weiß evt. jemand wie man mit vertretbarem Aufwand die Stelle findet, wo
das innerHTML implementiert ist? (Ich bin jetzt wirklich neugierig, wie
sowas zustande kommt.)
Gruß
michas
Ersetze die Zeichen U+0080 - U+00FF durch %XX bevor du die Ersetzung
vornimmst (ich nehme an, dass das Skript ISO-8859-1 erwartet). Wenn
andere Zeichen vorkommen hast du nat�rlich ein Problem (das hast du
im �brigen auch schon, da du Sonderzeichen wie ? und # nicht maskierst
bevor du die ins Dokument schreibst).
--
Bj�rn H�hrmann � mailto:bjo...@hoehrmann.de � http://bjoern.hoehrmann.de
Feature. URIs dürfen keine Unicode-Zeichen enthalten. Der Wert des
href-Attributs muss eine URI-Referenz sein; der Wert des class-Attributs nicht.
> Ist das irgendwo dokumentiert? (Ich habe nichts passendes gefunden.)
HTML 4.01 Specification und RFC3986/STD0066 ["Uniform Resource Identifier
(URI): Generic Syntax"].
> Und last but not least, wie schaffe ich es, dass er in meinem obigen
> Problem einen korrekten Link erzeugt?
Der Link ist korrekt.
> (Mit dem UTF-8 kann das Skript nichts anfangen.)
Was meinst Du damit?
> Theoretisch sollten doch die ganzen Firefox-Innereien offen sein.
Praktisch sind sie das auch.
> Weiß evt. jemand wie man mit vertretbarem Aufwand die Stelle findet, wo
> das innerHTML implementiert ist? (Ich bin jetzt wirklich neugierig, wie
> sowas zustande kommt.)
PointedEars
--
Wo im W3C-DOM für XML ist document.write spezifiziert? Nirgendwo. Das
geht also nicht, Du mußt das Dokument Knötchen für Knötchen aufbauen.
Soviel vom W3C zum Thema "Verstehen Sie Spaß???".
(Georg Maaß in dcljs <an91cq$c0ogv$1...@ID-3551.news.dfncis.de>)
Moment mal, im ursprünglichen Text war das "ä" ein Byte ISO-8859-1.
Im href-Attribut wurde daraus plötzlich zwei Byte UTF-8.
Er baut also absichtlich "Unicode" in die URI.
>> Und last but not least, wie schaffe ich es, dass er in meinem obigen
>> Problem einen korrekten Link erzeugt?
>
> Der Link ist korrekt.
Korrekt wäre da ein ein-Byte-ISO-8859-1-"ä", da das Skript, welches die
übergebenen Parameter auswertet, diese als ISO-8859-1 interpretiert.
>> Theoretisch sollten doch die ganzen Firefox-Innereien offen sein.
>
> Praktisch sind sie das auch.
Theoretisch hast du recht. ;)
Praktisch ist das Auffinden der passenden Stelle aber, zumindest für
mich, nichttrivial. Nach einiger Sucherei und viel Raten und Vermuten
hab ichs dann aufgegeben. :(
Die Zeichencodierung des Dokuments interessiert aber die Script-Engine
nicht, die intern nur UTF-16LE verwendet. Siehe ECMAScript Language
Specification, Edition 3 Final, Abschnitt 8.4 (The String Type).
> Im href-Attribut wurde daraus plötzlich zwei Byte UTF-8.
Nein, sondern zwei prozent-codierte UTF-8-Codeeinheiten, denn so ist es in
Abschnitt 2.5 von STD0066 definiert und wird serverseitig i.d.R. auch
unterstützt.
> Er baut also absichtlich "Unicode" in die URI.
Ja, diese kontextsensitive Codierung ist ein (begrüssenswertes) Feature des
Gecko-DOM-API.
>>> Und last but not least, wie schaffe ich es, dass er in meinem obigen
>>> Problem einen korrekten Link erzeugt?
>> Der Link ist korrekt.
>
> Korrekt wäre da ein ein-Byte-ISO-8859-1-"ä", da das Skript, welches die
> übergebenen Parameter auswertet, diese als ISO-8859-1 interpretiert.
Nein, denn URIs dürfen nur ASCII-Zeichen enthalten. Lies bitte das
Referenzmaterial, nach dem Du eingangs gefragt hast.
>>> Theoretisch sollten doch die ganzen Firefox-Innereien offen sein.
>> Praktisch sind sie das auch.
> > <http://mxr.mozilla.org/>
>
> Theoretisch hast du recht. ;)
> Praktisch ist das Auffinden der passenden Stelle aber, zumindest für
> mich, nichttrivial. Nach einiger Sucherei und viel Raten und Vermuten
> hab ichs dann aufgegeben. :(
Die Volltextsuche nach `innerHTML' (Kofferunempfindlichkeit[tm] ist ratsam)
zu befragen, dürfte auch für Laien nicht allzu schwierig sein. Grundlagen
in C++ sollten beim geneigten Leser natürlich vorhanden sein.
HTH
PointedEars
--
Nein. Bei zwei nebeneinander angeordneten Bildschirmen ist der rechte
Rand des linken Bildschirms die Mitte des Desktops. Der rechte Rand des
Desktops ist der rechte Rand des rechten Bildschirms, und da geht es
nicht mehr weiter. (Lars Trebing in darw <3E1C9AC9...@ltrebing.de>)
> Die Zeichencodierung des Dokuments interessiert aber die Script-Engine
> nicht, die intern nur UTF-16LE verwendet.
Ich dachte, das wäre UCS-2?
Servus,
Konni
Das ist dasselbe in grün. [psf 4.5]
<http://de.wikipedia.org/wiki/Universal_Character_Set>
Für den String-Typ ist in ES3F jedoch explizit "UTF-16"(LE) spezifiziert.
PointedEars
--
Snowboarder k÷nnen gar kein JavaScript. Sie klicken in Dreamweaver
'was zusammen und glauben, das sei "Programmieren".
-- Andreas Hollmann in dciwam
Ok, ein "ä" ist also ein "ä" egal wie es intern gespeichert wird.
Wenn er es aber wieder ins Dokument schreibt nutzt er dazu hier
normalerweise ISO-8859-1 (die Zeichencodierung des Dokuments) um dieses
Zeichen dort zu repräsentieren.
>> Im href-Attribut wurde daraus plötzlich zwei Byte UTF-8.
>
> Nein, sondern zwei prozent-codierte UTF-8-Codeeinheiten, denn so ist es in
> Abschnitt 2.5 von STD0066 definiert und wird serverseitig i.d.R. auch
> unterstützt.
Ok, am Anfang war das Zeichen in ISO-8859-1, intern hält er es als
UTF-16 und dieses Zeichen wird in einer URI korrekt als (kodiertes) UTF8
repräsentiert. Klingt logisch.
>> Korrekt wäre da ein ein-Byte-ISO-8859-1-"ä", da das Skript, welches die
>> übergebenen Parameter auswertet, diese als ISO-8859-1 interpretiert.
>
> Nein, denn URIs dürfen nur ASCII-Zeichen enthalten.
Klar. Ich meinte selbstverständlich das *kodierte* Byte.
Damit der Server mich versteht müsste in meinem Beispiel also
"Sch%E4fer" in die URL.
Wenn ich das jetzt richtig sehe, wird irgendwo in den Tiefen von
innerHTML die encodeURI-Funktion auf den String losgelassen, die den
Umlaut nach UTF-8 wandelt. Ich habe jetzt auch endlich die
escape-Funktion gefunden, die wohl nicht ganz standardkonform arbeitet,
aber in meinem Fall wohl genau das richtige Format erzeugt.
Scheint also so als sollte ich in meinem ursprünglichen Beispiel durch
folgendes ersetzen:
"$1 <a href=\"find.php?name="+escape("$2")+"\">$2</a>"
Das würde auch klappen wenn $2 erst ersetzt und dann escaped würde...
Irgendwie hab ich das Gefühl, dass ich hier irgendwas grundlegendes
falsch mache. :(
Das wird hier auch passieren. Es ändert aber genau nichts daran, dass das
Ergebnis in diesem Kontext (href-Attributwert) ein URI sein muss. D.h. die
Zeichen, die verwendet werden, um den URI prozent-zu-codieren sind sicher
Zeichen codiert nach ISO-8859-1 (sofern die Header stimmen oder ISO-8859-1
als wahrscheinlichste Codierung der Dokumentressource erkannt wird). Da das
aber nur Zeichen sein können, die auch in US-ASCII vorkommen, spielt die
Codierung dieser Zeichen hier nur eine untergeordnete Rolle.
>>> Im href-Attribut wurde daraus plötzlich zwei Byte UTF-8.
>> Nein, sondern zwei prozent-codierte UTF-8-Codeeinheiten, denn so ist es
>> in Abschnitt 2.5 von STD0066 definiert und wird serverseitig i.d.R.
>> auch unterstützt.
>
> Ok, am Anfang war das Zeichen in ISO-8859-1, intern hält er es als UTF-16
> und dieses Zeichen wird in einer URI korrekt als (kodiertes) UTF8
> repräsentiert. Klingt logisch.
Ist es auch.
>>> Korrekt wäre da ein ein-Byte-ISO-8859-1-"ä", da das Skript, welches
>>> die übergebenen Parameter auswertet, diese als ISO-8859-1
>>> interpretiert.
>> Nein, denn URIs dürfen nur ASCII-Zeichen enthalten.
>
> Klar. Ich meinte selbstverständlich das *kodierte* Byte. Damit der Server
> mich versteht müsste in meinem Beispiel also "Sch%E4fer" in die URL.
Nein, denn der Server hat dann keinerlei Information, welcher Codierung 0xE4
zuzuordnen ist; es gibt ja nicht nur ISO-8859-1 als einzige 8-bit-Codierung,
und der "Content-Type"-Header eines HTTP-Requests gilt nicht für den
Request-Befehl (sondern eben für den *Inhalt* der Nachricht, siehe RFC2616,
3.2.1, 3.2.2 und 7.2.1). Deshalb legt der URI-Standard ja auch die
Verwendung von prozent-codierten UTF-8-Codeeinheiten für Nicht-ASCII-Zeichen
fest. "ä" ist ein solches Zeichen, denn es lässt sich keinem
(US-)ASCII-Codepunkt von 0x00 bis 0x7F zuordnen.
> Wenn ich das jetzt richtig sehe, wird irgendwo in den Tiefen von
> innerHTML die encodeURI-Funktion auf den String losgelassen, die den
> Umlaut nach UTF-8 wandelt.
Unwahrscheinlich. Wahrscheinlicher ist, dass die C++-Implementation von
javascript:encodeURI() auch in SetInnerHTML() aufgerufen wird.
(BTW: Suche nach `innerHTML' in <http://mxr.mozilla.org/firefox/> führt
direkt zu
<http://mxr.mozilla.org/firefox/source/content/html/content/src/nsGenericHTMLElement.cpp#720>.
Suchdauer < 1 min.)
> Ich habe jetzt auch endlich die escape-Funktion gefunden, die wohl nicht
> ganz standardkonform arbeitet, aber in meinem Fall wohl genau das
> richtige Format erzeugt.
Nochmal zum Mitmeisseln: Das Format, welches Du als das richtige
bezeichnest, ist das falsche!
> Scheint also so als sollte ich in meinem ursprünglichen Beispiel durch
> folgendes ersetzen: "$1 <a
> href=\"find.php?name="+escape("$2")+"\">$2</a>"
Ja, das scheint nur so. escape() ist ja nicht ohne Grund für
URI-Prozent-Codierung zugunsten von encodeURI() und encodeURIComponent()
deprecated.
> Das würde auch klappen wenn $2 erst ersetzt und dann escaped würde...
> Irgendwie hab ich das Gefühl, dass ich hier irgendwas grundlegendes
> falsch mache. :(
Du liest nicht, was man Dir antwortet. Und dann wunderst Du Dich, dass das
Ergebnis Deiner falcshen Annahmen nicht mit der Realität übereinstimmt.
kopfschüttelnd,
PointedEars
--
> Einfach die xml Tags durch html Code ersetzen und gut...
Lass es mich so sagen: Die dunkle Seite gewählt Du hast. Den schnellen
Erfolg Du suchst, aber auf die Füsse fallen die Komplexität Dir wird.
Unterschätze niemals die Bugs der dunklen Seite! -- Geggo in fcc
Doch hat er. Serverseitig ist wohl ISO-8859-1 hart verdrahtet.
Ich behaupte nicht, dass das standardkonform ist.
> Unwahrscheinlich. Wahrscheinlicher ist, dass die C++-Implementation von
> javascript:encodeURI() auch in SetInnerHTML() aufgerufen wird.
>
> (BTW: Suche nach `innerHTML' in <http://mxr.mozilla.org/firefox/> führt
> direkt zu
> <http://mxr.mozilla.org/firefox/source/content/html/content/src/nsGenericHTMLElement.cpp#720>.
> Suchdauer < 1 min.)
Hatte ich auch schon gemacht. Ich bekomme hier aber "491 matching lines
in 140 files". Über SetInnerHTML() war ich dann nach deutlich mehr als
1 min auch gestolpert. Dort wird aber eigentlich nur
CreateContextualFragment aufgerufen. Deren Definition findet man dort
nicht unter "defined as a function" sonder unter "referenced in".
Die eigentliche Arbeit macht dort im wesentlichen ParseFragment, was
aber dann aber sehr schnell in den Tiefen des ParserDschungels verliert.
Bis zu der Stelle wo das href dann wieder gesetzt wird hab ich es nicht
durchgeschafft.
Aber wie das Parsen auch immer genau funktioniert das Problem ist doch
ein anderes:
-----------------------------------------------------------------
Der Firefox muss ja irgendeinen deterministischen Algorithmus haben um
aus einem HTML-Text seinen DOM-Baum inclusive href-Attribut zu baun.
Wenn im orginalem Quelltext der Seite href="Schäfer" steht dann
übersetzt er das in "Sch%E4fer". (Grade nochmal ausprobiert.)
Wenn ich in einem javascript-String href="Schäfer" schreibe und dies
innerHTML vorwerfe, dann übersetzt er das in "Sch%C3%A4fer".
(Selbiges passiert, wenn ich das href-Attribut manuell setze.)
In beiden Fällen, weiss er, dass es sich bei diesem nicht-ASCII-Zeichen
um den Buchstaben "ä" handelt. Die Frage ist nun warum er ihn in den
beiden Fällen unterschiedlich kodiert.
(Wenn es jeweils der selbe Algorithmus ist, der den Text parst, sollte
es dann ja eine Möglichkeit geben anzugeben, wie er kodieren soll.)
> Du liest nicht, was man Dir antwortet. Und dann wunderst Du Dich, dass das
> Ergebnis Deiner falcshen Annahmen nicht mit der Realität übereinstimmt.
Die Realität(tm) sieht hier so aus, dass in der Seite die ich bearbeite,
in Links einfach nicht-ASCII-Zeichen drinstehen und diese in ein
korrektes(tm) Format umzuwandeln dem Browser überlassen wird.
Die Serverseite, auf die ich keinen Einfluß habe, verläßt sich darauf,
dass der Browser diese als ISO-8859-1 (%E4) umwandelt, was wohl jeder
Browser auch genau so tut. Scheint so, als passt Realität und Standard
nicht überein...
> Wenn im orginalem Quelltext der Seite href="Schäfer" steht dann
> übersetzt er das in "Sch%E4fer". (Grade nochmal ausprobiert.)
Vermutlich aber auch nur dann wenn, dieser Quelltext selbst in
ISO-8859-1 kodiert ist. Denn für den Quelltext ist dann ja die
Kodierung bekannt.
> Wenn ich in einem javascript-String href="Schäfer" schreibe und dies
> innerHTML vorwerfe, dann übersetzt er das in "Sch%C3%A4fer".
> (Selbiges passiert, wenn ich das href-Attribut manuell setze.)
Weil JavaScript eben Strings nicht in ISO-8859-1 kodiert, sondern
Unicode verwendet.
> um den Buchstaben "ä" handelt. Die Frage ist nun warum er ihn in den
> beiden Fällen unterschiedlich kodiert.
Weil die eben in unterschiedlichen Komponenten des Browsers verarbeitet
werden und (in Deinem Fall) beide Komponenten andere Kodierungen für
Text verwenden. Für JavaScript ist Unicode die (einzige) Kodierung für
Text, HTML-Code selbst kann dagegen in unterschiedlichen Kodierungen
vorliegen.
> (Wenn es jeweils der selbe Algorithmus ist, der den Text parst, sollte
> es dann ja eine Möglichkeit geben anzugeben, wie er kodieren soll.)
Am einfachsten wird es sein, daß Du grundsätzlich überall UTF-8
verwendest. Oder Du verzichtest auf nicht-ASCII-Zeichen in URLs, so daß
Du es nicht dem Browser überlassen musst, die "richtige" Kodierung zu
finden, bzw. kodiere die problematischen Zeichen eben selbst so wie Du
das gerne hättest.
--
Alexander
Vor allem ist es nicht interoperabel.
> Der Firefox muss ja irgendeinen deterministischen Algorithmus haben um
> aus einem HTML-Text seinen DOM-Baum inclusive href-Attribut zu baun.
>
> Wenn im orginalem Quelltext der Seite href="Schäfer" steht dann übersetzt
> er das in "Sch%E4fer". (Grade nochmal ausprobiert.)
>
> Wenn ich in einem javascript-String href="Schäfer" schreibe und dies
> innerHTML vorwerfe, dann übersetzt er das in "Sch%C3%A4fer". (Selbiges
> passiert, wenn ich das href-Attribut manuell setze.)
>
> In beiden Fällen, weiss er, dass es sich bei diesem nicht-ASCII-Zeichen
> um den Buchstaben "ä" handelt. Die Frage ist nun warum er ihn in den
> beiden Fällen unterschiedlich kodiert.
Das hielte ich allerdings für einen Bug.
> (Wenn es jeweils der selbe Algorithmus ist, der den Text parst, sollte es
> dann ja eine Möglichkeit geben anzugeben, wie er kodieren soll.)
Du kommst an den Setter per Scripting nicht heran, der ist schon gelinkt und
compiliert. Und am besten ist es ohnehin, `innerHTML' zu vermeiden.
>> Du liest nicht, was man Dir antwortet. Und dann wunderst Du Dich, dass
>> das Ergebnis Deiner falcshen Annahmen nicht mit der Realität
>> übereinstimmt.
>
> Die Realität(tm) sieht hier so aus, dass in der Seite die ich bearbeite,
> in Links einfach nicht-ASCII-Zeichen drinstehen und diese in ein
> korrektes(tm) Format umzuwandeln dem Browser überlassen wird.
BAD. (Und ich dachte, die Realität[tm] sei woanders...))
> Die Serverseite, auf die ich keinen Einfluß habe, verläßt sich darauf,
> dass der Browser diese als ISO-8859-1 (%E4) umwandelt, was wohl jeder
> Browser auch genau so tut. Scheint so, als passt Realität und Standard
> nicht überein...
Es könnte natürlich auch sein, dass Du ein ... eigenwilliges Realitätsbild
hast. Es macht nämlich keineswegs "jeder Browser" so, inzwischen ist eher
das Gegenteil der Fall.
PointedEars
--
Andererseits wäre auf einer Seite unter vu-Domain mit Zappelgifs,
Mustertapete, MS Sans Comic und Frames ein fehlender Counter ein
glatter Stilbruch.
(Olaf Pöhlmann in dciwam <asl6a6$rm0$04$1...@news.t-online.com>)
Ganz genau. Das ist die Stelle an der die Kodierung des Quelltextes die
Kodierung der URL beeinflusst.
>> Wenn ich in einem javascript-String href="Schäfer" schreibe und dies
>> innerHTML vorwerfe, dann übersetzt er das in "Sch%C3%A4fer".
>> (Selbiges passiert, wenn ich das href-Attribut manuell setze.)
>
> Weil JavaScript eben Strings nicht in ISO-8859-1 kodiert, sondern
> Unicode verwendet.
Naja, er muss auch von UTF16 nach UTF8 umkodieren.
Ich hatte halt ursprünglich erwartet, dass er auch hier (wie oben auch)
das Encoding des Quelltextes als Zielkodierung nutzt.
Aber vermutlich wird die Kodierung des Quelltextes nur benutzt um aus
dem Quelltext einen DOM-Baum zu baun. Danach ist die Kodierung der Seite
ja eigentlich nicht mehr interessant und wird ignoriert.
> Am einfachsten wird es sein, daß Du grundsätzlich überall UTF-8
> verwendest. Oder Du verzichtest auf nicht-ASCII-Zeichen in URLs, so daß
> Du es nicht dem Browser überlassen musst, die "richtige" Kodierung zu
> finden, bzw. kodiere die problematischen Zeichen eben selbst so wie Du
> das gerne hättest.
Bei eigenen Seiten mach ich das ja auch so.
Hier schreib ich aber (per Greasemonkey) in einer fremden Seite rum.
Und diejenigen, die diese Seite verbrochen haben, schreiben halt einfach
<a href="...schäfer">schäfer<\a> in ihre eigenen Links. Einen solchen
Link in Javascript zu erzeugen scheint also doch deutlich komplizierter
als das replace aus dem ursprünglichen Posting. :(
Das replace auf dem innerHTML klang nach der elegantesten Lösung.
Wenn es irgendeine schicke Lösung ohne innerHTML gibt, lasse ich mich
aber gerne davon überzeugen. ;)
> Es könnte natürlich auch sein, dass Du ein ... eigenwilliges Realitätsbild
> hast. Es macht nämlich keineswegs "jeder Browser" so, inzwischen ist eher
> das Gegenteil der Fall.
Die reale Seite macht das so. Verschiedenste reale Nutzer benutzen sie
mit den verschiedensten realen Browsern. Mir ist nicht bekannt, dass es
irgendwelche Nutzer geben würde, die sich darüber beschweren, das die
Links nicht funktionieren. Deshalb gehe ich davon aus, dass auch andere
reale Browser das genau so handhaben wie mein realer Firefox.
Woher kommt dein Realitätsbild, dass "eher das Gegenteil" der Fall sei?
Wieso eigentlich?
Im directory auf der Serverplatte ist es eine Bytefolge und der HREF=""
Teil braucht sowieso nicht menschenlesbar zu sein, also ist der
Zeichensatz, mit dem der Browser läuft, irrelevant.
URLs zum Eintippen macht man ohnehin mit sieben Bit and alles ist gut.
So, nach vielen Stunden Haare-raufens und ungläubigen
Auf-den-Bildschirm-Starrens habe ich jetzt wohl endlich die Ursache
gefunden.
Hier die Essenz als JavaScript-Shell-Log:
p.innerHTML='<a href="Schäfer">Schäfer</a>'
<a href="Schäfer">Schäfer</a>
p.innerHTML
<a href="Sch%C3%A4fer">Schäfer</a>
p.firstChild.href
http://www.example.org/Sch%C3%A4fer
p.innerHTML='<a href="?Schäfer">Schäfer</a>'
<a href="?Schäfer">Schäfer</a>
p.innerHTML
<a href="?Sch%C3%A4fer">Schäfer</a>
p.firstChild.href
http://www.example.org/?Sch%E4fer
p.innerHTML=p.innerHTML
<a href="?Sch%C3%A4fer">Schäfer</a>
p.firstChild.href
http://www.example.org/?Sch%C3%A4fer
Ich denke ich kann festhalten:
- Umlaute *vor* dem ? werden immer UTF-8 kodiert.
- Umlaute *nach* dem ? werden nach dem Encoding des Dokuments kodiert.
- Ein innerHTML sich selbst zuzuweisen ist *kein* NOP.
Letzteres ist mir passiert, da ich mehrere replaces nacheinander
angewendet hatte:
text.innerHTML=text.innerHTML.replace(...)
text.innerHTML=text.innerHTML.replace(...)
Wenn ich nur einmal in innerHTML schreibe funktioniert es wie geplant.
text.innerHTML=text.innerHTML.replace(...)
.replace(...)
Vielen Dank für die konstruktiven Anregungen.
Gruß
michas
Wenn das so wäre, so wäre das ein Bug. Die Definition in STD0066 ist
unabhängig von der Codierung der verweisenden Ressource (und der Ressource,
auf die verwiesen wird). Da "Schäfer" also kein gültiger URI ist, sollte
die DOM-Implementation entweder "Schäfer" liefern (d.h. den ungültigen Wert
unverändert) oder die standardisierte Variante mit prozent-codierten
UTF-8-Codeeinheiten. Praktischer wäre ersteres; die Prozent-Codierung
sollte, wenn überhaupt, nur beim Schreiben der innerHTML-Eigenschaft
automatisch stattfinden.
>> Wenn ich in einem javascript-String href="Schäfer" schreibe und dies
>> innerHTML vorwerfe, dann übersetzt er das in "Sch%C3%A4fer". (Selbiges
>> passiert, wenn ich das href-Attribut manuell setze.)
>
> Weil JavaScript eben Strings nicht in ISO-8859-1 kodiert, sondern Unicode
> verwendet.
Das ist hier irrelevant, STD0066 hat mit JavaScript direkt nichts zu tun.
Ich habe die interne Codierung der Script-Engine/Sprache nur erwähnt, weil
Michael fälschlicherweise davon ausging, die Codierung der Ressource spielte
*dafür* eine Rolle.
>> um den Buchstaben "ä" handelt. Die Frage ist nun warum er ihn in den
>> beiden Fällen unterschiedlich kodiert.
>
> Weil die eben in unterschiedlichen Komponenten des Browsers verarbeitet
> werden und (in Deinem Fall) beide Komponenten andere Kodierungen für Text
> verwenden. Für JavaScript ist Unicode die (einzige) Kodierung für Text,
Das ist fchsal, es kommt auf die Sprachimplementation an (von deren es
keineswegs nur die eine, Netscape/Mozilla.org JavaScript, gibt). Konforme
Implementationen von ECMAScript müssen den Unicode-Standard bzw. das
Universal Character Set unterstützen (und damit intern UTF-16LE bzw. UCS-2
verwenden); frühere/andere Implementationen müssen das nicht.
Und JFYI: Unicode an sich ist keine Codierung, sondern ein Standard, der
Zeichen und ihre Codierungen definiert. Die möglichen Codierungen für die
Glyphen/Zeichen des Unicode-Zeichenvorrats gehen von UTF-7 bis UTF-32. Es
ist daher in mehrfacher Hinsich fhcsal zu sagen, dass "[f]ür JavaScript [die
(einzige) Kodierung für Text] Unicode" sei. Siehe <http://unicode.org/faq/>
> HTML-Code selbst kann dagegen in unterschiedlichen Kodierungen vorliegen.
Wie gesagt, das ist irrelevant. Entscheidend ist hier nicht, welche
Codierung die Script-Engine verwendet, sondern welche Prozent-Codierung das
DOM API vornimmt. Dies gilt sowohl für das Lesen als auch das Schreiben der
proprietären innerHTML-Eigenschaft.
>> (Wenn es jeweils der selbe Algorithmus ist, der den Text parst, sollte
>> es dann ja eine Möglichkeit geben anzugeben, wie er kodieren soll.)
>
> Am einfachsten wird es sein, daß Du grundsätzlich überall UTF-8
> verwendest.
Das kann eine gute Idee sein, ist aber nicht unbedingt notwendig, denn die
Codierung des Dokuments sollte keine Rolle spielen.
> Oder Du verzichtest auf nicht-ASCII-Zeichen in URLs, so daß Du es nicht
> dem Browser überlassen musst, die "richtige" Kodierung zu finden,
Dies ist die empfehlenswerte, weil standardkonforme und interoperable Variante.
> bzw. kodiere die problematischen Zeichen eben selbst so wie Du das gerne
> hättest.
Das ist nicht zu empfehlen, weil nicht standardkonform und nicht interoperabel.
PointedEars
--
ich benutze den Befehl BOQuery, um Daten aus meiner Datenbank zu lesen.
Dieser funktioniert im IE 6 auch meistens. Aber auf manchen Rechnern bei
uns in der Firma funktioniert er nicht. [...] Was muß ich installieren?
(Reiner Wahnsiedler in dcljs <ardkdn$d0q$07$1...@news.t-online.com>)
Das kommt darauf an, was Du unter elegant verstehst. Sicher ist `innerHTML'
für Dich *bequem*. Aber es ist auch *proprietär*, was bedeutet, dass genau
das passieren kann (und darf), was Dir passiert ist.
> Wenn es irgendeine schicke Lösung ohne innerHTML gibt, lasse ich mich
> aber gerne davon überzeugen. ;)
Was verstehst Du unter "schick"? Die spezifizierte, standardkonforme Lösung
ist sicher weniger bequem für Dich, aber sie ist sicher auch (nach
Feature-Test, mit Fallback) *zuverlässiger*. Sei `text' eine Referenz auf
ein Element, so ist folgendes möglich:
var rx = /(Name:)\s*(\S+)/;
if (rx.test(text.textContent))
{
var m = null;
while ((m = getNextMatch(text, m)))
{
m.target.textContent = m.target.textContent.replace(rx, "$1 ");
var link = document.createElement("a");
link.href = "find.php?name=" + encodeURIComponent(m[2]);
link.appendChild(document.createTextNode(m[2]));
text.parentNode.insertBefore(link, text.nextSibling);
}
}
getNextMatch(text, ...) muss dann als rekursive Suche über die Kindelemente
von `text' implementiert werden; es muss eine Referenz zu einem Objekt
liefern, welches die relevanten Eigenschaften bereitstellt. Hat `text' nur
Textknoten als Kindelemente, erübrigt sich die Rekursion. Nicht
unwahrscheinlich, dass hier die Verwendung von XPath zur Effizienzsteigerung
beträgt.
>> Es könnte natürlich auch sein, dass Du ein ... eigenwilliges Realitätsbild
>> hast. Es macht nämlich keineswegs "jeder Browser" so, inzwischen ist eher
>> das Gegenteil der Fall.
>
> Die reale Seite macht das so. Verschiedenste reale Nutzer benutzen sie
> mit den verschiedensten realen Browsern. Mir ist nicht bekannt, dass es
> irgendwelche Nutzer geben würde, die sich darüber beschweren, das die
> Links nicht funktionieren. Deshalb gehe ich davon aus, dass auch andere
> reale Browser das genau so handhaben wie mein realer Firefox.
>
> Woher kommt dein Realitätsbild, dass "eher das Gegenteil" der Fall sei?
Vielleicht reden wir aneinander vorbei. Ich meinte, dass ich kein aktuelles
Nutzerprogramm kenne, welches Umlaute in URIs beim Request nicht in
prozent-codierte UTF-8-Codeeinheiten umwandelt.
PointedEars
--
Lass es mich so ausdrücken: Eigentlich werde ich keine Zeit haben, aber die
fürs Usenet übliche nehme ich mir. Nähme ich mir noch zusätzlich was vor,
würde ich womöglich das tun, um nicht das, das ich tun sollte, tun zu müssen.
(Christoph Päper in <darw/> <avl5ul$30fp$1...@ariadne.rz.tu-clausthal.de>)
Unter elegant verstehe ich in diesem Fall eine einzelne Zeile Code, aus
der man sofort die Semantik erkennen kann.
> Sicher ist `innerHTML'
> für Dich *bequem*. Aber es ist auch *proprietär*, was bedeutet, dass genau
> das passieren kann (und darf), was Dir passiert ist.
In diesem speziellen Fall ist mir das "proprietär" ausnahmsweise einmal
fast egal, da der Code im Greasmonkey läuft, also nur für Firefox
gedacht ist.
> Die spezifizierte, standardkonforme Lösung
> ist sicher weniger bequem
Ok, eine standardkonforme Lösung ist möglich, scheint aber *deutlich*
aufwendiger und dadurch auch fehlerträchtiger zu sein. :(
Für den konkreten Fall bleibe ich also lieber beim innerHTML.
> Hat `text' nur Textknoten als Kindelemente, erübrigt sich die Rekursion.
Die Textknoten hatte ich mir zuvor schon per XPath bestimmt, so dass im
speziellen Fall 'text' nur ein einziger (längerer) Textknoten ist in dem
potentiel mehrere gleichartige Ersetzungen vorgenommen werden sollen,
weswegen ein replace(/.../g,...) ja so verlockend ist.
> Vielleicht reden wir aneinander vorbei. Ich meinte, dass ich kein aktuelles
> Nutzerprogramm kenne, welches Umlaute in URIs beim Request nicht in
> prozent-codierte UTF-8-Codeeinheiten umwandelt.
Das Nutzerprogramm Firefox macht das z.B. so. - Zumindest dann, wenn es
sich um Umlaute im Query-Teil der URI in nicht-UTF-8-Seiten handelt.
Nimm dir z.B. mal tagesschau.de:
Suchst du dort nach "Schäfer" wird das in "?searchText=Sch%E4fer" übersetzt.
Änderst du das in die "korrekte" Version "?searchText=Sch%C3%A4fer" kann
er damit nichts mehr anfangen.
Andere Seiten wie dict.leo.org scheinen da intelligenter zu sein und
akzeptieren beide Versionen, indem wohl die richtige Kodierung erraten wird.
Ich sehe aber auch grad nicht, dass dieses Verhalten unbedingt dem
Standard wiedersprechen muss. Ber von dir zitierte STD66 hält sich, am
Ende von 1.2.1 noch sehr neutral:
Such a definition should specify the
character encoding used to map those characters to octets
prior to being percent-encoded for the URI.
Später in 3.2.2 wenn es um den *Host*-Part geht sagt er dann:
Non-ASCII characters must first be encoded according to UTF-8
Beim *Query*-Part in 3.4 wird wieder kein encoding vorgeschrieben.
Mag aber auch gut sein, das ich irgendwas wichtiges übersehen hab.