CDATA comment?

I am implementing the Suckerfish Dropdown menus to my site, and am planning to have the javascript portion reside externally. The inline script from the tutorial starts with


and ends with


Not knowing what these are, I was unsure of how to handle them in the external javascript file. Can someone please enlighten me?

You don’t need them in an external JavaScript. :slight_smile:

Good to know…so what are they? I understand the concept of putting a ordinary comment tag around script and style info in the <head>, is this some sort of expansion on this idea?

In XHTML you can’t have code like JavaScript or CSS. CDATA is basically like a comment for them so the parser ignores what in between the opening and closing CDATA tags.

Thanks. That was my assumption, but wasn’t sure…that’s a heck of a comment tag! :slight_smile:

The problem with having JavaScript (or CSS) inside an (X)HTML document is that some characters that are common in scripts have special meaning in the markup language. ‘>’, for instance. Thus you need to escape or protect these.

A common old-skool way was to enclose the whole script in an SGML comment, but that doesn’t work with real XHTML, because XML parsers are free to ignore anything within comments. But X(HT)ML offers another way: CDATA sections. The only character sequence that is special there is ‘]]>’ which doesn’t normally occur very often in JavaScript or CSS.

Now, if you’re serving real XHTML, all you need is this:

<script type="application/x-javascript">
... script code here ...

However, if you’re using pretend-XHTML (served as text/html) it is really HTML, and obeys the rules of HTML. CDATA sections are useless in HTML browsers, so you hide the CDATA markers within an SGML comment.

If you want this to work even if served as application/xhtml+xml (and why else would you use XHTML?) you need the trickery above.

Of course, putting the script in an external file is rather easier … :slight_smile:

Actually, it’s more complicated than that. For XHTML, all you need is <![CDATA[ and ]]>. However, typical HTML parsers don’t understand <![CDATA[ and will throw an error if it is inside a script or style element. So we have to resort to a hack:

starting line: <!–//–><![CDATA[//><!–

ending line: //–><!]]>

This is how it works:

Remember how HTML parsers ignore the first line in a script element if it starts with “<!–”? That would prevent HTML parsers from seeing the “<![CDATA[”. However, that type of trick doesn’t work in XHTML and would in fact prevent the script from being executed. So we need to end the comment (“–>”) before the “<![CDATA[”, but if we do that, than the “<![CDATA[” would no longer be hidden to some HTML parsers. So inside the comment, we add “//” that the XHTML parser will ignore (since it really ignores everything inside comments) and most HTML parsers will allow their JS parsers to comment out the rest of the line, including the “<![CDATA[”.

So: <!–//–><![CDATA[

Most modern browsers would actually work with just “<!-- –>”, since the “<!–” itself would comment out the whole line, but not all HTML parsers are like that.

But what about legacy browsers that don’t support Javascript? In this case, the goal is to make sure the script internals aren’t displayed. Since they don’t support the “<!–” whole line commenting, the “<![CDATA[” is again visible. Next trick: turn the “<![CDATA[” into a “processing instruction” tag (<!foo>), which won’t be recognized nor outputted. “<![CDATA[>” would hide it from legacy browsers. However, it wouldn’t work with XHTML, since it would consider the “>” to be the first character of the script. So replace that with “//>” so it would ignore that “>” and the rest of the line: “<![CDATA[//>”. Finally, add the “<!–” to the end to hide the rest of the script from legacy browsers.

So: <!–//–><![CDATA[//><!–

The ending part goes along the same lines. XHTML parsers needs the “]]>”, but HTML parsers don’t understand that (and the JS parser would throw an error). So that needs to be commented out with “//”.

So: //]]>

Now to support legacy browsers. They need “–>” somewhere. It can’t go after the “]]>” since the XHTML parser will see an comment end without a comment start. That could be solved by using the “<!-- –>” trick, but there’s a more elegant solution. Add the “–>” before the “]]>” and make the “]]>” into a processing instruction tag to hide it: “–><!]]>”. Also, the “<!-- –>” would actually fail for a fully compliant HTML parser that doesn’t support JS since its actually the “–” that toggles off/on comments, not the “<!–”/“–>”, and the whole comment would be like: “<!-- …script stuff here… //]]><!-- –>”, which has 3 “–”'s. However, to avoid going into that esoteric stuff, just stick with “–><!]]>”.

So: //–><!]]>

BTW, if you don’t care about legacy browsers, you can just use this:

starting line: <!–//–><![CDATA[

ending line: //]]>