[JS] single quote escapen dmv ' in functie

Pagina: 1
Acties:

  • JayVee
  • Registratie: Mei 2002
  • Laatst online: 14-11 21:30

JayVee

shibby++!

Topicstarter
Hoi,

// edit: ARGH! Ik zie dat de topic titel een single quote bevat, ik had daar gewoon & #039; staan (zonder spatie, als ik die hier weglaat komt er ook hier een single quote te staan)

Als je een single quote wilt escapen binnen single quotes gebruik je normaal gewoon de escape character "\". Maar voor het gemak wil ik echter de php functie htmlentities gebruiken (met ENT_QUOTES zodat single quotes ook escaped worden), en dan wordt een single quote escaped dmv & #039;.

Dit werkt echter niet in een function call. Zie het volgende voorbeeld (dat ook duidelijk maakt waarom ik het zo doe hop ik):
HTML:
1
2
<img onmouseover="overlib( 'quote this: \' ' );" />   <!-- werkt -->
<img onmouseover="overlib( 'quote this: ' ' );" />   <!-- werkt niet -->


Een simpeler voorbeeld is natuurlijk
HTML:
1
<img onclick="alert( ''' );" />


FireFox (eigenlijk FireBug) geeft bij het eerste voorbeeld aan het sluit haakje niet te vinden, bij het tweede voorbeeld "unterminated string literal". IE6 snapt het ook niet (maar met de foutmelding kun je niets uiteraard).

Waarom ziet javascript & #039; (zonder spatie...) als een single quote en werkt
JavaScript:
1
alert( '€' );
wel gewoon?

Uiteraard kan ik de single quote wel apart escapen, maar ik wil graag weten waarom dit niet werkt. Vandaar dit topic! Enlighten me!

[ Voor 9% gewijzigd door JayVee op 09-02-2007 15:23 . Reden: zie eerste [sub] alinea ]

ASCII stupid question, get a stupid ANSI!


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

HTML:
1
<img onclick="alert( '&amp;#039;' );">

Intentionally left blank


  • JayVee
  • Registratie: Mei 2002
  • Laatst online: 14-11 21:30

JayVee

shibby++!

Topicstarter
crisp schreef op vrijdag 09 februari 2007 @ 15:27:
HTML:
1
<img onclick="alert( '&amp;#039;' );">
Leuk dat dat wel werkt (neem ik aan, heb het niet getest), maar kun je mij ook vertellen waarom dat zo is?

Oftewel: wat is het verschil tussen
JavaScript:
1
2
3
alert( '€' );
// en
alert( ''' );

[ Voor 15% gewijzigd door JayVee op 09-02-2007 15:52 ]

ASCII stupid question, get a stupid ANSI!


  • Rekcor
  • Registratie: Februari 2005
  • Laatst online: 08-10 13:03
JayVee schreef op vrijdag 09 februari 2007 @ 15:48:
[...]

Leuk dat dat wel werkt (neem ik aan, heb het niet getest), maar kun je mij ook vertellen waarom dat zo is?
Ik weet het niet zeker, maar met

HTML:
1
&amp#039;


wordt echt de platte tekst "& # 0 3 9 ;" doorgeven, met

HTML:
1
'


daarenteger, gaat de interpreter zelf aan de slag, waardoor het een ' wordt (ipv &#039)

  • JayVee
  • Registratie: Mei 2002
  • Laatst online: 14-11 21:30

JayVee

shibby++!

Topicstarter
Daar lijkt het inderdaad op. Maar waarom?

It's not a bug - it's a feature. => My a$$! :)

// edit: de PHP code is nu geworden
PHP:
1
str_replace( "'", "&amp;#039;", htmlspecialchars($elName) )

Lekker handig en duidelijk... }:O

[ Voor 45% gewijzigd door JayVee op 09-02-2007 16:04 ]

ASCII stupid question, get a stupid ANSI!


  • Rekcor
  • Registratie: Februari 2005
  • Laatst online: 08-10 13:03
Die code van Crisp werkt trouwens niet: hij geeft de letterlijke tekst ipv de entity.

http://forums.htmlhelp.com/lofiversion/index.php/t1552.html gaat over hetzelfde probleem. Wat ze daar zeggen komt neer op:
a. Buiten HTML bestaan HTML-entities simpelweg niet.
b. Je moet in JS met unicode-karakters werken.

  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Dan heb ik de vraag verkeerd begrepen denk ik ;)

Je hebt te maken met 2 zaken:
1) escaping van bepaalde karakters binnen een string literal in javascipt
2) HTML-encoding van attribute-values in HTML

Voor 1) kan je in PHP addcslashes() gebruiken - JS gebruikt immers C-type escaping. De karakters die je moet escapen zijn o.a. newlines, linefeeds, tabs, single en/of double quotes, de backslash en de NULL-byte. Voor inline gebruik in een HTML document is het ook handig om de forward slash te escapen.
Voor 2) is htmlspecialchars() bedoelt. ENT_QUOTES is niet noodzakelijk als je consequent double quotes gebruikt voor attributes. htmlentities() is bijna altijd overdone.

In short:
PHP:
1
2
3
4
5
6
$alertstring = "Here's a single quote: ' and here's a double quote: \"";
$jsescaped = addcslashes($alertstring, "\0\n\r\t\\'/\"");
$jsfunction = "alert('" . $jsescaped . "');";
$htmlencoded = htmlspecialchars($jsfunction);

echo '<img onclick="' . $htmlencoded . '">';


en zo ziet de source er dan uit:
HTML:
1
<img onclick="alert('Here\'s a single quote: \' and here\'s a double quote: \&quot;');">


en als je toch ENT_QUOTES gebruikt (bijvoorbeeld omdat je zelf de markup niet in de hand hebt en iemand anders misschien wel single quotes gebruikt voor attributes - god knows why - dan zou de source er zo uitzien:

HTML:
1
<img onclick='alert('Here\'s a single quote: \' and here\'s a double quote: \&quot;');'>


of simpel:
HTML:
1
<img onclick='alert('\'');'>

note de backslash :)

[ Voor 16% gewijzigd door crisp op 09-02-2007 22:57 ]

Intentionally left blank


  • JayVee
  • Registratie: Mei 2002
  • Laatst online: 14-11 21:30

JayVee

shibby++!

Topicstarter
Ik snap het verschil, maar het is best lastig om zo inline javascript goed te escapen. Ik heb wel volledige controle over de content, en attribute values staan altijd tussen double quotes.

Het werkt nu goed, zelfs met een erg moeilijk string
code:
1
'h<4/x>0\r"\n


Alleen loop ik nu tegen een bug in overlib aan :(
HTML:
1
<img onclick="return overlib( 'Hallo \\r\\n', CAPTION, 'Hallo \\r\\n' );" />

De body wordt goed getoond, alleen de caption wordt 'Hallo ' (met twee spaties). Wie weet kan ik het fixen en mijn eerste (nuttige) open source contribution doen! :Y)

Bedankt voor de uitleg iig!

ASCII stupid question, get a stupid ANSI!


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Ik neem aan dat de overlib functie gewoon 1 argument nodig heeft, dus zal je string concattenation moeten doen:
HTML:
1
<img onclick="return overlib( 'Hallo \\r\\n' + CAPTION + 'Hallo \\r\\n' );">

Wel heb ik wat algemene opmerkingen:

1) Het img-element heeft geen default actie, je hoeft dus geen waarde te retourneren
2) Ik neem aan dat CAPTION een global variabele is die ergens wordt geinstantieerd? Ik zou dergelijke globals toch niet graag her en der verspreid in mijn markup willen zien...
3) Sowieso is scheiding van markup en behavior good practice; inline eventhandlers breken met die goede gewoonte.

Ik meen dat overlib een soort JS-alternatief is voor de gewone reguliere tooltip, mijn approach zou dan ook zijn om te beginnen met een reguliere tooltip mbv het title-attribuut en met unobtrusive scripting hier een overlib-sausje overheen te gooien :)

Intentionally left blank


  • JayVee
  • Registratie: Mei 2002
  • Laatst online: 14-11 21:30

JayVee

shibby++!

Topicstarter
1) De img tag en de onclick handler heb ik alleen voor het voorbeeld gekozen, kostten het minst markup
// edit: was <a> vergeten }:O
2) overlib werkt zoals in mijn voorbeelden, CAPTION is inderdaad een constante
3) Als het "statische" functionaliteit betreft zet ik javascript code zelf ook liever in aparte bestanden (of laat ik deze dynamisch door php genereren, als het veel code is). In dit geval gaat het echter om een enkele call naar overlib, die ik het liefst op deze manier wil doen. Aangezien het echter een bitch is om helemaal correct te escapen op deze manier ga ik er misschien nog eens over nadenken.

De overlib tooltips gebruik ik waar de title tooltip niet genoeg mogelijkheden bieden. Zo gebruik ik hem om een lijst van links naar documenten, met mooie plaatjes etc, te tonen. Overlib kan complete HTML (zelfs iframes) in een tooltip zetten en is erg krachtig.

ASCII stupid question, get a stupid ANSI!


  • crisp
  • Registratie: Februari 2000
  • Nu online

crisp

Devver

Pixelated

Als je met identifiers werkt en de teksten zelf apart in een object stopt heb je al een stuk minder last van het feit dat je dubbel moet escapen:
HTML:
1
2
3
4
5
6
7
8
9
10
11
12
13
<img onclick="myoverlib('hello')">
<script type="text/javascript">
var overlibTexts =
{
    hello: 'Hallo \\r\\n' + CAPTION + 'Hallo \\r\\n',
    bye: 'Tot ziens'
}
function myoverlib(id)
{
  if (id in overlibTexts)
    overlib(overlibTexts[id]);
}
</script>

Intentionally left blank

Pagina: 1