Search code examples
javascripttogglexhtml-1.0-strict

Valid xhtml 1.0 strict JS toggle without speculative parsing error


i know there are tons of toggle-scripts out there, but i couldn't find any to fit my needs so far. It should be:

  • valid xhtml 1.0 strict
  • valid css 2.1 / functional for browsers without css 3
  • visible to users without javascript (just visible... no toggle)
  • don't cause a speculative parsing error (firefox/gecko console)
  • if possible don't load a whole scriptlibrary from somewhere just for this tiny toggle function

Speculative parsing error happens when within a JavaScript section some incomplete html is written (e.g. tag not closed).

See this example, which causes speculative parsing error and flickering content while loading:

function toggle(ID) {    	
	var ele = document.getElementById(ID);
	
	if(ele.style.display == "block") {
			ele.style.display = "none"; } 
	else { 
			ele.style.display = "block"; } 
}
<a href="javascript:toggle('content')">Content Toggle Linktext</a>

<script type="text/javascript">
	/* <![CDATA[ */
	document.write('<div id="content" style="display:none;">');
	/* ]]> */
</script>

<p>Content blablabla</p>

<script type="text/javascript">
	/* <![CDATA[ */
	document.write('<\/div>');
	/* ]]> */
</script>

So how to achieve my needs? Maybe i need a completely new approach? Thanks, Stony


Solution

  • Ok i think I've found a solution by myself at this blog comment which works very well at the moment and makes the html much easier to read. The script is loaded in the header.

    /* JavaScript */
    function toggle(ID) {   
        var ele = document.getElementById(ID);
    
        if (ele.style.display === "block") {
                ele.style.display = "none"; }
        else {
                ele.style.display = "block"; }
    }
    
    document.documentElement.className += " CssClassJsLoad";
    // writes the classname "CssClassJsLoad" into the <html>-tag to make sure document is completely loaded by browser before parsing starts
    
    /* CSS */
    .CssClassJsLoad .JsHide {
        display:none; }
    /* For all objects within both of these classes: Do not display.
    Remember: the <html>-tag only gets the class "CssClassJsLoad" if JS is present or respectively successfully executed. So if JS is not present, display will be standard as "block" element */
    
    <!-- HTML -->
    <a id="content-link" href="javascript:toggle('content')">Content Toggle Linktext</a>
    
    <div class="JsHide" id="content">
      <p>Content Text blablabla. Inherits class "JsHide" from surrounding div and "CssClassJsLoad" from surrounding html-tag</p>
    </div>