Skip to content

Commit

Permalink
[e] (0) An intro section on avoiding common pitfalls with scripts. Fi…
Browse files Browse the repository at this point in the history
…le bugs if you have ideas of other things to mention here.

Fixing http://www.w3.org/Bugs/Public/show_bug.cgi?id=12664

git-svn-id: http://svn.whatwg.org/webapps@6421 340c8d12-0b0e-0410-8428-c7bf67bfef74
  • Loading branch information
Hixie committed Aug 11, 2011
1 parent fc893bf commit 6f4a955
Show file tree
Hide file tree
Showing 3 changed files with 197 additions and 4 deletions.
68 changes: 66 additions & 2 deletions complete.html
Expand Up @@ -298,7 +298,8 @@ <h2 class="no-num no-toc" id=contents>Table of contents</h2>
<li><a href=#typographic-conventions><span class=secno>1.8.2 </span>Typographic conventions</a></ol></li>
<li><a href=#a-quick-introduction-to-html><span class=secno>1.9 </span>A quick introduction to HTML</a>
<ol>
<li><a href=#writing-secure-applications-with-html><span class=secno>1.9.1 </span>Writing secure applications with HTML</a></ol></li>
<li><a href=#writing-secure-applications-with-html><span class=secno>1.9.1 </span>Writing secure applications with HTML</a></li>
<li><a href=#common-pitfalls-to-avoid-when-using-the-scripting-apis><span class=secno>1.9.2 </span>Common pitfalls to avoid when using the scripting APIs</a></ol></li>
<li><a href=#conformance-requirements-for-authors><span class=secno>1.10 </span>Conformance requirements for authors</a>
<ol>
<li><a href=#presentational-markup><span class=secno>1.10.1 </span>Presentational markup</a></li>
Expand Down Expand Up @@ -2305,7 +2306,70 @@ <h4 id=writing-secure-applications-with-html><span class=secno>1.9.1 </span>Writ

</dd>

</dl><h3 id=conformance-requirements-for-authors><span class=secno>1.10 </span>Conformance requirements for authors</h3>
</dl><h4 id=common-pitfalls-to-avoid-when-using-the-scripting-apis><span class=secno>1.9.2 </span>Common pitfalls to avoid when using the scripting APIs</h4>

<p><i>This section is non-normative.</i></p>

<p>Scripts in HTML have "run-to-completion" semantics, meaning that
the browser will generally run the script uninterrupted before doing
anything else, such as firing further events or continuing to parse
the document.</p>

<p>On the other hand, parsing of HTML files happens asynchronously
and incrementally, meaning that the parser can pause at any point to
let scripts run. This is generally a good thing, but it does mean
that authors need to be careful to avoid hooking event handlers
after the events could have possibly fired.</p>

<p>There are two techniques for doing this reliably: use <a href=#event-handler-content-attributes>event
handler content attributes</a>, or create the element and add the
event handlers in the same script. The latter is safe because, as
mentioned earlier, scripts are run to completion before further
events can fire.</p>

<div class=example>

<p>One way this could manifest itself is with <code><a href=#the-img-element>img</a></code>
elements and the <code title=event-load>load</code> event. The
event could fire as soon as the element has been parsed, especially
if the image has already been cached (which is common).</p>

<p>Here, the author uses the <code title=handler-onload><a href=#handler-onload>onload</a></code> handler on an <code><a href=#the-img-element>img</a></code>
element to catch the <code title=event-load>load</code> event:</p>

<pre>&lt;img src="games.png" alt="Games" onload="gamesLogoHasLoaded(event)"&gt;</pre>

<p>If the element is being added by script, then so long as the
event handlers are added in the same script, the event will still
not be missed:</p>

<pre>&lt;script&gt;
var img = new Image();
img.src = 'games.png';
img.alt = 'Games';
img.onload = gamesLogoHasLoaded;
// img.addEventListener('load', gamesLogoHasLoaded, false); // would work also
&lt;/script&gt;</pre>

<p>However, if the author first created the <code><a href=#the-img-element>img</a></code>
element and then in a separate script added the event listeners,
there's a chance that the <code title=event-load>load</code>
event would be fired in between, leading it to be missed:</p>

<pre class=bad>&lt;!-- Do not use this style, it has a race condition! --&gt;
&lt;img id="games" src="games.png" alt="Games"&gt;
&lt;!-- the 'load' event might fire here while the parser is taking a
break, in which case you will not see it! --&gt;
&lt;script&gt;
var img = document.getElementById('games');
img.onload = gamesLogoHasLoaded; // might never fire!
&lt;/script&gt;</pre>

</div>



<h3 id=conformance-requirements-for-authors><span class=secno>1.10 </span>Conformance requirements for authors</h3>

<p><i>This section is non-normative.</i></p>

Expand Down
68 changes: 66 additions & 2 deletions index
Expand Up @@ -298,7 +298,8 @@
<li><a href=#typographic-conventions><span class=secno>1.8.2 </span>Typographic conventions</a></ol></li>
<li><a href=#a-quick-introduction-to-html><span class=secno>1.9 </span>A quick introduction to HTML</a>
<ol>
<li><a href=#writing-secure-applications-with-html><span class=secno>1.9.1 </span>Writing secure applications with HTML</a></ol></li>
<li><a href=#writing-secure-applications-with-html><span class=secno>1.9.1 </span>Writing secure applications with HTML</a></li>
<li><a href=#common-pitfalls-to-avoid-when-using-the-scripting-apis><span class=secno>1.9.2 </span>Common pitfalls to avoid when using the scripting APIs</a></ol></li>
<li><a href=#conformance-requirements-for-authors><span class=secno>1.10 </span>Conformance requirements for authors</a>
<ol>
<li><a href=#presentational-markup><span class=secno>1.10.1 </span>Presentational markup</a></li>
Expand Down Expand Up @@ -2202,7 +2203,70 @@ a.setAttribute('href', 'http://example.com/'); // change the content attribute d

</dd>

</dl><h3 id=conformance-requirements-for-authors><span class=secno>1.10 </span>Conformance requirements for authors</h3>
</dl><h4 id=common-pitfalls-to-avoid-when-using-the-scripting-apis><span class=secno>1.9.2 </span>Common pitfalls to avoid when using the scripting APIs</h4>

<p><i>This section is non-normative.</i></p>

<p>Scripts in HTML have "run-to-completion" semantics, meaning that
the browser will generally run the script uninterrupted before doing
anything else, such as firing further events or continuing to parse
the document.</p>

<p>On the other hand, parsing of HTML files happens asynchronously
and incrementally, meaning that the parser can pause at any point to
let scripts run. This is generally a good thing, but it does mean
that authors need to be careful to avoid hooking event handlers
after the events could have possibly fired.</p>

<p>There are two techniques for doing this reliably: use <a href=#event-handler-content-attributes>event
handler content attributes</a>, or create the element and add the
event handlers in the same script. The latter is safe because, as
mentioned earlier, scripts are run to completion before further
events can fire.</p>

<div class=example>

<p>One way this could manifest itself is with <code><a href=#the-img-element>img</a></code>
elements and the <code title=event-load>load</code> event. The
event could fire as soon as the element has been parsed, especially
if the image has already been cached (which is common).</p>

<p>Here, the author uses the <code title=handler-onload><a href=#handler-onload>onload</a></code> handler on an <code><a href=#the-img-element>img</a></code>
element to catch the <code title=event-load>load</code> event:</p>

<pre>&lt;img src="games.png" alt="Games" onload="gamesLogoHasLoaded(event)"&gt;</pre>

<p>If the element is being added by script, then so long as the
event handlers are added in the same script, the event will still
not be missed:</p>

<pre>&lt;script&gt;
var img = new Image();
img.src = 'games.png';
img.alt = 'Games';
img.onload = gamesLogoHasLoaded;
// img.addEventListener('load', gamesLogoHasLoaded, false); // would work also
&lt;/script&gt;</pre>

<p>However, if the author first created the <code><a href=#the-img-element>img</a></code>
element and then in a separate script added the event listeners,
there's a chance that the <code title=event-load>load</code>
event would be fired in between, leading it to be missed:</p>

<pre class=bad>&lt;!-- Do not use this style, it has a race condition! --&gt;
&lt;img id="games" src="games.png" alt="Games"&gt;
&lt;!-- the 'load' event might fire here while the parser is taking a
break, in which case you will not see it! --&gt;
&lt;script&gt;
var img = document.getElementById('games');
img.onload = gamesLogoHasLoaded; // might never fire!
&lt;/script&gt;</pre>

</div>



<h3 id=conformance-requirements-for-authors><span class=secno>1.10 </span>Conformance requirements for authors</h3>

<p><i>This section is non-normative.</i></p>

Expand Down
65 changes: 65 additions & 0 deletions source
Expand Up @@ -1098,6 +1098,71 @@ a.setAttribute('href', 'http://example.com/'); // change the content attribute d
</dl>



<h4>Common pitfalls to avoid when using the scripting APIs</h4>

<!--END dev-html--><p><i>This section is non-normative.</i></p><!--START dev-html-->

<p>Scripts in HTML have "run-to-completion" semantics, meaning that
the browser will generally run the script uninterrupted before doing
anything else, such as firing further events or continuing to parse
the document.</p>

<p>On the other hand, parsing of HTML files happens asynchronously
and incrementally, meaning that the parser can pause at any point to
let scripts run. This is generally a good thing, but it does mean
that authors need to be careful to avoid hooking event handlers
after the events could have possibly fired.</p>

<p>There are two techniques for doing this reliably: use <span>event
handler content attributes</span>, or create the element and add the
event handlers in the same script. The latter is safe because, as
mentioned earlier, scripts are run to completion before further
events can fire.</p>

<div class="example">

<p>One way this could manifest itself is with <code>img</code>
elements and the <code title="event-load">load</code> event. The
event could fire as soon as the element has been parsed, especially
if the image has already been cached (which is common).</p>

<p>Here, the author uses the <code
title="handler-onload">onload</code> handler on an <code>img</code>
element to catch the <code title="event-load">load</code> event:</p>

<pre>&lt;img src="games.png" alt="Games" onload="gamesLogoHasLoaded(event)"></pre>

<p>If the element is being added by script, then so long as the
event handlers are added in the same script, the event will still
not be missed:</p>

<pre>&lt;script>
var img = new Image();
img.src = 'games.png';
img.alt = 'Games';
img.onload = gamesLogoHasLoaded;
// img.addEventListener('load', gamesLogoHasLoaded, false); // would work also
&lt;/script></pre>

<p>However, if the author first created the <code>img</code>
element and then in a separate script added the event listeners,
there's a chance that the <code title="event-load">load</code>
event would be fired in between, leading it to be missed:</p>

<pre class="bad">&lt;!-- Do not use this style, it has a race condition! -->
&lt;img id="games" src="games.png" alt="Games">
&lt;!-- the 'load' event might fire here while the parser is taking a
break, in which case you will not see it! -->
&lt;script>
var img = document.getElementById('games');
img.onload = gamesLogoHasLoaded; // might never fire!
&lt;/script></pre>

</div>



<h3>Conformance requirements for authors</h3>

<!--END dev-html--><p><i>This section is non-normative.</i></p><!--START dev-html-->
Expand Down

0 comments on commit 6f4a955

Please sign in to comment.