Compare Revisions
Last modification
- Rev 2 2012-12-15 20:48:17
- Author: PointedEars
- Log message:
Added original FAQs:
- cljs FAQ and FAQ Notes
- SELFHTML.DE JavaScript-FAQ
/trunk/.project |
0,0 → 1,28 |
<?xml version="1.0" encoding="UTF-8"?> |
<projectDescription> |
<name>FAQs</name> |
<comment></comment> |
<projects> |
</projects> |
<buildSpec> |
<buildCommand> |
<name>org.eclipse.wst.common.project.facet.core.builder</name> |
<arguments> |
</arguments> |
</buildCommand> |
<buildCommand> |
<name>org.eclipse.wst.validation.validationbuilder</name> |
<arguments> |
</arguments> |
</buildCommand> |
<buildCommand> |
<name>org.eclipse.dltk.core.scriptbuilder</name> |
<arguments> |
</arguments> |
</buildCommand> |
</buildSpec> |
<natures> |
<nature>org.eclipse.php.core.PHPNature</nature> |
<nature>org.eclipse.wst.common.project.facet.core.nature</nature> |
</natures> |
</projectDescription> |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: selfhtml.de/index.html |
=================================================================== |
--- selfhtml.de/index.html (nonexistent) |
+++ selfhtml.de/index.html (revision 2) |
@@ -0,0 +1,258 @@ |
+<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN" |
+ "http://www.w3.org/TR/html4/strict.dtd"> |
+<html> |
+<head> |
+<meta http-equiv="Content-Type" content="text/html; charset=ISO-8859-1"> |
+<meta name="generator" content="HTML Tidy, see www.w3.org"> |
+ |
+<title>JavaScript- und Java-Linkliste</title> |
+ |
+<style type="text/css"> |
+a[href ^="http:"]:before { |
+ content: "\2192"; |
+ text-decoration: none; |
+ color: inherit; |
+ background-color: inherit; |
+} |
+ |
+ul a[href ^="http:"]:before { |
+ content: ""; |
+} |
+</style> |
+</head> |
+ |
+<body> |
+<h1>JavaScript- und Java-Linkliste</h1> |
+ |
+<h2>Vorwort</h2> |
+ |
+<p>Dies ist ein informativer Text, der (technische) Fakten |
+vermittelt, <strong>keine</strong> Meinungen!</p> |
+ |
+<p>Bei FAQs (<b>F</b>requently <b>A</b>sked <b>Q</b>uestions = |
+häufig gestellte Fragen) und bei Fragen, die darauf hindeuten, dass dem |
+Teilnehmer der Unterschied zwischen Java und JavaScript nicht klar ist, |
+sollte hierauf verwiesen werden.</p> |
+ |
+<p>Hilfreiche Kommentare und Verbesserungsvorschläge bitte <strong>nur</strong> |
+per E-Mail an faq@PointedEars.de <strong>direkt</strong> an mich. Alles |
+andere bitte nach /dev/tonne, danke.</p> |
+ |
+<p>Vielen Dank für die Idee zu diesem Posting an <a |
+ href="http://homepage.boku.ac.at/partl/">Dr. Hubert Partl</a>, der |
+einen ähnlichen Text regelmässig in den <a |
+ href="http://einklich.net/usenet/usenet1.htm">Usenet</a>-Newsgroups |
+<a href="news:de.comp.lang.javascript">de.comp.lang.javascript</a> |
+und <a href="news:de.comp.lang.java">de.comp.lang.java</a> (hier |
+mit einem Klick zum Abo) postet.</p> |
+ |
+<hr> |
+ |
+<h2>Worum geht es?</h2> |
+ |
+<p>Viele Fragen, die gestellt werden, wurden vorher bereits |
+diskutiert und beantwortet. Das erneute Stellen dieser Fragen <strong>nervt</strong> |
+die Teilnehmer, die hier schon länger mitlesen und -posten (kurz: |
+Regulars, von engl. "regular" = regelmässig), denn niemand möchte die |
+gleiche Frage immer wieder beantworten.</p> |
+ |
+<p>Das hat dann oft gereizte Reaktionen zur Folge und der Fragende |
+wundert sich darüber, denn er stellt ja die Frage aus seiner Perspektive |
+das erste Mal.</p> |
+ |
+<p>Um Auseinandersetzungen zu vermeiden, mögen bitte die Regulars |
+einfach auf dieses Dokument verweisen und die Frager versuchen, Probleme |
+<strong>vor</strong> dem Posten über die Links in dieser FAQ sowie |
+einschlägige Literatur und <strong>Selbst</strong>studium (einfach mal |
+was ausprobieren!) zu lösen.</p> |
+ |
+<p>Weitere Information zum Auffinden von früheren Antworten findet |
+man(n) auf der <a href="http://dcljs.de/">Website der Gruppe</a>. |
+<p>Ausserdem gibt es regelmässig Verwechslungen zwischen den beiden |
+<strong>Programmiersprachen</strong> <a href="#java">Java</a> und <a |
+ href="#js">JavaScript</a>. Java ist <strong>nicht</strong> JavaScript |
+(kurz: Java <strong>!=</strong> JavaScript), und umgekehrt.</p> |
+ |
+<hr> |
+ |
+<h2><a name="js">JavaScript</a></h2> |
+ |
+<p>Script-Sprache z.B. innerhalb von HTML-Dokumenten.</p> |
+ |
+<p><a href="#ecmascript">ECMAScript</a>-Implementation von <a |
+ href="#netscape">Netscape</a> (siehe Microsoft <a href="#jscript">JScript</a>).</p> |
+ |
+<p>Wird von Netscape Navigator bis 4.x (Mozilla/4.0) und Netscape <a |
+ href="#gecko">Gecko</a> (Rendering-Engine von Mozilla/5.0 -- d.h. |
+Mozilla SeaMonkey, Mozilla Firefox/Thunderbird, Netscape 6+, Camino, |
+...) verwendet.</p> |
+ |
+<p>(X)HTML-Element: <code>script</code></p> |
+<ul> |
+ <li><a href="http://www.w3.org/TR/html4/interact/scripts.html">Normative |
+ Version</a> (englisch)</li> |
+ <li><a |
+ href="http://edition-w3.de/TR/1999/REC-html401-19991224/interact/scripts.html">Vorveröffentlichung |
+ der Deutschen Übersetzung</a></li> |
+</ul> |
+ |
+<p>.js-Dateien (üblich), wenn als externe Scripte eingebunden</p> |
+ |
+<h2>Referenzen</h2> |
+ |
+<ul> |
+ <li><a name="ecmascript" id="ecmascript" |
+ href="http://www.mozilla.org/js/language/">ECMAScript (ECMA-262)</a> |
+ (englisch)</li> |
+ |
+ <li><a name="netscape">Mozilla Developer Center (MDC)</a> |
+ (englisch):<br> |
+ <ul> |
+ <li><a href="http://developer.mozilla.org/en/docs/JavaScript">JavaScript</a></li> |
+ |
+ <li><a href="http://developer.mozilla.org/en/docs/DOM">DOM</a></li> |
+ |
+ <li><a name="gecko" id="gecko" |
+ href="http://developer.mozilla.org/en/docs/Gecko_DOM_Reference">Gecko |
+ DOM Reference</a> (englisch)</li> |
+ </ul> |
+ </li> |
+ |
+ <li>W3C-DOM Level 2 (englisch): |
+ <ul> |
+ <li><a href="http://www.w3.org/TR/DOM-Level-2/">Core</a></li> |
+ <li><a href="http://www.w3.org/TR/DOM-Level-2-Events/">Events</a></li> |
+ <li><a href="http://www.w3.org/TR/DOM-Level-2-HTML/">HTML</a></li> |
+ <li><a href="http://www.w3.org/TR/DOM-Level-2-Style/">Style</a></li> |
+ </ul> |
+ </li> |
+ |
+ <li>Microsoft Developer Network (MSDN) Library (englisch): |
+ <ul> |
+ <li><a name="jscript" id="jscript" |
+ href="http://msdn.microsoft.com/library/en-us/script56/html/js56jsoriJScript.asp">JScript</a>: |
+ <a href="#ecmascript">ECMAScript</a>-Implementation von Microsoft, |
+ wird u.a. von der IE-Browserkomponente, <a href="http://asp.net/">Active |
+ Server Pages (ASP)</a> und dem Windows Script Host verwendet.</li> |
+ |
+ <li><a |
+ href="http://msdn.microsoft.com/nhp/Default.asp?contentid=28001169">Windows |
+ Script Documentation</a></li> |
+ |
+ <li><a |
+ href="http://msdn.microsoft.com/workshop/author/dhtml/reference/dhtml_reference_entry.asp">HTML |
+ and DHTML Reference</a> (DOM-Referenz zur IE-Browserkomponente)</li> |
+ </ul> |
+ </li> |
+</ul> |
+ |
+<h3>FAQs, FFQs</h3> |
+ |
+<ul> |
+ <li><a href="http://dcljs.de/faq/">FAQ -- |
+ Frequently Asked Questions -- Häufig gestellte Fragen</a></li> |
+ |
+ <li><a name="ffq" id="ffq" href="http://praast.de/ffq/">FFQ |
+ -- Frequently Forbidden Questions -- "Verbotene" Fragen</a></li> |
+ |
+ <li><a href="http://dcljs.de/">Website der Newsgroup |
+ de.comp.lang.javascript</a></li> |
+</ul> |
+ |
+<h3>Testcases, Tools</h3> |
+ |
+<ul> |
+ <li><a href="http://www.brain4.de/programmierecke/js/">JavaScript-Ecke |
+ von Ralf Beutler, u.a. zur Abfrage von Maus und Tastatur-Ereignissen</a></li> |
+ |
+ <li><a href="http://PointedEars.de/scripts/test/whatami">Was |
+ bin ich? -- Wie "gut" Browsererkennung ist</a> von Thomas 'PointedEars' |
+ Lahn</li> |
+ |
+ <li><a href="http://PointedEars.de/scripts/test/hoverMe/">hoverMe |
+ -- Vorladen von Bildern und Realisierung des Hover-Effekts</a> von Thomas |
+ 'PointedEars' Lahn (unter Beachtung der Lizenzbestimmungen frei |
+ verwendbar)</li> |
+ |
+ <li><a |
+ href="http://PointedEars.de/scripts/test/ObjectInspector/nightly/latest/index">ObjectInspector</a> |
+ von Thomas 'PointedEars' Lahn (unter Beachtung der Lizenzbestimmungen |
+ frei verwendbar)</li> |
+ |
+ <li><a href="http://PointedEars.de/scripts/js-version-info">JS/ECMAScript-Versionsinformation</a></li> |
+ |
+ <li><a href="http://PointedEars.de/scripts/test/mime-types/">Support |
+ von für JS/ECMAScript registrierten MIME-Typen</a></li> |
+</ul> |
+ |
+<h3>Tutorials, Fertigscripte (siehe <a href="#ffq">FFQ</a>)</h3> |
+ |
+<ul> |
+ <li>"SELFHTML -- HTML-Dateien selbst erstellen" von Stefan Münz: |
+ <ul> |
+ <li><a href="http://selfhtml.teamone.de/javascript/">JavaScript</a></li> |
+ <li><a href="http://selfhtml.teamone.de/dhtml/">Dynamisches |
+ HTML (DHTML)</a></li> |
+ </ul> |
+ </li> |
+ |
+ <li><a href="http://javascript.seite.net/">Kakao |
+ & Kekse -- Die deutsche JavaScript-Seite</a></li> |
+ |
+ <li><a href="http://dhtml.seite.net/">Milch & Zucker -- |
+ Die deutsche DHTML-Seite</a></li> |
+</ul> |
+ |
+<hr> |
+ |
+<h2><a name="java">Java</a></h2> |
+ |
+<p>Programmiersprache für Applets und Applikationen</p> |
+ |
+<p>(X)HTML-Elemente: <code>applet</code>, <code>object</code></p> |
+<ul> |
+ <li><a href="http://www.w3.org/TR/html4/struct/objects.html">Normative |
+ Version</a> (englisch)</li> |
+ <li><a |
+ href="http://edition-w3.de/TR/1999/REC-html401-19991224/struct/objects.html">Vorveröffentlichung |
+ der Deutschen Übersetzung</a></li> |
+</ul> |
+ |
+<ul> |
+ <li>Quelltext: .java-Dateien (üblich)</li> |
+ <li>Compiliert: |
+ <ul> |
+ <li>.class-Dateien (zwingend, plattformunabhängig),</li> |
+ <li>.exe-Dateien (plattformabhängig)</li> |
+ </ul> |
+ </li> |
+</ul> |
+ |
+<h3>Referenzen</h3> |
+ |
+<p><a href="http://developer.java.sun.com/developer/infodocs/">Sun |
+Java Documentation & Training (englisch)</a></p> |
+ |
+<h3>FAQs, weiterführende Information</h3> |
+ |
+<ul> |
+ <li><a href="http://www.dclj.de/faq.html">FAQ -- |
+ Frequently Asked Questions -- Häufig gestellte Fragen</a></li> |
+ |
+ <li><a href="http://dclj.de/">Website der Newsgroup |
+ de.comp.lang.java</a></li> |
+</ul> |
+ |
+<h3>Tutorials, fertiger Code (siehe <a href="#ffq">FFQ</a>)</h3> |
+ |
+<ul> |
+ <li>"SELFHTML -- HTML-Dateien selbst erstellen" von Stefan Münz:<br> |
+ <a |
+ href="http://selfhtml.teamone.de/html/multimedia/java_applets.htm#einbinden">Java-Applets |
+ einbinden</a></li> |
+ |
+ <li><a href="http://java.seite.net/">Kaffee & |
+ Kuchen -- Die deutsche Java-Seite</a></li> |
+</ul> |
+</body> |
+</html> |
\ No newline at end of file |
/selfhtml.de/index.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: .buildpath |
=================================================================== |
--- .buildpath (nonexistent) |
+++ .buildpath (revision 2) |
@@ -0,0 +1,5 @@ |
+<?xml version="1.0" encoding="UTF-8"?> |
+<buildpath> |
+ <buildpathentry kind="src" path=""/> |
+ <buildpathentry kind="con" path="org.eclipse.php.core.LANGUAGE"/> |
+</buildpath> |
Index: cljs/faq_notes/cookies.html |
=================================================================== |
--- cljs/faq_notes/cookies.html (nonexistent) |
+++ cljs/faq_notes/cookies.html (revision 2) |
@@ -0,0 +1,120 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
+<html lang="en"><head><title>Cookies</title> |
+<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> |
+<link href="../faq.css" rel="stylesheet" type="text/css"> |
+<link href="faq_notes.css" rel="stylesheet" type="text/css"> |
+</head> |
+<body> |
+ |
+<h1><a name="cookies" id="cookies">Cookies</a></h1> |
+ |
+<ul> |
+ <li><a href="#proxIs">Privacy filters on proxies</a></li> |
+</ul> |
+ |
+<h2><a name="proxIs" id="proxIs">Privacy filters on proxies</a></h2> |
+ |
+<p id="proxIs_1"> |
+<a href="http://www.w3schools.com/js/js_cookies.asp">The page |
+referenced</a> from <a href="http://jibbering.com/faq/#FAQ4_4">section 4.4 of |
+the FAQ</a> describes a generally sound strategy for using cookies but suffers from |
+an additional issue relating to "privacy" filters employed by content |
+inserting/re-writing proxies. |
+</p> |
+ |
+<p id="proxIs_2"> |
+The problem is that some of these filters identify the character sequence |
+"cookie" within Javascript source code and replace it with an |
+alternative string. <a href="http://groups.google.com/groups?threadm=41ebaba2.0306240406.1fdff5ef%40posting.google.com"> |
+A c.l.j. thread describing an occurrence of this problem</a> had |
+"cookie" replaced by "ignore" by ZoneAlarm, and |
+Proximatron has a similar filter available (but not active) by default. |
+</p> |
+ |
+<p id="proxIs_3"> |
+The effect of changing occurrences of <code>document.cookie</code> |
+into <code>document.ignore</code> within source code is that attempts |
+to write to the property just result in a new string property being |
+assigned to the document object, but no cookie is created. And reading |
+from the property returns the same string, or an undefined value |
+if nothing has yet been written to the property. |
+</p> |
+ |
+<p id="proxIs_4"> |
+The problem with the irt.org code is that the <code>Get_Cookie</code> |
+and <code>Set_Cookie</code> functions are |
+not written with a consideration that <code>document.cookie</code> may |
+not refer to a string. |
+</p> |
+ |
+<p id="proxIs_5"> |
+<code>Get_Cookie</code> will error if "cookie" has been replaced with |
+"ignore" because it treats the <code>document.cookie</code> |
+value as if it was a string. But changing that one function so that it |
+does not attempt to read <code>document.cookie</code> if the value is |
+not a string may prevent the error but would still undermine that strategy used. |
+</p> |
+ |
+<p id="proxIs_6"> |
+However, the problem can be completely avoided by wrapping the content |
+of the <code>Get_Cookie</code> and <code>Set_Cookie</code> functions |
+in <code>typeof</code> tests and only executing the rest of the |
+function if <code>typeof</code> returns <code>"string"</code>. |
+</p> |
+ |
+ |
+<pre id="proxIs_ex1"> |
+function Get_Cookie(name) { |
+ if(typeof document.cookie == "string"){ |
+ var start = document.cookie.indexOf(name+"="); |
+ var len = start+name.length+1; |
+ if ((!start)&& |
+ (name != document.cookie.substring(0,name.length))){ |
+ return null; |
+ } |
+ if (start == -1) return null; |
+ var end = document.cookie.indexOf(";",len); |
+ if (end == -1) end = document.cookie.length; |
+ return unescape(document.cookie.substring(len,end)); |
+ }else{ |
+ <span class="commentJS">/* document.cookie is not a string so return an |
+ empty string. When tested this will type-convert to |
+ boolean false (accurately) giving the impression that |
+ client-side cookies are not available on this system:- |
+ */</span> |
+ return ""; |
+ } |
+} |
+ |
+function Set_Cookie(name,value,expires,path,domain,secure) { |
+ if(typeof document.cookie == "string"){ |
+ document.cookie = name + "=" +escape(value) + |
+ ( (expires) ? ";expires=" + expires.toGMTString() : "") + |
+ ( (path) ? ";path=" + path : "") + |
+ ( (domain) ? ";domain=" + domain : "") + |
+ ( (secure) ? ";secure" : ""); |
+ }<span class="commentJS">//else document.cookie is not a string so do not write to it.</span> |
+} |
+ |
+function Delete_Cookie(name,path,domain) { |
+ if (Get_Cookie(name)) document.cookie = name + "=" + |
+ ( (path) ? ";path=" + path : "") + |
+ ( (domain) ? ";domain=" + domain : "") + |
+ ";expires=Thu, 01-Jan-70 00:00:01 GMT"; |
+ } |
+} |
+</pre> |
+ |
+<p id="proxIs_7"> |
+Cookie reading and writing is unlikely to be done sufficiently often that |
+the extra overhead of the tests will impact on the performance of |
+the resulting script. |
+</p> |
+ |
+<p id="rToc"> |
+<a href="faq_notes.html#toc">comp.lang.javascript FAQ notes T.O.C.</a> |
+</p> |
+ |
+ |
+</body> |
+</html> |
\ No newline at end of file |
/cljs/faq_notes/cookies.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/faq_notes/contributors.html |
=================================================================== |
--- cljs/faq_notes/contributors.html (nonexistent) |
+++ cljs/faq_notes/contributors.html (revision 2) |
@@ -0,0 +1,93 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
+<html lang="en"><head><title>Notes on the comp.lang.javascript FAQ</title> |
+<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> |
+<link href="../faq.css" rel="stylesheet" type="text/css"> |
+<link href="faq_notes.css" rel="stylesheet" type="text/css"> |
+<style type="text/css"> |
+.nameList, .nameList UL { |
+ list-style-type:none; |
+} |
+</style> |
+</head> |
+<body> |
+ |
+<h1>Contributors</h1> |
+<!-- listed by Date --> |
+<h2>Editors:</h2> |
+<ul class="nameList"> |
+ <li><span class="person">Jim Ley</span>. - Jan 2004</li> |
+ <li><span class="person">Richard Cornford</span>. Jan 2004 - </li> |
+</ul> |
+<!-- Alphabetical list by surname or username if not an individual's name --> |
+<h2>Contributors:</h2> |
+<ul class="nameList"> |
+ <li><span class="person">Richard Cornford</span>: |
+ <ul> |
+ <li>2 Author - Posting Questions and replies to comp.lang.javascript</li> |
+ <li>4.4.1 Author - Privacy filters on proxies</li> |
+ <li>4.13.1 Author - Referencing Forms and Form Controls</li> |
+ <li>4.15.1 Author - An Alternative DynWrite function</li> |
+ <li>4.21.1 Author - Javascript Type-Conversion</li> |
+ <li>4.26.1 Author - Browser Detecting (and what to do Instead)</li> |
+ <li>4.39.1 Author - Javascript Square Bracket Notation</li> |
+ <li>Misc 2 Author - Javascript Closures</li> |
+ <li>Misc 3 Author - How to Include Scripts in HTML Documents</li> |
+ </ul> |
+ </li> |
+ <li><span class="person">Martin Honnen</span>: |
+ <ul> |
+ <li>Misc 2 Suggestions and corrections</li> |
+ </ul> |
+ </li> |
+ <li><span class="person">Jim Ley</span>: |
+ <ul> |
+ <li>Author - The comp.lang.javascript FAQ version 7.9</li> |
+ </ul> |
+ </li> |
+ <li><span class="person">Lasse Reichstein Nielsen</span>: |
+ <ul> |
+ <li>4.13.1 Suggestions of content</li> |
+ <li>4.39.1 Technical corrections</li> |
+ <li>Misc 2 Definition of Closure</li> |
+ </ul> |
+ </li> |
+ <li><span class="person">Michael Winter</span>: |
+ <ul> |
+ <li>FAQ General suggestions and corrections</li> |
+ </ul> |
+ </li> |
+ <li><span class="person">Yann-Erwan Perio (Yep)</span>: |
+ <ul> |
+ <li>4.39.1 Code testing and suggestions</li> |
+ <li>Misc 2 Suggestions and corrections</li> |
+ </ul> |
+ </li> |
+ <li><span class="person">Mike Scirocco</span>: |
+ <ul> |
+ <li>Misc 2 Corrections</li> |
+ </ul> |
+ </li> |
+ <li><span class="person">Dr John Stockton</span>: |
+ <ul> |
+ <li>2 Additional material, suggestions and corrections</li> |
+ <li>4.15.1 Code testing and suggestions</li> |
+ <li>4.21.1 Regular expression examples and additional suggestions</li> |
+ <li>4.26.1 Suggestions and corrections</li> |
+ <li>4.39.1 Suggestions and corrections</li> |
+ <li>Misc 2 Suggestions and corrections</li> |
+ </ul> |
+ </li> |
+ <li><span class="person">Randy Webb (HikksNotAtHome)</span>: |
+ <ul> |
+ <li>4.13.1 Suggestions of content and technical corrections</li> |
+ <li>4.15.1 The first getElementById emulation for IE 4 listed</li> |
+ </ul> |
+ </li> |
+</ul> |
+ |
+<p> |
+<a href="faq_notes.html#toc">comp.lang.javascript FAQ notes T.O.C.</a> |
+</p> |
+ |
+</body> |
+</html> |
\ No newline at end of file |
/cljs/faq_notes/contributors.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/faq_notes/faqNotes.zip |
=================================================================== |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/cljs/faq_notes/faqNotes.zip |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+application/octet-stream |
\ No newline at end of property |
Index: cljs/faq_notes/square_brackets.html |
=================================================================== |
--- cljs/faq_notes/square_brackets.html (nonexistent) |
+++ cljs/faq_notes/square_brackets.html (revision 2) |
@@ -0,0 +1,369 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
+<html lang="en"><head><title>Square Bracket Notation</title> |
+<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> |
+<link href="../faq.css" rel="stylesheet" type="text/css"> |
+<link href="faq_notes.css" rel="stylesheet" type="text/css"> |
+</head> |
+<body> |
+<h1>Javascript Square Bracket Notation</h1> |
+<ul> |
+ <li><a href="#intro">Introduction</a></li> |
+ <li><a href="#sBs">Square Bracket Syntax</a></li> |
+ <li><a href="#vId">String Variables as Identifiers</a></li> |
+ <li><a href="#eId">String Expressions as Identifiers</a></li> |
+ <li><a href="#aVa">Global Variable access with the Square Bracket Notation</a></li> |
+ <li><a href="#illc">Illegal characters in Identifier-strings</a></li> |
+</ul> |
+<h2><a name="intro" id="intro">Introduction</a></h2> |
+ |
+<p id="intro_1">To be useful javascript needs to be able to access the properties of |
+objects. It is impossible to learn javascript without understanding the |
+dot notation that is normally used to access the properties of objects. |
+</p> |
+ |
+<p id="intro_2">Javascript also offers an alternative property accessor notation |
+using square brackets in a way that is similar to the way in which the |
+indexed members of an Array are accessed, except that a string is used |
+between the square brackets. This alternative notation is extremely |
+powerful and useful but gets very little coverage in most books on |
+javascript and that seems to leave novice javascript programmers |
+unaware that they even have this option.</p> |
+ |
+<p id="intro_3">The coverage in javascript books can be very poor. Looking back at |
+some of the books that I first used to learn javascript, one devotes |
+exactly one paragraph to property accessors and another actually states |
+that the square bracket notation can only be used with integer indexes |
+to access Arrays and array-like structures.</p> |
+ |
+<p id="intro_4">With an understanding of dot notation and few clues that an |
+alternative exists, novice (and a few surprisingly experienced) |
+javascript programmers often turn to the <code>eval</code> function, |
+constructing a string that represents a dot notation accessor |
+(frequently retrieving the property names from javascript variables) |
+and then passing it to the <code>eval</code> function in order to |
+access the object property that it refers to. The <code>eval</code> |
+function is just not needed to perform this type of property access |
+and it is a relatively inefficient way of doing so (plus, some embedded |
+browsers lack the resources to implement an <code>eval</code> function). |
+</p> |
+ |
+<h2><a name="sBs" id="sBs">Square Bracket Syntax</a></h2> |
+<p id="sBs_1">If you can access the property of an object using dot |
+notation, such as:-</p> |
+ |
+<pre id="sBs_ex1">document.body</pre> |
+ |
+<p id="sBs_2">- you can also use the square bracket notation:-</p> |
+ |
+<pre id="sBs_ex2">document['body']</pre> |
+ |
+<p id="sBs_3">- in which the dot and the identifier to the right of the dot are |
+replaced with a set of square brackets containing a string that |
+represents the identifier that was to the right of the dot.</p> |
+ |
+<p id="sBs_4">The Property Accessors section of javascript language specification |
+(ECMA 262) makes it clear that the dot notation and the square bracket |
+notation are parallel ways of accessing the properties of objects.</p> |
+ |
+<blockquote cite="http://www.ecma-international.org/publications/files/ecma-st/Ecma-262.pdf"> |
+<dl> |
+ <dt>ECMA 262 3rd Edition. Section 11.2.1 Property Accessors</dt> |
+ <dd> |
+ Properties are accessed by name, using either the dot notation: |
+<pre > |
+MemberExpression.Identifier |
+CallExpression.Identifier |
+</pre> |
+ or the bracket notation: |
+<pre> |
+MemberExpression[ Expression ] |
+CallExpression[ Expression ] |
+</pre> |
+ The dot notation is explained by the following syntactic conversion: |
+ <pre>MemberExpression.Identifier</pre> |
+ is identical in its behaviour to |
+ <pre>MemberExpression[ <identifier-string> ]</pre> |
+ and similarly |
+ <pre>CallExpression.Identifier</pre> |
+ is identical in its behaviour to |
+ <pre >CallExpression[ <identifier-string> ]</pre> |
+ where <code><identifier-string></code> is a string literal |
+ containing the same sequence of characters as the Identifier. |
+ <dd> |
+</dl> |
+</blockquote> |
+ |
+<p id="sBs_5">In the following simple <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> page:-</p> |
+ |
+<pre id="sBs_ex3"> |
+<html> |
+ <head> |
+ <title></title> |
+ </head> |
+ <body> |
+ <form name="formName" action="#"> |
+ <input type="text" name="inpName" value="Example value text"> |
+ </form> |
+ </body> |
+</html> |
+</pre> |
+ |
+<p id="sBs_6">- which contains a form named <code>"formName"</code> with |
+one input element named <code>"inpName"</code>. Various forms |
+of dot notation property accessor can be used to reference the |
+<code>"value"</code> property of the input element. One of |
+the simplest is:-</p> |
+ |
+<pre id="sBs_ex4"> |
+var stringOfValue = document.formName.inpName.value; |
+</pre> |
+ |
+<p id="sBs_7">This dot notation has three dots, so there are three points at which |
+the square bracket notation could be used in place of the dot notation |
+(these are all equivalent).</p> |
+ |
+<pre id="sBs_ex5"> |
+var stringOfValue = document["formName"].inpName.value; |
+ |
+var stringOfValue = document.formName["inpName"].value; |
+ |
+var stringOfValue = document.formName.inpName["value"]; |
+</pre> |
+ |
+<p id="sBs_8">The following combinations are also all equivalent to the original |
+dot notation:-</p> |
+ |
+<pre id="sBs_ex6"> |
+var stringOfValue = document["formName"].inpName["value"]; |
+ |
+var stringOfValue = document["formName"]["inpName"].value; |
+ |
+var stringOfValue = document["formName"]["inpName"]["value"]; |
+ |
+var stringOfValue = window["document"]["formName"]["inpName"]["value"]; |
+</pre> |
+ |
+<p id="sBs_9">Where the dot notation follows the dot with the identifier for the |
+property that is to be accessed, the square bracket notation replaces |
+the dot and identifier with square brackets that contain a string that |
+represents the identifier for the property (the property name).</p> |
+ |
+<h2><a name="vId" id="vId">String Variables as Identifiers</a></h2> |
+ |
+<p id="vId_1">The string used within the square brackets does not need to be a |
+string literal. It can be any expression that results in a string. |
+This is where the square bracket notation becomes most useful as the |
+expression could be a reference to a string variable that holds the |
+property name as its value, or a function call that returns a string, |
+or an expression that concatenates two strings, or any combination of |
+these.</p> |
+ |
+<p id="vId_2">This means that the identifier needed to access a property does not |
+need to be coded into a javascript. Consider the following simple |
+function:-</p> |
+ |
+<pre id="vId_ex1"> |
+function setPropertyToValue(oObj, sPropName, value){ |
+ oObj[sPropName] = value; |
+} |
+</pre> |
+ |
+<p id="vId_3">- provided with a reference to an object (<code>oObj</code>), the |
+name of a property (<code>sPropName</code>) and a value for that |
+property (<code>value</code>), it will set the value of the property |
+without needing to know what the name of the property that it is |
+setting is. Called as |
+<code>setPropertyToValue(document.formName.inpName, "value", "new value")</code> |
+it will set the value of the field in the example form above to the |
+string <code>"new value"</code>. However, called as |
+<code>setPropertyToValue(window, "location", "http://www.google.com")</code> |
+and the same function will navigate a web browser to the URL provided |
+as the final parameter. Although this is a forced example you should be |
+able to see that the square bracket notation offers considerable power |
+and flexibility.</p> |
+ |
+<p id="vId_4">Any variable that holds a string value can be used between the |
+square brackets to form a property accessor. Variables that hold |
+non-strings will have their value internally type converted into a |
+string and that string will be used as the property name. This is not very |
+useful, especially if the variables contain references to objects or |
+functions, as the returned string is likely to be implementation |
+dependent.</p> |
+ |
+<h2><a name="eId" id="eId">String Expressions as Identifiers</a></h2> |
+ |
+<p id="eId_1">The ability to build the string used as the property name can be |
+very useful in loops and with dynamically generating web pages (server |
+side) that have variable length content. The strings can be the result |
+of expressions that concatenate string literals with variables |
+(particularly loop counters).</p> |
+ |
+<p id="eId_2">Given the form:-</p> |
+ |
+<pre id="eId_ex1"> |
+<form name="formName" action="#"> |
+ <input type="text" name="field_1"> |
+ <input type="text" name="field_2"> |
+ <input type="text" name="field_3"> |
+</form> |
+</pre> |
+ |
+<p id="eId_3">- the following loop will clear the value property of each element |
+it turn:-</p> |
+ |
+<pre id="eId_ex2"> |
+for(var c = 1;c < 4;c++){ |
+ document.forms["formName"].elements["field_"+c].value = ""; |
+} |
+</pre> |
+ |
+<p id="eId_4">If a server side process had created the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> form with |
+<code>n</code> elements, named <code>field_1, field_2 ... field_n</code> |
+, then all the server side process would have to do to have the loop |
+clear each and every input element would be to change the <code>4</code> |
+in the example to the value of <code>n+1</code>.</p> |
+ |
+<p id="eId_5">Concatenation is the most common type of expression used with the |
+square bracket notation but any javascript expression could be used. |
+A function that returned a string could be used.</p> |
+ |
+<p id="eId_6">In the following (rather contrived) example :-</p> |
+ |
+<pre id="eId_ex3"> |
+function getRootElName(){ |
+ if(document.compatMode && (document.compatMode == "CSS1Compat")){ |
+ return "documentElement"; |
+ }else{ |
+ return "body"; |
+ } |
+} |
+ |
+var verticalScroll = document[getRootElName()].scrollTop; |
+</pre> |
+<p id="eId_7">- the <code>scrollTop</code> value is read from either the |
+<code>document.body</code> or <code>document.documentElement</code> |
+depending on the value of <code>document.compatMode</code>. Passing |
+strings about is far from the best way of achieving what the code |
+above does but there will be circumstances when returning a string |
+from a function call for use in a property accessor is potentially |
+useful.</p> |
+ |
+<h2><a name="aVa" id="aVa">Global Variable access with the Square Bracket Notation</a></h2> |
+ |
+<p id="aVa_1">The square bracket notation requires that there be some sort of |
+object reference to the left of the brackets.</p> |
+ |
+<pre id="aVa_ex1">["document"] <span class="commentJS">//Array literal, not a Property Accessor!</span></pre> |
+ |
+<p id="aVa_2">-will produce an error if an attempt is made to assign a value to it, |
+as it will be treated as an Array literal, if an attempt to read from |
+it is made the one element array containing the string within the |
+brackets is returned. Global variables are normally referenced by their |
+one identifier alone. This would seem to exclude global variables from |
+the possibility of being referenced using a string that held their |
+identifier name or an expression that built, or returned, their name. |
+However, javascript global variables (and global function names for |
+that matter) are properties of a global object. Any identifier that |
+holds a reference to the global object can be used to the left of the |
+square brackets to form a property accessor that refers to a global |
+variable.</p> |
+ |
+<p id="aVa_3">In a web browser the global object is the window (or frame) in which |
+the script is running. Each window (or frame) object contains a number |
+of properties, at least two of which are references to the window |
+(global object) itself. These properties are 'window' and 'self'. |
+These property names can be used as the identifier to the left of the |
+square brackets when referring to global variables. So given a global |
+variable defined as:-</p> |
+ |
+<pre id="aVa_ex2"> |
+var anyName = 0; |
+</pre> |
+ |
+<p id="aVa_4">- that global variable can be referenced as:-</p> |
+ |
+<pre id="aVa_ex3"> |
+window["anyName"] |
+</pre> |
+ |
+<p id="aVa_5">As with any other use of the square bracket notation, the string |
+within the brackets can be held in a variable or constructed/returned |
+by an expression.</p> |
+ |
+<p id="aVa_6">Code that is executing in the global context, the code within global |
+functions (except Object constructors invoked with the <code>new</code> |
+keyword) and inline code outside of any functions, could also use the |
+<code>this</code> keyword to refer to the global object. The |
+<code>this</code> keyword refers to an object depending on the |
+execution context. For code executing in the global context |
+<code>this</code> is the global object (on a web browser, the window |
+object). As a result, the above variable could be referred to as |
+<code>this["anyName"]</code>, but only in code that is |
+executing in the global context.</p> |
+ |
+<p id="aVa_7">However, using the <code>this</code> keyword is very likely to be |
+confusing, especially in scripts that include custom javascript objects |
+where the methods (and constructors) of those objects would be using |
+<code>this</code> to refer to their own object instances.</p> |
+ |
+<p id="aVa_8">Some javascript implementations do not have a property of the global |
+object that refers to the global object. Rather than trying to use the |
+<code>this</code> keyword to access global variables it is possible to |
+create your own global variable that refers to the global object.</p> |
+ |
+<pre id="aVa_ex4"> |
+var myGlobal = this; |
+</pre> |
+ |
+<p id="aVa_9">- executed as inline code at the start of a script will assign a |
+reference to the global object (<code>this</code> in that context). |
+From then on all global variables can be referenced with square bracket |
+notation as:-</p> |
+ |
+<pre id="aVa_ex5"> |
+myGlobal["anyName"]; |
+</pre> |
+ |
+<p id="aVa_10">- and expect <code>myGlobal</code> to refer to the global object |
+from any execution context.</p> |
+ |
+<h2><a name="illc" id="illc">Illegal characters in Identifier-strings</a></h2> |
+ |
+<p id="illc_1">One advantage of the square bracket notation over dot notation is |
+the ability to use characters in identifier-strings that are not legal |
+identifier characters. It is generally best to avoid giving javascript |
+properties names and <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> elements names/IDs that are not made up |
+entirely of characters that are legal in the relevant context. However, |
+it is not always possible to avoid referencing elements with names that |
+include characters that would be illegal in a javascript identifier. |
+PHP offers an example of this, multiple form elements given the same |
+name followed with empty square brackets, such as |
+<code>name="inpEl[]"</code>, are made available on the server |
+as an array.</p> |
+ |
+<p id="illc_2">The square bracket notation would allow an element with such a name |
+to be referenced as <code> document.forms["formName"].elements["inpEl[]"][0]</code> |
+for example (the final <code>[0]</code> reflects the fact that |
+multiple elements with the same name, when accessed by name, generate |
+collections of elements and individual elements within that collection |
+need to be referenced by index).</p> |
+ |
+<p id="illc_3"> |
+<a href="faq_notes.html#toc">comp.lang.javascript FAQ notes T.O.C.</a> |
+</p> |
+ |
+<ul style="list-style-type:none;margin-top:2.5em;"> |
+ <li>Written by <span class="person">Richard Cornford</span>. March 2003.</li> |
+ <li>With technical corrections and suggestions by:-<br> |
+ <ul style="list-style-type:none;"> |
+ <li><span class="person">Yann-Erwan Perio (Yep)</span>. (Also, thanks for testing the use |
+ of <code>this</code> to reference the global object in WSH |
+ and ASP2.) |
+ </li> |
+ <li><span class="person">Lasse Reichstein Nielsen</span>.</li> |
+ <li><span class="person">Dr John Stockton</span>.</li> |
+ </ul> |
+ </li> |
+</ul> |
+</body> |
+</html> |
\ No newline at end of file |
/cljs/faq_notes/square_brackets.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/faq_notes/closures.html |
=================================================================== |
--- cljs/faq_notes/closures.html (nonexistent) |
+++ cljs/faq_notes/closures.html (revision 2) |
@@ -0,0 +1,1574 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" |
+ "http://www.w3.org/TR/html4/strict.dtd"> |
+<html lang="en"> |
+<head> |
+<title>Javascript Closures</title> |
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> |
+<link href="../../faq.css" rel="stylesheet" type="text/css"> |
+<link href="../notes.css" rel="stylesheet" type="text/css"> |
+<style type="text/css"> |
+CODE { white-space:nowrap; } |
+.scopeCh { |
+ white-space:nowrap; |
+ font-family:Courier, monospace; |
+} |
+</style> |
+</head> |
+<body> |
+ |
+<h1>Javascript Closures</h1> |
+<div id="faqNav"> |
+ <a href="../../">FAQ</a> > <a href="../">FAQ Notes</a> |
+</div> |
+ |
+<ul> |
+ <li><a href="#clIntro">Introduction</a></li> |
+ <li><a href="#clResO">The Resolution of Property Names on Objects</a> |
+ <ul> |
+ <li><a href="#clResA">Assignment of Values</a></li> |
+ <li><a href="#clResR">Reading of Values</a></li> |
+ </ul> |
+ </li> |
+ <li><a href="#clIRExSc">Identifier Resolution, Execution Contexts and scope chains</a> |
+ <ul> |
+ <li><a href="#clExCon">The Execution Context</a></li> |
+ <li><a href="#clScCh">scope chains and [[scope]]</a></li> |
+ <li><a href="#clIdRes">Identifier Resolution</a></li> |
+ </ul> |
+ </li> |
+ <li><a href="#clClose">Closures</a> |
+ <ul> |
+ <li><a href="#clAtGb">Automatic Garbage Collection</a></li> |
+ <li><a href="#clFrmC">Forming Closures</a></li> |
+ </ul> |
+ </li> |
+ <li><a href="#clClDo">What can be done with Closures?</a> |
+ <ul> |
+ <li><a href="#clSto">Example 1: setTimeout with Function References</a></li> |
+ <li><a href="#clObjI">Example 2: Associating Functions with Object Instance Methods</a></li> |
+ <li><a href="#clEncap">Example 3: Encapsulating Related Functionality</a></li> |
+ <li><a href="#clOtE">Other Examples</a></li> |
+ </ul> |
+ </li> |
+ <li><a href="#clAc">Accidental Closures</a></li> |
+ <li><a href="#clMem">The Internet Explorer Memory Leak Problem</a></li> |
+</ul> |
+ |
+<h2 id="clIntro">Introduction</h2> |
+ |
+<blockquote cite="http://groups.google.com/groups?selm=wu535hos.fsf@hotpop.com"> |
+ <dl> |
+ <dt id="clDefN">Closure</dt> |
+ <dd>A "closure" is an expression (typically a function) that |
+ can have free variables together with an environment that binds |
+ those variables (that "closes" the expression). |
+ <dd> |
+ </dl> |
+</blockquote> |
+ |
+<p> |
+Closures are one of the most powerful features of ECMAScript |
+(javascript) but they cannot be property exploited without |
+understanding them. They are, however, relatively easy to create, |
+even accidentally, and their creation has potentially harmful |
+consequences, particularly in some relatively common web browser |
+environments. To avoid accidentally encountering the drawbacks and |
+to take advantage of the benefits they offer it is necessary to |
+understand their mechanism. This depends heavily on the role of |
+scope chains in identifier resolution and so on the resolution of |
+property names on objects. |
+</p> |
+ |
+<p> |
+The simple explanation of a Closure is that ECMAScript allows inner |
+functions; function definitions and function expressions that are |
+inside the function bodes of other functions. And that those inner |
+functions are allowed access to all of the local variables, parameters |
+and declared inner functions within their outer function(s). A closure |
+is formed when one of those inner functions is made accessible outside |
+of the function in which it was contained, so that it may be executed |
+after the outer function has returned. At which point it still has |
+access to the local variables, parameters and inner function |
+declarations of its outer function. Those local variables, parameter |
+and function declarations (initially) have the values that they had |
+when the outer function returned and may be interacted with by the |
+inner function. |
+</p> |
+ |
+<p> |
+Unfortunately, properly understanding closures requires an |
+understanding of the mechanism behind them, and quite a bit of |
+technical detail. While some of the ECMA 262 specified algorithms have |
+been brushed over in the early part of the following explanation, much |
+cannot be omitted or easily simplified. Individuals familiar with |
+object property name resolution may skip that section but only people |
+already familiar with closures can afford to skip the following |
+sections, and they can stop reading now and get back to exploiting |
+them. |
+</p> |
+ |
+<h2 id="clResO">The Resolution of Property Names on Objects</h2> |
+ |
+<p> |
+ECMAScript recognises two categories of object, "Native Object" |
+and "Host Object" with a sub-category of native objects called |
+"Built-in Object" (ECMA 262 3rd Ed Section 4.3). Native objects |
+belong to the language and host objects are provided by the environment, |
+and may be, for example, document objects, DOM nodes and the like. |
+</p> |
+ |
+<p> |
+Native objects are loose and dynamic bags of named properties (some |
+implementations are not that dynamic when it comes to the built in |
+object sub-category, though usually that doesn't matter). The defined |
+named properties of an object will hold a value, which may be a |
+reference to another Object (functions are also Objects in this sense) |
+or a primitive value: String, Number, Boolean, Null or Undefined. The |
+Undefined primitive type is a bit odd in that it is possible to assign |
+a value of Undefined to a property of an object but doing so does not |
+remove that property from the object; it remains a defined named |
+property, it just holds the value <code>undefined</code>. |
+</p> |
+ |
+<p> |
+The following is a simplified description of how property values are |
+read and set on objects with the internal details brushed over to the |
+greatest extent possible. |
+</p> |
+ |
+<h3><a name="clResA" id="clResA">Assignment of Values</a></h3> |
+ |
+<p> |
+Named properties of objects can be created, or values set on existing |
+named properties, by assigning a value to that named property. So |
+given:- |
+</p> |
+ |
+<pre> |
+var objectRef = new Object(); <span class="commentJS">//create a generic javascript object.</span> |
+</pre> |
+ |
+<p> |
+A property with the name "testNumber" can be created as:- |
+</p> |
+ |
+<pre> |
+objectRef.testNumber = 5; |
+<span class="commentJS">/* - or:- */</span> |
+objectRef["testNumber"] = 5; |
+</pre> |
+ |
+<p> |
+The object had no "testNumber" property prior to the |
+assignment but one is created when the assignment is made. Any |
+subsequent assignment does not need to create the property, it just |
+re-sets its value:- |
+</p> |
+ |
+<pre> |
+objectRef.testNumber = 8; |
+<span class="commentJS">/* - or:- */</span> |
+objectRef["testNumber"] = 8; |
+</pre> |
+ |
+<p> |
+Javascript objects have prototypes that can themselves be objects, as |
+will be described shortly, and that prototype may have named |
+properties. But this has no role in assignment. If a value is assigned |
+and the actual object does not have a property with the corresponding |
+name a property of that name is created and the value is assigned to |
+it. If it has the property then its value is re-set. |
+</p> |
+ |
+<h3><a name="clResR" id="clResR">Reading of Values</a></h3> |
+ |
+<p> |
+It is in reading values from object properties that prototypes come |
+into play. If an object has a property with the property name used in |
+the property accessor then the value of that property is returned:- |
+</p> |
+ |
+<pre> |
+<span class="commentJS">/* Assign a value to a named property. If the object does not have a |
+ property with the corresponding name prior to the assignment it |
+ will have one after it:- |
+*/</span> |
+objectRef.testNumber = 8; |
+ |
+<span class="commentJS">/* Read the value back from the property:- */</span> |
+ |
+var val = objectRef.testNumber; |
+<span class="commentJS">/* and - val - now holds the value 8 that was just assigned to the |
+ named property of the object. */</span> |
+ </pre> |
+ |
+<p> |
+But all objects may have prototypes, and prototypes are objects so they, in |
+turn, may have prototypes, which may have prototypes, and so on forming |
+what is called the prototype chain. The prototype chain ends when one |
+of the objects in the chain has a null prototype. The default prototype for the |
+<code>Object</code> constructor has a null prototype so:- |
+</p> |
+ |
+<pre> |
+var objectRef = new Object(); <span class="commentJS">//create a generic javascript object.</span> |
+</pre> |
+ |
+<p> |
+Creates an object with the prototype <code>Object.prototype</code> that itself has a |
+null prototype. So the prototype chain for <code>objectRef</code> contains only one |
+object: <code>Object.prototype</code>. However:- |
+</p> |
+ |
+<pre> |
+<span class="commentJS">/* A "constructor" function for creating objects of a - |
+ MyObject1 - type. |
+*/</span> |
+function MyObject1(formalParameter){ |
+ <span class="commentJS">/* Give the constructed object a property called - testNumber - and |
+ assign it the value passed to the constructor as its first |
+ argument:- |
+ */</span> |
+ this.testNumber = formalParameter; |
+} |
+ |
+<span class="commentJS">/* A "constructor" function for creating objects of a - |
+ MyObject2 - type:- |
+*/</span> |
+function MyObject2(formalParameter){ |
+ <span class="commentJS">/* Give the constructed object a property called - testString - |
+ and assign it the value passed to the constructor as its first |
+ argument:- |
+ */</span> |
+ this.testString = formalParameter; |
+} |
+ |
+<span class="commentJS">/* The next operation replaces the default prototype associated with |
+ all MyObject2 instances with an instance of MyObject1, passing the |
+ argument - 8 - to the MyObject1 constructor so that its - |
+ testNumber - property will be set to that value:- |
+*/</span> |
+MyObject2.prototype = new MyObject1( 8 ); |
+ |
+<span class="commentJS">/* Finally, create an instance of - MyObject2 - and assign a reference |
+ to that object to the variable - objectRef - passing a string as the |
+ first argument for the constructor:- |
+*/</span> |
+ |
+var objectRef = new MyObject2( "String_Value" ); |
+</pre> |
+ |
+<p> |
+The instance of <code>MyObject2</code> referred to by the <code>objectRef</code> variable has a |
+prototype chain. The first object in that chain is the instance of |
+<code>MyObject1</code> that was created and assigned to the prototype |
+property of the <code>MyObject2</code> constructor. The instance of |
+<code>MyObject1</code> has a prototype, the object that was assigned to the function |
+<code>MyObject1</code>'s prototype property by the implementation. That object has |
+a prototype, the default <code>Object</code> prototype that corresponds with the |
+object referred to by <code>Object.prototype</code>. <code>Object.prototype</code> has a null |
+prototype so the prototype chain comes to an end at this point. |
+</p> |
+<p> |
+When a property accessor attempts to read a named property form the |
+object referred to by the variable <code>objectRef</code> the whole |
+prototype chain can enter into the process. In the simple case:- |
+</p> |
+ |
+<pre> |
+var val = objectRef.testString; |
+</pre> |
+ |
+<p> |
+- the instance of <code>MyObject2</code> referred to by <code>objectRef</code> has |
+a property with the name "testString" so it is the value of |
+that property, set to "String_Value", that is assigned to the |
+variable <code>val</code>. However:- |
+</p> |
+ |
+<pre> |
+var val = objectRef.testNumber; |
+</pre> |
+ |
+<p> |
+- cannot read a named property form the instance of |
+<code>MyObject2</code> itself as it has no such property but the |
+variable <code>val</code> is set to the value of <code>8</code> rather |
+than undefined because having failed to find a corresponding named |
+property on the object itself the interpreter then examines the object |
+that is its prototype. Its prototype is the instance of |
+<code>MyObject1</code> and it was created with a property named |
+"testNumber" with the value <code>8</code> assigned to that property, so |
+the property accessor evaluates as the value <code>8</code>. Neither |
+<code>MyObject1</code> or <code>MyObject2</code> have defined a |
+<code>toString</code> method, but if a property accessor attempts to |
+read the value of a <code>toString</code> property from |
+<code>objectRef</code>:- |
+</p> |
+ |
+<pre> |
+var val = objectRef.toString; |
+</pre> |
+ |
+<p> |
+- the <code>val</code> variable is assigned a reference to a function. |
+That function is the <code>toString</code> property of |
+<code>Object.prototype</code> and is returned because the process of |
+examining the prototype of <code>objectRef</code>, when |
+<code>objectRef</code> turns out not to have a "toString" |
+property, is acting on an object, so when that prototype is found to |
+lack the property its prototype is examined in turn. Its prototype |
+is <code>Object.prototype</code>, which does have a |
+<code>toString</code> method so it is a reference to that function |
+object that is returned. |
+</p> |
+ |
+<p> |
+Finally:- |
+</p> |
+ |
+<pre> |
+var val = objectRef.madeUpProperty; |
+</pre> |
+ |
+<p> |
+- returns <code>undefined</code>, because as the process of working up the prototype |
+chain finds no properties on any of the object with the name |
+"madeUpPeoperty" it eventually gets to the prototype of |
+<code>Object.prototype</code>, which is null, and the process ends |
+returning <code>undefined</code>. |
+</p> |
+ |
+<p> |
+The reading of named properties returns the first value found, on the |
+object or then from its prototype chain. The assigning of a value to a |
+named property on an object will create a property on the object itself |
+if no corresponding property already exists. |
+</p> |
+ |
+<p> |
+This means that if a value was assigned as |
+<code>objectRef.testNumber = 3</code> a "testNumber" property |
+will be created on the instance of <code>MyObject2</code> itself, and |
+any subsequent attempts to read that value will retrieve that value as |
+set on the object. The prototype chain no longer needs to be examined |
+to resolve the property accessor, but the instance of |
+<code>MyObject1</code> with the value of <code>8</code> assigned to its |
+"testNumber" property is unaltered. The assignment to the |
+<code>objectRef</code> object masks the corresponding property in its |
+prototype chain. |
+</p> |
+ |
+<p> |
+Note: ECMAScript defines an internal <code>[[prototype]]</code> |
+property of the internal Object type. This property is not directly accessible with |
+scripts, but it is the chain of objects referred to with the |
+internal <code>[[prototype]]</code> property that is used in property |
+accessor resolution; the object's prototype chain. A public |
+<code>prototype</code> property exists to allow the assignment, |
+definition and manipulation of prototypes in association with the |
+internal <code>[[prototype]]</code> property. The details of the |
+relationship between to two are described in ECMA 262 (3rd edition) |
+and are beyond the <dfn>scope</dfn> of this discussion. |
+</p> |
+ |
+<h2 id="clIRExSc">Identifier Resolution, Execution Contexts and scope chains</h2> |
+ |
+<h3 id="clExCon">The Execution Context</h3> |
+ |
+<p> |
+An <dfn>execution context</dfn> is an abstract concept used by the ECMSScript |
+specification (ECMA 262 3rd edition) to define the behaviour required |
+of ECMAScript implementations. The specification does not say anything |
+about how <dfn>execution contexts</dfn> should be implemented but execution |
+contexts have associated attributes that refer to specification defined |
+structures so they might be conceived (and even implemented) as objects |
+with properties, though not public properties. |
+</p> |
+ |
+<p> |
+All javascript code is executed in an <dfn>execution context</dfn>. Global code |
+(code executed inline, normally as a JS file, or <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> page, loads) gets |
+executed in <dfn>global</dfn> <dfn>execution context</dfn>, and each invocation of a function (possibly as a constructor) has an associated |
+<dfn>execution context</dfn>. Code executed with the <code>eval</code> function |
+also gets a distinct execution context but as <code>eval</code> is |
+never normally used by javascript programmers it will not be discussed |
+here. The specified details of <dfn>execution contexts</dfn> are to be found in |
+section 10.2 of ECMA 262 (3rd edition). |
+</p> |
+ |
+<p> |
+When a javascript function is called it enters an <dfn>execution context</dfn>, |
+if another function is called (or the same function recursively) a new |
+<dfn>execution context</dfn> is created and execution enters that context for the |
+duration of the function call. Returning to the original execution |
+context when that called function returns. Thus running javascript code |
+forms a stack of <dfn>execution contexts</dfn>. |
+</p> |
+ |
+<p> |
+When an <dfn>execution context</dfn> is created a number of things happen in a |
+defined order. First, in the <dfn>execution context</dfn> of a function, an |
+"Activation" object is created. The activation object is |
+another specification mechanism. It can be considered as an object |
+because it ends up having accessible named properties, but it is not a |
+normal object as it has no prototype (at least not a defined prototype) |
+and it cannot be directly referenced by javascript code. |
+</p> |
+ |
+<p> |
+The next step in the creation of the <dfn>execution context</dfn> for a function |
+call is the creation of an <code>arguments</code> object, which is an |
+array-like object with integer indexed members corresponding with the |
+arguments passed to the function call, in order. It also has |
+<code>length</code> and <code>callee</code> properties (which are not |
+relevant to this discussion, see the spec for details). A property of |
+the Activation object is created with the name "arguments" |
+and a reference to the <code>arguments</code> object is assigned to |
+that property. |
+</p> |
+ |
+<p> |
+Next the <dfn>execution context</dfn> is assigned a <dfn>scope</dfn>. A <dfn>scope</dfn> consists of a |
+list (or chain) of objects. Each function object has an internal |
+<code>[[scope]]</code> property (which we will go into more detail |
+about shortly) that also consists of a list (or chain) of objects. |
+The <dfn>scope</dfn> that is assigned to the <dfn>execution context</dfn> of a function call |
+consists of the list referred to by the <code>[[scope]]</code> property |
+of the corresponding function object with the Activation object added |
+at the front of the chain (or the top of the list). |
+</p> |
+ |
+<p> |
+Then the process of "variable instantiation" takes place using an object |
+that ECMA 262 refers to as the "Variable" object. However, |
+the Activation object is used as the Variable object (note this, it is |
+important: they are the same object). Named properties of the Variable |
+object are created for each of the function's formal parameters, and if |
+arguments to the function call correspond with those parameters the |
+values of those arguments are assigned to the properties (otherwise the |
+assigned value is <code>undefined</code>). Inner function definitions |
+are used to create function objects which are assigned to properties of |
+the Variable object with names that correspond to the function name |
+used in the function declaration. The last stage of variable |
+instantiation is to create named properties of the Variable object |
+that correspond with all the local variables declared within the |
+function. |
+</p> |
+ |
+<p> |
+The properties created on the Variable object that correspond with |
+declared local variables are initially assigned <code>undefined</code> |
+values during variable instantiation, the actual initialisation of |
+local variables does not happen until the evaluation of the |
+corresponding assignment expressions during the execution of the |
+function body code. |
+</p> |
+ |
+<p> |
+It is the fact that the Activation object, with its |
+<code>arguments</code> property, and the Variable object, with named |
+properties corresponding with function local variables, are the same |
+object, that allows the identifier <code>arguments</code> to be treated |
+as if it was a function local variable. |
+</p> |
+ |
+<p> |
+Finally a value is assigned for use with the <code>this</code> keyword. |
+If the value assigned refers to an object then property accessors |
+prefixed with the <code>this</code> keyword reference properties of |
+that object. If the value assigned (internally) is null then the |
+<code>this</code> keyword will refer to the global object. |
+</p> |
+ |
+<p> |
+The global execution context gets some slightly different handling as |
+it does not have arguments so it does not need a defined Activation |
+object to refer to them. The global execution context does need a <dfn>scope</dfn> |
+and its <dfn>scope chain</dfn> consists of exactly one object, the global object. |
+The global execution context does go through variable instantiation, |
+its inner functions are the normal top level function declarations that |
+make up the bulk of javascript code. The global object is used as the |
+Variable object, which is why globally declared functions become |
+properties of the global object. As do globally declared variables. |
+</p> |
+ |
+<p> |
+The global execution context also uses a reference to the global object |
+for the <code>this</code> object. |
+</p> |
+ |
+<h3 id="clScCh">scope chains and [[scope]]</h3> |
+ |
+<p> |
+The <dfn>scope chain</dfn> of the execution context for a function call is |
+constructed by adding the execution context's Activation/Variable |
+object to the front of the <dfn>scope chain</dfn> held in the function |
+object's <code>[[scope]]</code> property, so it is important to |
+understand how the internal <code>[[scope]]</code> property is |
+defined. |
+</p> |
+ |
+<p> |
+In ECMAScript functions are objects, they are created during variable |
+instantiation from function declarations, during the evaluation of |
+function expressions or by invoking the <code>Function</code> |
+constructor. |
+</p> |
+ |
+<p> |
+Function objects created with the <code>Function</code> constructor |
+always have a <code>[[scope]]</code> property referring to a <dfn>scope |
+chain</dfn> that only contains the global object. |
+</p> |
+ |
+<p> |
+Function objects created with function declarations or function |
+expressions have the <dfn>scope chain</dfn> of the execution context in which |
+they are created assigned to their internal <code>[[scope]]</code> |
+property. |
+</p> |
+ |
+<p> |
+In the simplest case of a global function declaration such as:- |
+</p> |
+ |
+<pre> |
+function exampleFunction(formalParameter){ |
+ ... <span class="commentJS">// function body code</span> |
+} |
+</pre> |
+ |
+<p> |
+- the corresponding function object is created during the variable |
+instantiation for the global execution context. The global execution |
+context has a <dfn>scope chain</dfn> consisting of only the global object. Thus |
+the function object that is created and referred to by the property of |
+the global object with the name "exampleFunction" is |
+assigned an internal <code>[[scope]]</code> property referring to a |
+<dfn>scope chain</dfn> containing only the global object. |
+</p> |
+ |
+<p> |
+A similar <dfn>scope chain</dfn> is assigned when a function expression is |
+executed in the global context:- |
+</p> |
+ |
+<pre> |
+var exampleFuncRef = function(){ |
+ ... <span class="commentJS">// function body code</span> |
+} |
+</pre> |
+ |
+<p> |
+- except in this case a named property of the global object is created |
+during variable instantiation for the global execution context but the |
+function object is not created, and a reference to it assigned to the |
+named property of the global object, until the assignment expression is |
+evaluated. But the creation of the function object still happens in the |
+global execution context so the <code>[[scope]]</code> property of the |
+created function object still only contains the global object in the |
+assigned scope chain. |
+</p> |
+ |
+<p> |
+Inner function declarations and expressions result in function objects |
+being created within the execution context of a function so they get |
+more elaborate scope chains. Consider the following code, which defines |
+a function with an inner function declaration and then executes the |
+outer function:- |
+</p> |
+ |
+<pre> |
+function exampleOuterFunction(formalParameter){ |
+ function exampleInnerFuncitonDec(){ |
+ ... <span class="commentJS">// inner function body</span> |
+ } |
+ ... <span class="commentJS">// the rest of the outer function body.</span> |
+} |
+ |
+exampleOuterFunction( 5 ); |
+</pre> |
+ |
+<p> |
+The function object corresponding with the outer function declaration |
+is created during variable instantiation in the global execution context |
+so its <code>[[scope]]</code> property contains the one item scope |
+chain with only the global object in it. |
+</p> |
+ |
+<p> |
+When the global code executes the call to the |
+<code>exampleOuterFunction</code> a new execution context is created for |
+that function call and an Activation/Variable object along with it. |
+The <dfn>scope</dfn> of that new execution context becomes the chain consisting of |
+the new Activation object followed by the chain refereed to by the |
+outer function object's <code>[[scope]]</code> property (just the |
+global object). Variable instantiation for that new execution context |
+results in the creation of a function object that corresponds with the |
+inner function definition and the <code>[[scope]]</code> property of |
+that function object is assigned the value of the <dfn>scope</dfn> from the |
+execution context in which it was created. A <dfn>scope chain</dfn> that contains |
+the Activation object followed by the global object. |
+</p> |
+ |
+<p> |
+So far this is all automatic and controlled by the structure and |
+execution of the source code. The <dfn>scope chain</dfn> of the execution context |
+defines the <code>[[scope]]</code> properties of the function objects |
+created and the <code>[[scope]]</code> properties of the function |
+objects define the <dfn>scope</dfn> for their execution contexts (along with the |
+corresponding Activation object). But ECMAScript provides the |
+<code>with</code> statement as a means of modifying the scope chain. |
+</p> |
+ |
+<p> |
+The <code>with</code> statement evaluates an expression and if that |
+expression is an object it is added to the <dfn>scope chain</dfn> of the current |
+execution context (in front of the Activation/Variable object). The |
+<code>with</code> statement then executes another statement (that may |
+itself be a block statement) and then restores the execution context's |
+<dfn>scope chain</dfn>to what it was before. |
+</p> |
+ |
+<p> |
+A function declaration could not be affected by a <code>with</code> |
+statement as they result in the creation of function objects during |
+variable instantiation, but a function expression can be evaluated |
+inside a <code>with</code> statement:- |
+</p> |
+ |
+<pre> |
+<span class="commentJS">/* create a global variable - y - that refers to an object:- */</span> |
+var y = {x:5}; <span class="commentJS">// object literal with an - x - property</span> |
+function exampleFuncWith(){ |
+ var z; |
+ <span class="commentJS">/* Add the object referred to by the global variable - y - to the |
+ front of he scope chain:- |
+ */</span> |
+ with(y){ |
+ <span class="commentJS">/* evaluate a function expression to create a function object |
+ and assign a reference to that function object to the local |
+ variable - z - :- |
+ */</span> |
+ z = function(){ |
+ ... <span class="commentJS">// inner function expression body;</span> |
+ } |
+ } |
+ ... |
+} |
+ |
+<span class="commentJS">/* execute the - exampleFuncWith - function:- */</span> |
+exampleFuncWith(); |
+</pre> |
+ |
+<p> |
+When the <code>exampleFuncWith</code> function is called the resulting |
+execution context has a <dfn>scope chain</dfn> consisting of its Activation object |
+followed by the global object. The execution of the <code>with</code> |
+statement adds the object referred to by the global variable |
+<code>y</code> to the front of that <dfn>scope chain</dfn> during the evaluation |
+of the function expression. The function object created by the |
+evaluation of the function expression is assigned a |
+<code>[[scope]]</code> property that corresponds with the <dfn>scope</dfn> of the |
+execution context in which it is created. A <dfn>scope chain</dfn> consisting of |
+object <code>y</code> followed by the Activation object from the |
+execution context of the outer function call, followed by the global |
+object. |
+</p> |
+ |
+<p> |
+When the block statement associated with the <code>with</code> |
+statement terminates the <dfn>scope</dfn> of the execution context is restored |
+(the <code>y</code> object is removed), but the function object has |
+been created at that point and its <code>[[scope]]</code> property |
+assigned a reference to a <dfn>scope chain</dfn> with the <code>y</code> object |
+at its head. |
+</p> |
+ |
+<h3><a name="clIdRes" id="clIdRes">Identifier Resolution</a></h3> |
+ |
+<p> |
+Identifiers are resolved against the scope chain. ECMA 262 categorises |
+<code>this</code> as a keyword rather than an identifier, which is not |
+unreasonable as it is always resolved dependent on the |
+<code>this</code> value in the execution context in which it is used, |
+without reference to the scope chain. |
+</p> |
+ |
+<p> |
+Identifier resolution starts with the first object in the scope chain. |
+It is checked to see if it has a property with a name that corresponds |
+with the identifier. Because the <dfn>scope chain</dfn> is a chain of objects |
+this checking encompasses the prototype chain of that object (if it |
+has one). If no corresponding value can be found on the first object |
+in the <dfn>scope chain</dfn> the search progresses to the next object. And so on until |
+one of the objects in the chain (or one of its prototypes) has a |
+property with a name that corresponds with the identifier or the scope |
+chain is exhausted. |
+</p> |
+ |
+<p> |
+The operation on the identifier happens in the same way as the use of |
+property accessors on objects described above. The object identified |
+in the <dfn>scope chain</dfn> as having the corresponding property takes the |
+place of the object in the property accessor and the identifier acts |
+as a property name for that object. The global object is always at the |
+end of the scope chain. |
+</p> |
+ |
+<p> |
+As execution contexts associated with function calls will have the |
+Activation/Variable object at the front of the chain, identifiers used |
+in function bodies are effectively first checked to see whether they |
+correspond with formal parameters, inner function declaration names or |
+local variables. Those would be resolved as named properties of the |
+Activation/Variable object. |
+</p> |
+ |
+<h2><a name="clClose" id="clClose">Closures</a></h2> |
+ |
+<h3><a name="clAtGb" id="clAtGb">Automatic Garbage Collection</a></h3> |
+ |
+<p> |
+ECMAScript uses automatic garbage collection. The specification |
+does not define the details, leaving that to the implementers to sort |
+out, and some implementations are known to give a very low priority to |
+their garbage collection operations. But the general idea is that if an |
+object becomes un-referable (by having no remaining references to it |
+left accessible to executing code) it becomes available for garbage |
+collection and will at some future point be destroyed and any resources |
+it is consuming freed and returned to the system for re-use. |
+</p> |
+ |
+<p> |
+This would normally be the case upon exiting an execution context. The |
+<dfn>scope chain</dfn> structure, the Activation/Variable object and any objects |
+created within the execution context, including function objects, would |
+no longer be accessible and so would become available for garbage |
+collection. |
+</p> |
+ |
+<h3><a name="clFrmC" id="clFrmC">Forming Closures</a></h3> |
+ |
+<p> |
+A closure is formed by returning a function object that was created |
+within an execution context of a function call from that function call |
+and assigning a reference to that inner function to a property of another |
+object. Or by directly assigning a reference to such a function object |
+to, for example, a global variable, a property of a globally accessible |
+object or an object passed by reference as an argument to the outer |
+function call. e.g:- |
+</p> |
+ |
+<pre> |
+function exampleClosureForm(arg1, arg2){ |
+ var localVar = 8; |
+ function exampleReturned(innerArg){ |
+ return ((arg1 + arg2)/(innerArg + localVar)); |
+ } |
+ <span class="commentJS">/* return a reference to the inner function defined as - |
+ exampleReturned -:- |
+ */</span> |
+ return exampleReturned; |
+} |
+ |
+var globalVar = exampleClosureForm(2, 4); |
+</pre> |
+ |
+<p> |
+Now the function object created within the execution context of the |
+call to <code>exampleClosureForm</code> cannot be garbage collected |
+because it is referred to by a global variable and is still accessible, |
+it can even be executed with <code>globalVar(n)</code>. |
+</p> |
+ |
+<p> |
+But something a little more complicated has happened because the |
+function object now referred to by <code>globalVar</code> was created |
+with a <code>[[scope]]</code> property referring to a scope chain |
+containing the Activation/Variable object belonging to the execution |
+context in which it was created (and the global object). Now the |
+Activation/Variable object cannot be garbage collected either as the |
+execution of the function object referred to by <code>globalVar</code> |
+will need to add the whole <dfn>scope chain</dfn> from its <code>[[scope]]</code> |
+property to the <dfn>scope</dfn> of the execution context created for each call to |
+it. |
+</p> |
+ |
+<p> |
+A closure is formed. The inner function object has the free variables |
+and the Activation/Variable object on the function's <dfn>scope chain</dfn> is |
+the environment that binds them. |
+</p> |
+ |
+<p> |
+The Activation/Variable object is trapped by being |
+referred to in the <dfn>scope chain</dfn> assigned to the internal |
+<code>[[scope]]</code> property of the function object now referred to |
+by the <code>globalVar</code> variable. The Activation/Variable object |
+is preserved along with its state; the values of its properties. Scope |
+resolution in the execution context of calls to the inner function will |
+resolve identifiers that correspond with named properties of that |
+Activation/Variable object as properties of that object. The value of |
+those properties can still be read and set even though the execution |
+context for which it was created has exited. |
+</p> |
+ |
+<p> |
+In the example above that Activation/Variable object has a state that |
+represents the values of formal parameters, inner function definitions |
+and local variables, at the time when the outer function returned |
+(exited its execution context). The <code>arg1</code> property has the |
+value <code>2</code>,the <code>arg2</code> property the value |
+<code>4</code>, <code>localVar</code> the value <code>8</code> and an |
+<code>exampleReturned</code> property that is a reference to the inner |
+function object that was returned form the outer function. (We will be |
+referring to this Activation/Variable object as "ActOuter1" in later |
+discussion, for convenience.) |
+</p> |
+ |
+<p> |
+If the <code>exampleClosureForm</code> function was called again as:- |
+</p> |
+ |
+<pre> |
+var secondGlobalVar = exampleClosureForm(12, 3); |
+</pre> |
+ |
+<p> |
+- a new execution context would be created, along with a new Activation |
+object. And a new function object would be returned, with its own |
+distinct <code>[[scope]]</code> property referring to a scope chain |
+containing the Activation object form this second execution context, |
+with <code>arg1</code> being <code>12</code> and <code>arg2</code> |
+being <code>3</code>. (We will be referring to this Activation/Variable |
+object as "ActOuter2" in later discussion, for convenience.) |
+</p> |
+ |
+<p> |
+A second and distinct closure has been formed by the second execution |
+of <code>exampleClosureForm</code>. |
+</p> |
+ |
+<p> |
+The two function objects created by the execution of |
+<code>exampleClosureForm</code> to which references have been assigned |
+to the global variable <code>globalVar</code> and |
+<code>secondGlobalVar</code> respectively, return the expression |
+<code>((arg1 + arg2)/(innerArg + localVar))</code>. Which applies |
+various operators to four identifiers. How these identifiers are |
+resolved is critical to the use and value of closures. |
+</p> |
+ |
+<p> |
+Consider the execution of the function object referred to by |
+<code>globalVar</code>, as <code>globalVar(2)</code>. A new execution |
+context is created and an Activation object (we will call it |
+"ActInner1"), which is added to the head of the scope chain |
+referred to the <code>[[scope]]</code> property of the executed |
+function object. ActInner1 is given a property named |
+<code>innerArg</code>, after its formal parameter and the argument |
+value <code>2</code> assigned to it. The <dfn>scope chain</dfn> for this new |
+execution context is: <span class="scopeCh">ActInner1-></span> |
+<span class="scopeCh">ActOuter1-></span> |
+<span class="scopeCh">global object</span>. |
+</p> |
+ |
+<p> |
+Identifier resolution is done against the <dfn>scope chain</dfn> so in order |
+to return the value of the expression |
+<code>((arg1 + arg2)/(innerArg + localVar))</code> the values of the |
+identifiers will be determined by looking for properties, with names |
+corresponding with the identifiers, on each object in the scope chain |
+in turn. |
+</p> |
+ |
+<p> |
+The first object in the chain is ActInner1 and it has a property named |
+<code>innerArg</code> with the value <code>2</code>. All of the other |
+3 identifiers correspond with named properties of ActOuter1; |
+<code>arg1</code> is <code>2</code>, <code>arg2</code> is |
+<code>4</code> and <code>localVar</code> is <code>8</code>. The |
+function call returns <code>((2 + 4)/(2 + 8))</code>. |
+</p> |
+ |
+<p> |
+Compare that with the execution of the otherwise identical function |
+object referred to by <code>secondGlobalVar</code>, as |
+<code>secondGlobalVar(5)</code>. Calling the Activation object for |
+this new execution context "ActInner2", the scope chain |
+becomes: <span class="scopeCh">ActInner2-></span> |
+<span class="scopeCh">ActOuter2-></span> |
+<span class="scopeCh">global object</span>. ActInner2 returns |
+<code>innerArg</code> as <code>5</code> and ActOuter2 returns |
+<code>arg1</code>, <code>arg2</code> and <code>localVar</code> as |
+<code>12</code>, <code>3</code> and <code>8</code> respectively. The |
+value returned is <code>((12 + 3)/(5 + 8))</code>. |
+</p> |
+ |
+<p> |
+Execute <code>secondGlobalVar</code> again and a new Activation object |
+will appear at the front of the <dfn>scope chain</dfn> but ActOuter2 will still |
+be next object in the chain and the value of its named properties will |
+again be used in the resolution of the identifiers <code>arg1</code>, |
+<code>arg2</code> and <code>localVar</code>. |
+</p> |
+ |
+<p> |
+This is how ECMAScript inner functions gain, and maintain, access to the formal |
+parameters, declared inner functions and local variables of the |
+execution context in which they were created. And it is how the |
+forming of a closure allows such a function object to keep referring |
+to those values, reading and writing to them, for as long as it |
+continues to exist. The Activation/Variable object from the execution |
+context in which the inner function was created remains on the scope |
+chain referred to by the function object's <code>[[scope]]</code> |
+property, until all references to the inner function are freed and |
+the function object is made available for garbage collection (along |
+with any now unneeded objects on its scope chain). |
+</p> |
+ |
+<p> |
+Inner function may themselves have inner functions, and the inner |
+functions returned from the execution of functions to form closures |
+may themselves return inner functions and form closures of their own. |
+With each nesting the <dfn>scope chain</dfn> gains extra Activation objects |
+originating with the execution contexts in which the inner function |
+objects were created. The ECMAScript specification requires a scope |
+chain to be finite, but imposes no limits on their length. |
+Implementations probably do impose some practical limitation but no |
+specific magnitude has yet been reported. The potential for nesting |
+inner functions seems so far to have exceeded anyone's desire to |
+code them. |
+</p> |
+ |
+<h2><a name="clClDo" id="clClDo">What can be done with Closures?</a></h2> |
+ |
+<p> |
+Strangely the answer to that appears to be anything and everything. |
+I am told that closures enable ECMAScript to emulate anything, so the |
+limitation is the ability to conceive and implement the emulation. That |
+is a bit esoteric and it is probably better to start with something a |
+little more practical. |
+</p> |
+ |
+ |
+<h3><a name="clSto" id="clSto">Example 1: setTimeout with Function References</a></h3> |
+ |
+ |
+<p> |
+A common use for a closure is to provide parameters for the execution |
+of a function prior to the execution of that function. For example, |
+when a function is to be provided as the first argument to the |
+<code>setTimout</code> function that is common in web browser |
+environments. |
+</p> |
+ |
+<p> |
+<code>setTimeout</code> schedules the execution of a function (or a |
+string of javascript source code, but not in this context), provided as |
+its first argument, after an interval expressed in milliseconds (as its |
+second argument). If a piece of code wants to use |
+<code>setTimeout</code> it calls the <code>setTimeout</code> function |
+and passes a reference to a function object as the first argument and |
+the millisecond interval as the second, but a reference to a function |
+object cannot provide parameters for the scheduled execution of that |
+function. |
+</p> |
+ |
+<p> |
+However, code could call another function that returned a reference to |
+an inner function object, with that inner function object being passed |
+by reference to the <code>setTimeout</code> function. The parameters to |
+be used for the execution of the inner function are passed with the |
+call to the function that returns it. <code>setTimout</code> executes |
+the inner function without passing arguments but that inner function |
+can still access the parameters provided by the call to the outer |
+function that returned it:- |
+</p> |
+ |
+<pre> |
+function callLater(paramA, paramB, paramC){ |
+ <span class="commentJS">/* Return a reference to an anonymous inner function created |
+ with a function expression:- |
+ */</span> |
+ return (function(){ |
+ <span class="commentJS">/* This inner function is to be executed with - setTimeout |
+ - and when it is executed it can read, and act upon, the |
+ parameters passed to the outer function:- |
+ */</span> |
+ paramA[paramB] = paramC; |
+ }); |
+} |
+ |
+... |
+ |
+<span class="commentJS">/* Call the function that will return a reference to the inner function |
+ object created in its execution context. Passing the parameters that |
+ the inner function will use when it is eventually executed as |
+ arguments to the outer function. The returned reference to the inner |
+ function object is assigned to a local variable:- |
+*/</span> |
+var functRef = callLater(elStyle, "display", "none"); |
+<span class="commentJS">/* Call the setTimeout function, passing the reference to the inner |
+ function assigned to the - functRef - variable as the first argument:- |
+*/</span> |
+hideMenu=setTimeout(functRef, 500); |
+</pre> |
+ |
+<h3><a name="clObjI" id="clObjI">Example 2: Associating Functions with Object Instance Methods</a></h3> |
+ |
+<p> |
+There are many other circumstances when a reference to a function |
+object is assigned so that it would be executed at some future time |
+where it is useful to provide parameters for the execution of that |
+function that would not be easily available at the time of execution |
+but cannot be known until the moment of assignment. |
+</p> |
+ |
+<p> |
+One example might be a javascript object that is designed to |
+encapsulate the interactions with a particular DOM element. It has |
+<code>doOnClick</code>, <code>doMouseOver</code> and |
+<code>doMouseOut</code> methods and wants to execute those methods |
+when the corresponding events are triggered on the DOM element, but |
+there may be any number of instances of the javascript object created |
+associated with different DOM elements and the individual object |
+instances do not know how they will be employed by the code that |
+instantiated them. The object instances do not know how to reference |
+themselves globally because they do not know which global variables |
+(if any) will be assigned references to their instances. |
+</p> |
+ |
+<p> |
+So the problem is to execute an event handling function that has an |
+association with a particular instance of the javascript object, and |
+knows which method of that object to call. |
+</p> |
+ |
+<p> |
+The following example uses a small generalised closure based function |
+that associates object instances with element event handlers. |
+Arranging that the execution of the event handler calls the specified |
+method of the object instance, passing the event object and a reference |
+to the associated element on to the object method and returning the |
+method's return value. |
+</p> |
+ |
+<pre> |
+<span class="commentJS">/* A general function that associates an object instance with an event |
+ handler. The returned inner function is used as the event handler. |
+ The object instance is passed as the - obj - parameter and the name |
+ of the method that is to be called on that object is passed as the - |
+ methodName - (string) parameter. |
+*/</span> |
+function associateObjWithEvent(obj, methodName){ |
+ <span class="commentJS">/* The returned inner function is intended to act as an event |
+ handler for a DOM element:- |
+ */</span> |
+ return (function(e){ |
+ <span class="commentJS">/* The event object that will have been parsed as the - e - |
+ parameter on DOM standard browsers is normalised to the IE |
+ event object if it has not been passed as an argument to the |
+ event handling inner function:- |
+ */</span> |
+ e = e||window.event; |
+ <span class="commentJS">/* The event handler calls a method of the object - obj - with |
+ the name held in the string - methodName - passing the now |
+ normalised event object and a reference to the element to |
+ which the event handler has been assigned using the - this - |
+ (which works because the inner function is executed as a |
+ method of that element because it has been assigned as an |
+ event handler):- |
+ */</span> |
+ return obj[methodName](e, this); |
+ }); |
+} |
+ |
+<span class="commentJS">/* This constructor function creates objects that associates themselves |
+ with DOM elements whose IDs are passed to the constructor as a |
+ string. The object instances want to arrange than when the |
+ corresponding element triggers onclick, onmouseover and onmouseout |
+ events corresponding methods are called on their object instance. |
+*/</span> |
+function DhtmlObject(elementId){ |
+ <span class="commentJS">/* A function is called that retrieves a reference to the DOM |
+ element (or null if it cannot be found) with the ID of the |
+ required element passed as its argument. The returned value |
+ is assigned to the local variable - el -:- |
+ */</span> |
+ var el = getElementWithId(elementId); |
+ <span class="commentJS">/* The value of - el - is internally type-converted to boolean for |
+ the - if - statement so that if it refers to an object the |
+ result will be true, and if it is null the result false. So that |
+ the following block is only executed if the - el - variable |
+ refers to a DOM element:- |
+ */</span> |
+ if(el){ |
+ <span class="commentJS">/* To assign a function as the element's event handler this |
+ object calls the - associateObjWithEvent - function |
+ specifying itself (with the - this - keyword) as the object |
+ on which a method is to be called and providing the name of |
+ the method that is to be called. The - associateObjWithEvent |
+ - function will return a reference to an inner function that |
+ is assigned to the event handler of the DOM element. That |
+ inner function will call the required method on the |
+ javascript object when it is executed in response to |
+ events:- |
+ */</span> |
+ el.onclick = associateObjWithEvent(this, "doOnClick"); |
+ el.onmouseover = associateObjWithEvent(this, "doMouseOver"); |
+ el.onmouseout = associateObjWithEvent(this, "doMouseOut"); |
+ ... |
+ } |
+} |
+DhtmlObject.prototype.doOnClick = function(event, element){ |
+ ... <span class="commentJS">// doOnClick method body</span>. |
+} |
+DhtmlObject.prototype.doMouseOver = function(event, element){ |
+ ... <span class="commentJS">// doMouseOver method body.</span> |
+} |
+DhtmlObject.prototype.doMouseOut = function(event, element){ |
+ ... <span class="commentJS">// doMouseOut method body.</span> |
+} |
+</pre> |
+ |
+<p> |
+And so any instances of the <code>DhtmlObject</code> can associate themselves |
+with the DOM element that they are interested in without any need |
+to know anything about how they are being employed by other code, |
+impacting on the global namespace or risking clashes with other |
+instances of the <code>DhtmlObject</code>. |
+</p> |
+ |
+<h3><a name="clEncap" id="clEncap">Example 3: Encapsulating Related Functionality</a></h3> |
+ |
+<p> |
+Closures can be used to create additional scopes that can be used to |
+group interrelated and dependent code in a way that minimises the risk |
+of accidental interaction. Suppose a function is to build a string and |
+to avoid the repeated concatenation operations (and the creation of |
+numerous intermediate strings) the desire is to use an array to store |
+the parts of the string in sequence and then output the results using |
+the <code>Array.prototype.join</code> method (with an empty string as its argument). |
+The array is going to act as a buffer for the output, but defining it |
+locally to the function will result in its re-creation on each |
+execution of the function, which may not be necessary if the only |
+variable content of that array will be re-assigned on each function |
+call. |
+</p> |
+ |
+<p> |
+One approach might make the array a global variable so that it can be |
+re-used without being re-created. But the consequences of that will be |
+that, in addition to the global variable that refers to the function |
+that will use the buffer array, there will be a second global property |
+that refers to the array itself. The effect is to render the code less |
+manageable, as, if it is to be used elsewhere, its author has to remember |
+to include both the function definition and the array definition. It |
+also makes the code less easy to integrate with other code because |
+instead of just ensuring that the function name is unique within the |
+global namespace it is necessary to ensure that the Array on which it |
+is dependent is using a name that is unique within the global |
+namespace. |
+</p> |
+ |
+<p> |
+A Closure allows the buffer array to be associated (and neatly |
+packaged) with the function that is dependent upon it and |
+simultaneously keep the property name to which the buffer array as |
+assigned out of the global namespace and free of the risk of name |
+conflicts and accidental interactions. |
+</p> |
+ |
+<p> |
+The trick here is to create one additional execution context by |
+executing a function expression in-line and have that function |
+expression return an inner function that will be the function that is |
+used by external code. The buffer array is then defined as a local |
+variable of the function expression that is executed in-line. That only |
+happens once so the Array is only created once, but is available to |
+the function that depends on it for repeated use. |
+</p> |
+ |
+<p> |
+The following code creates a function that will return a string of |
+<span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span>, much of which is constant, but those constant character |
+sequences need to be interspersed with variable information provided |
+as parameter to the function call. |
+</p> |
+ |
+<p> |
+A reference to an inner function object is returned from the in-line |
+execution of a function expression and assigned to a global variable |
+so that it can be called as a global function. The buffer array is |
+defined as a local variable in the outer function expression. It is |
+not exposed in the global namespace and does not need to be re-created |
+whenever the function that uses it is called. |
+</p> |
+ |
+<pre> |
+<span class="commentJS">/* A global variable - getImgInPositionedDivHtml - is declared and |
+ assigned the value of an inner function expression returned from |
+ a one-time call to an outer function expression. |
+ |
+ That inner function returns a string of <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> that represents an |
+ absolutely positioned DIV wrapped round an IMG element, such that |
+ all of the variable attribute values are provided as parameters |
+ to the function call:- |
+*/</span> |
+var getImgInPositionedDivHtml = (function(){ |
+ <span class="commentJS">/* The - buffAr - Array is assigned to a local variable of the |
+ outer function expression. It is only created once and that one |
+ instance of the array is available to the inner function so that |
+ it can be used on each execution of that inner function. |
+ |
+ Empty strings are used as placeholders for the date that is to |
+ be inserted into the Array by the inner function:- |
+ */</span> |
+ var buffAr = [ |
+ '<div id="', |
+ '', <span class="commentJS">//index 1, DIV ID attribute</span> |
+ '" style="position:absolute;top:', |
+ '', <span class="commentJS">//index 3, DIV top position</span> |
+ 'px;left:', |
+ '', <span class="commentJS">//index 5, DIV left position</span> |
+ 'px;width:', |
+ '', <span class="commentJS">//index 7, DIV width</span> |
+ 'px;height:', |
+ '', <span class="commentJS">//index 9, DIV height</span> |
+ 'px;overflow:hidden;\"><img src=\"', |
+ '', <span class="commentJS">//index 11, IMG URL</span> |
+ '\" width=\"', |
+ '', <span class="commentJS">//index 13, IMG width</span> |
+ '\" height=\"', |
+ '', <span class="commentJS">//index 15, IMG height</span> |
+ '\" alt=\"', |
+ '', <span class="commentJS">//index 17, IMG alt text</span> |
+ '\"><\/div>' |
+ ]; |
+ <span class="commentJS">/* Return the inner function object that is the result of the |
+ evaluation of a function expression. It is this inner function |
+ object that will be executed on each call to - |
+ getImgInPositionedDivHtml( ... ) -:- |
+ */</span> |
+ return (function(url, id, width, height, top, left, altText){ |
+ <span class="commentJS">/* Assign the various parameters to the corresponding |
+ locations in the buffer array:- |
+ */</span> |
+ buffAr[1] = id; |
+ buffAr[3] = top; |
+ buffAr[5] = left; |
+ buffAr[13] = (buffAr[7] = width); |
+ buffAr[15] = (buffAr[9] = height); |
+ buffAr[11] = url; |
+ buffAr[17] = altText; |
+ <span class="commentJS">/* Return the string created by joining each element in the |
+ array using an empty string (which is the same as just |
+ joining the elements together):- |
+ */</span> |
+ return buffAr.join(''); |
+ }); <span class="commentJS">//:End of inner function expression.</span> |
+})(); |
+<span class="commentJS">/*^^- :The inline execution of the outer function expression. */</span> |
+</pre> |
+ |
+<p> |
+If one function was dependent on one (or several) other functions, but |
+those other functions were not expected to be directly employed by any |
+other code, then the same technique could be used to group those |
+functions with the one that was to be publicly exposed. Making a |
+complex multi-function process into an easily portable and encapsulated |
+unit of code. |
+</p> |
+ |
+<h3><a name="clOtE" id="clOtE">Other Examples</a></h3> |
+ |
+<p> |
+Probably one of the best known applications of closures is |
+<a href="http://www.crockford.com/javascript/private.html">Douglas |
+Crockford's technique for the emulation of private instance variables |
+in ECMAScript objects</a>. Which can be extended to all sorts of |
+structures of <dfn>scope</dfn> contained nested accessibility/visibility, including |
+<a href="http://myweb.tiscali.co.uk/cornford/js_info/private_static.html"> |
+the emulation of private static members for ECMAScript objects</a>. |
+</p> |
+ |
+<p> |
+The possible application of closures are endless, understanding how |
+they work is probably the best guide to realising how they can be |
+used. |
+</p> |
+ |
+<h2 id="clAc">Accidental Closures</h2> |
+ |
+<p> |
+Rendering any inner function accessible outside of the body of the |
+function in which it was created will form a closure. That makes |
+closures very easy to create and one of the consequences is that |
+javascript authors who do not appreciate closures as a language feature |
+can observe the use of inner functions for various tasks and employ |
+inner functions, with no apparent consequences, not realising that |
+closures are being created or what the implications of doing that are. |
+</p> |
+ |
+<p> |
+Accidentally creating closures can have harmful side effects as the |
+following section on the IE memory leak problem describes, but they can |
+also impact of the efficiency of code. It is not the closures |
+themselves, indeed carefully used they can contribute significantly |
+towards the creation of efficient code. It is the use of inner |
+functions that can impact on efficiency. |
+</p> |
+ |
+<p> |
+A common situation is where inner functions are used is as event |
+handlers for DOM elements. For example the following code might be used |
+to add an onclick handler to a link element:- |
+</p> |
+ |
+<pre> |
+<span class="commentJS">/* Define the global variable that is to have its value added to the |
+ - href - of a link as a query string by the following function:- |
+*/</span> |
+var quantaty = 5; |
+<span class="commentJS">/* When a link passed to this function (as the argument to the function |
+ call - linkRef -) an onclick event handler is added to the link that |
+ will add the value of a global variable - quantaty - to the - href - |
+ of that link as a query string, then return true so that the link |
+ will navigate to the resource specified by the - href - which will |
+ by then include the assigned query string:- |
+*/</span> |
+function addGlobalQueryOnClick(linkRef){ |
+ <span class="commentJS">/* If the - linkRef - parameter can be type converted to true |
+ (which it will if it refers to an object):- |
+ */</span> |
+ if(linkRef){ |
+ <span class="commentJS">/* Evaluate a function expression and assign a reference to the |
+ function object that is created by the evaluation of the |
+ function expression to the onclick handler of the link |
+ element:- |
+ */</span> |
+ linkRef.onclick = function(){ |
+ <span class="commentJS">/* This inner function expression adds the query string to |
+ the - href - of the element to which it is attached as |
+ an event handler:- |
+ */</span> |
+ this.href += ('?quantaty='+escape(quantaty)); |
+ return true; |
+ }; |
+ } |
+} |
+</pre> |
+ |
+<p> |
+Whenever the <code>addGlobalQueryOnClick</code> function is called a |
+new inner function is created (and a closure formed by its assignment). |
+From the efficiency point of view that would not be significant if the |
+<code>addGlobalQueryOnClick</code> function was only called once or |
+twice, but if the function was heavily employed many distinct function |
+objects would be created (one for each evaluation of the inner function |
+expression). |
+</p> |
+ |
+<p> |
+The above code is not taking advantage of the fact that inner functions |
+are becoming accessible outside of the function in which they are being |
+created (or the resulting closures). As a result exactly the same effect |
+could be achieved by defining the function that is to be used as the |
+event handler separately and then assigning a reference to that |
+function to the event handling property. Only one function object would |
+be created and all of the elements that use that event handler would |
+share a reference to that one function:- |
+</p> |
+ |
+<pre> |
+<span class="commentJS">/* Define the global variable that is to have its value added to the |
+ - href - of a link as a query string by the following function:- |
+*/</span> |
+var quantaty = 5; |
+ |
+<span class="commentJS">/* When a link passed to this function (as the argument to the function |
+ call - linkRef -) an onclick event handler is added to the link that |
+ will add the value of a global variable - quantaty - to the - href - |
+ of that link as a query string, then return true so that the link |
+ will navigate to the resource specified by the - href - which will |
+ by then include the assigned query string:- |
+*/</span> |
+function addGlobalQueryOnClick(linkRef){ |
+ <span class="commentJS">/* If the - linkRef - parameter can be type converted to true |
+ (which it will if it refers to an object):- |
+ */</span> |
+ if(linkRef){ |
+ <span class="commentJS">/* Assign a reference to a global function to the event |
+ handling property of the link so that it becomes the |
+ element's event handler:- |
+ */</span> |
+ linkRef.onclick = forAddQueryOnClick; |
+ } |
+} |
+<span class="commentJS">/* A global function declaration for a function that is intended to act |
+ as an event handler for a link element, adding the value of a global |
+ variable to the - href - of an element as an event handler:- |
+*/</span> |
+function forAddQueryOnClick(){ |
+ this.href += ('?quantaty='+escape(quantaty)); |
+ return true; |
+} |
+</pre> |
+ |
+<p> |
+As the inner function in the first version is not being used to exploit |
+the closures produced by its use, it would be more efficient not to use |
+an inner function, and thus not repeat the process of creating many |
+essentially identical function objects. |
+</p> |
+ |
+<p> |
+A similar consideration applies to object constructor functions. It is |
+not uncommon to see code similar to the following skeleton constructor:- |
+</p> |
+ |
+ |
+<pre> |
+function ExampleConst(param){ |
+ <span class="commentJS">/* Create methods of the object by evaluating function expressions |
+ and assigning references to the resulting function objects |
+ to the properties of the object being created:- |
+ */</span> |
+ this.method1 = function(){ |
+ ... <span class="commentJS">// method body.</span> |
+ }; |
+ this.method2 = function(){ |
+ ... <span class="commentJS">// method body.</span> |
+ }; |
+ this.method3 = function(){ |
+ ... <span class="commentJS">// method body.</span> |
+ }; |
+ <span class="commentJS">/* Assign the constructor's parameter to a property of the object:- |
+ */</span> |
+ this.publicProp = param; |
+} |
+</pre> |
+ |
+<p> |
+Each time the constructor is used to create an object, with |
+<code>new ExampleConst(n)</code>, a new set of function objects are |
+created to act as its methods. So the more object instances that are |
+created the more function objects are created to go with them. |
+</p> |
+ |
+<p> |
+Douglas Crockford's technique for emulating private members on |
+javascript objects exploits the closure resulting form assigning |
+references to inner function objects to the public properties of a |
+constructed object from within its constructor. But if the methods of |
+an object are not taking advantage of the closure that they will form |
+within the constructor the creation of multiple function objects for |
+each object instantiation will make the instantiation process slower |
+and more resources will be consumed to accommodate the extra function |
+objects created. |
+</p> |
+ |
+<p> |
+In that case it would be more efficient to create the function object |
+once and assign references to them to the corresponding properties of |
+the constructor's <code>prototype</code> so they may be shared by all |
+of the objects created with that constructor:- |
+</p> |
+ |
+<pre> |
+function ExampleConst(param){ |
+ <span class="commentJS">/* Assign the constructor's parameter to a property of the object:- |
+ */</span> |
+ this.publicProp = param; |
+} |
+<span class="commentJS">/* Create methods for the objects by evaluating function expressions |
+ and assigning references to the resulting function objects to the |
+ properties of the constructor's prototype:- |
+*/</span> |
+ExampleConst.prototype.method1 = function(){ |
+ ... <span class="commentJS">// method body.</span> |
+}; |
+ExampleConst.prototype.method2 = function(){ |
+ ... <span class="commentJS">// method body.</span> |
+}; |
+ExampleConst.prototype.method3 = function(){ |
+ ... <span class="commentJS">// method body.</span> |
+}; |
+ |
+</pre> |
+<h2><a name="clMem" id="clMem">The Internet Explorer Memory Leak Problem</a></h2> |
+ |
+<p> |
+The Internet Explorer web browser (verified on versions 4 to 6 (6 is |
+current at the time of writing)) has a fault in its garbage collection |
+system that prevents it from garbage collecting ECMAScript and some |
+host objects if those host objects form part of a "circular" |
+reference. The host objects in question are any DOM Nodes (including |
+the document object and its descendants) and ActiveX objects. If a |
+circular reference is formed including one or more of them, then |
+none of the objects involved will be freed until the browser is closed |
+down, and the memory that they consume will be unavailable to the |
+system until that happens. |
+</p> |
+ |
+<p> |
+A circular reference is when two or more objects refer to each other in |
+a way that can be followed and lead back to the starting point. Such |
+as object 1 has a property that refers to object 2, object 2 has a |
+property that refers to object 3 and object 3 has a property that |
+refers back to object 1. With pure ECMAScript objects as soon as no |
+other objects refer to any of objects 1, 2 or 3 the fact that they only |
+refer to each other is recognised and they are made available for |
+garbage collection. But on Internet Explorer, if any of those objects |
+happen to be a DOM Node or ActiveX object, the garbage collection |
+cannot see that the circular relationship between them is isolated |
+from the rest of the system and free them. Instead they all stay in |
+memory until the browser is closed. |
+</p> |
+ |
+<p> |
+Closures are extremely good at forming circular references. If a |
+function object that forms a closure is assigned as, for example, and |
+event handler on a DOM Node, and a reference to that Node is assigned |
+to one of the Activation/Variable objects in its <dfn>scope chain</dfn> then a |
+circular reference exists. |
+<span class="scopeCh">DOM_Node.onevent -></span> |
+<span class="scopeCh">function_object.[[scope]] -></span> |
+<span class="scopeCh">scope_chain -></span> |
+<span class="scopeCh">Activation_object.nodeRef -></span> |
+<span class="scopeCh">DOM_Node</span>. |
+It is very easy to do, and a bit of browsing around a site that forms |
+such a reference in a piece of code common to each page can consume |
+most of the systems memory (possibly all). |
+</p> |
+ |
+<p> |
+Care can be taken to avoid forming circular references and remedial |
+action can be taken when they cannot otherwise be avoided, such as |
+using IE's onunload event to null event handling function |
+references. Recognising the problem and understanding closures |
+(and their mechanism) is the key to avoiding this problem with IE. |
+</p> |
+ |
+<p id="rToc"> |
+<a href="faq_notes.html#toc">comp.lang.javascript FAQ notes T.O.C.</a> |
+</p> |
+ |
+<ul style="list-style-type:none;margin-top:2.5em;"> |
+ <li>Written by <span class="person">Richard Cornford</span>. March 2004.</li> |
+ <li>With corrections and suggestions by:-<br> |
+ <ul style="list-style-type:none;"> |
+ <li><span class="person">Martin Honnen</span>.</li> |
+ <li><span class="person">Yann-Erwan Perio (Yep)</span>.</li> |
+ <li><span class="person">Lasse Reichstein Nielsen</span>. (<a href="#clDefN">definition of closure</a>)</li> |
+ <li><span class="person">Mike Scirocco</span>.</li> |
+ <li><span class="person">Dr John Stockton</span>.</li> |
+ <li><span class="person">Garrett Smith</span>.</li> |
+ </ul> |
+ </li> |
+</ul> |
+</body> |
+</html> |
/cljs/faq_notes/closures.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/faq_notes/faq_notes.html |
=================================================================== |
--- cljs/faq_notes/faq_notes.html (nonexistent) |
+++ cljs/faq_notes/faq_notes.html (revision 2) |
@@ -0,0 +1,196 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
+<html lang="en"><head><title>Notes on the comp.lang.javascript FAQ</title> |
+<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> |
+<meta name="ROBOTS" content="NOINDEX NOFOLLOW"> |
+<link href="../faq.css" rel="stylesheet" type="text/css"> |
+<link href="faq_notes.css" rel="stylesheet" type="text/css"> |
+<style type="text/css"> |
+.tocEn { |
+ margin-bottom:0.5em; |
+} |
+</style> |
+</head> |
+<body> |
+<div id="pageWarning"> |
+ The documents under <kbd>faq_notes/</kbd> are unmaintained. An up-to-date version |
+ of this document may be available at |
+ <a href="/faq/notes/">/faq/notes/</a>. |
+</div> |
+ |
+<h1>Notes on the comp.lang.javascript FAQ</h1> |
+<h2><a name="toc" id="toc">Table of Contents</a></h2> |
+ |
+<ul id="contTable"> |
+ <li class="tocEn"><a href="#fnIntro">Introduction to the Notes</a> |
+ <li class="tocEn"> |
+ <a name="FAQN2" id="FAQN2">2 comp.lang.javascript tips</a> |
+ <ol> |
+ <li><a href="clj_posts.html">Posting Questions and Replies to comp.lang.javascript</a></li> |
+ </ol> |
+ </li> |
+ <li class="tocEn"> |
+ <a name="FAQN4_4" id="FAQN4_4">4.4 How can I see in javascript if a web browser accepts cookies?</a> |
+ <ol> |
+ <li><a href="cookies.html">Privacy filters on proxies</a></li> |
+ </ol> |
+ </li> |
+ <li class="tocEn"> |
+ <a name="FAQN4_12" id="FAQN4_12">4.12 Why does parseInt('09') give an error?</a> |
+ <ol> |
+ <li>See: <a href="type_convert.html#tcPrIntRx">4.21.1 Javascript Type-Conversion - parseInt with a radix argument</a> |
+ </li> |
+ </ol> |
+ </li> |
+ <li class="tocEn"> |
+ <a name="FAQN4_13" id="FAQN4_13">4.13 How do I get the value of a form control?</a> |
+ <ol> |
+ <li><a href="form_access.html#faHead">Referencing Forms and Form Controls.</a> |
+ <ul> |
+ <li><a href="form_access.html#faInt">Introduction</a> |
+ <ul> |
+ <li><a href="form_access.html#faInF">Forms</a></li> |
+ <li><a href="form_access.html#faInC">Form Controls</a></li> |
+ </ul> |
+ </li> |
+ <li><a href="form_access.html#faShrt">Shortcut Accessors</a></li> |
+ <li><a href="form_access.html#faComMis">The Most Common Mistake</a></li> |
+ <li><a href="form_access.html#faAnon">Anonymous Form References</a></li> |
+ <li><a href="form_access.html#faBut">Radio Button and Other Control Collections</a></li> |
+ <li><a href="form_access.html#faEff">Efficient use of Form Accessors</a></li> |
+ </ul> |
+ </li> |
+ </ol> |
+ </li> |
+ <li class="tocEn"> |
+ <a name="FAQN4_15" id="FAQN4_15">4.15 How do I modify the current page in a browser?</a> |
+ <ol> |
+ <li><a href="alt_dynwrite.html#alDynWr">An Alternative DynWrite function</a> |
+ <ul> |
+ <li><a href="alt_dynwrite.html#DynWr">The DynWrite function.</a></li> |
+ <li><a href="alt_dynwrite.html#getEl">Element retrieval given the element ID as a string.</a></li> |
+ <li><a href="alt_dynwrite.html#innHTest">innerHTML Testing Strategy.</a></li> |
+ <li><a href="alt_dynwrite.html#AltDynWr">Alternative DynWrite function.</a></li> |
+ </ul> |
+ </li> |
+ </ol> |
+ </li> |
+ <li class="tocEn"> |
+ <a name="FAQN4_21" id="FAQN4_21">4.21 Why does 1+1 equal 11? or How do I convert a string to a number?</a> |
+ <ol> |
+ <li><a href="type_convert.html">Javascript Type-Conversion</a> |
+ <ul> |
+ <li><a href="type_convert.html#tcInt">Introduction.</a></li> |
+ <li><a href="type_convert.html#tcBool">Converting to Boolean.</a></li> |
+ <li><a href="type_convert.html#tcString">Converting to String.</a></li> |
+ <li><a href="type_convert.html#tcNumber">Converting to Number.</a></li> |
+ <li><a href="type_convert.html#tcParse">Parsing to Number.</a> |
+ <ul> |
+ <li><a href="type_convert.html#tcParseFl">parseFloat</a></li> |
+ <li><a href="type_convert.html#tcParseIn">parseInt</a></li> |
+ <li><a href="type_convert.html#tcPrIntRx">parseInt with a radix argument</a></li> |
+ </ul> |
+ </li> |
+ <li><a href="type_convert.html#tcToInt32">ToInt32.</a></li> |
+ <li><a href="type_convert.html#tcUserIn">Converting User Input.</a> |
+ <ul> |
+ <li><a href="type_convert.html#tcRegEx">Regular expression examples.</a></li> |
+ </ul> |
+ </li> |
+ </ul> |
+ </li> |
+ </ol> |
+ </li> |
+ <li class="tocEn"> |
+ <a name="FAQN4_25" id="FAQN4_25">4.25 My element is named myselect[] , how do I access it?</a> |
+ <ol> |
+ <li>See: <a href="square_brackets.html#illc">4.39.1 Javascript Square Bracket Notation - Illegal characters in Identifier-strings</a> |
+ </li> |
+ </ol> |
+ </li> |
+ <li class="tocEn"> |
+ <a name="FAQN4_26" id="FAQN4_26">4.26 How do I detect Opera/Netscape/IE?</a> |
+ <ol> |
+ <li><a href="not_browser_detect.html#bdTop">Browser Detecting (and what to do Instead)</a> |
+ |
+ <ul> |
+ <li><a href="not_browser_detect.html#bdIntro">Introduction</a></li> |
+ <li><a href="not_browser_detect.html#bdValid">Avoiding structural differences in the browser DOMs</a></li> |
+ <li><a href="not_browser_detect.html#bdDif">Browsers Differences</a></li> |
+ <li><a href="not_browser_detect.html#bdFailS">Failed Strategies: Browser Detecting</a> |
+ <ul> |
+ <li><a href="not_browser_detect.html#bdUAS">Assumptions Based on navigator.userAgent</a></li> |
+ <li><a href="not_browser_detect.html#bdOI">Assumptions Based on DOM Objects: Object inference</a></li> |
+ </ul> |
+ </li> |
+ <li><a href="not_browser_detect.html#bdFD">A Strategy That Works: Object/Feature Detecting.</a> |
+ <ul> |
+ <li><a href="not_browser_detect.html#bdGEID">Example 1: IDed Element Retrieval</a></li> |
+ <li><a href="not_browser_detect.html#bdScroll">Example 2: Scroll Values</a></li> |
+ <li><a href="not_browser_detect.html#bdReplace">Example 3: String.prototype.replace</a></li> |
+ </ul> |
+ </li> |
+ <li><a href="not_browser_detect.html#bdDesPb">The Javascript Design Problem</a></li> |
+ </ul> |
+ |
+ |
+ </li> |
+ </ol> |
+ </li> |
+ <li class="tocEn"> |
+ <a name="FAQN4_39" id="FAQN4_39">4.39 How do I access the property of an object using a string?</a> |
+ <ol> |
+ <li><a href="square_brackets.html">Javascript Square Bracket Notation</a> |
+ <ul> |
+ <li><a href="square_brackets.html#intro">Introduction</a></li> |
+ <li><a href="square_brackets.html#sBs">Square Bracket Syntax</a></li> |
+ <li><a href="square_brackets.html#vId">String Variables as Identifiers</a></li> |
+ <li><a href="square_brackets.html#eId">String Expressions as Identifiers</a></li> |
+ <li><a href="square_brackets.html#aVa">Global Variable access with the Square Bracket Notation</a></li> |
+ <li><a href="square_brackets.html#illc">Illegal characters in Identifier-strings</a></li> |
+ </ul> |
+ </li> |
+ </ol> |
+ </li> |
+ <li class="tocEn"> |
+ <a name="FAQN4_41" id="FAQN4_41">4.41 Why doesn't the global variable "divId" always refer to the element with id="divId"?</a> |
+ <ol> |
+ <li>See: <a href="alt_dynwrite.html#getEl">4.15.1 An Alternative DynWrite function - Element retrieval given the element ID as a string</a></li> |
+ <li>See: <a href="not_browser_detect.html#bdGEID">4.26.1 Browser Detecting (and what to do Instead) - Example 1: IDed Element Retrieval</a></li> |
+ </ol> |
+ </li> |
+ <li>Miscellaneous |
+ <ol> |
+ <li class="tocEn"><a href="cljs_charter.html">The comp.lang.javascript Charter</a></li> |
+ <li class="tocEn"><a href="closures.html">Javascript Closures</a></li> |
+ <li class="tocEn"><a href="script_tags.html">How to Include Scripts in <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> Documents</a></li> |
+ <li class="tocEn"><a href="misc.html">Tricks and Tips</a></li> |
+ </ol> |
+ </li> |
+ <li class="tocEn"><a href="contributors.html">Contributors</a></li> |
+ <li class="tocEn"><a href="faqNotes.zip">The complete FAQ and Notes in ZIP format (174KB)</a></li> |
+</ul> |
+ |
+<h2><a name="fnIntro" id="fnIntro">Introduction to the Notes</a></h2> |
+ |
+<p> |
+Because the <a href="http://jibbering.com/faq/">comp.lang.javascript |
+FAQ</a> is posted to the group regularly |
+there are practical constraints on how much can be included in it. At |
+the same time it is often felt that it should contain more (or more |
+in-depth) information on some of its topics. The FAQ is largely |
+designed to provide URLs of other resources that provide that |
+additional information, but where no additional resource is available |
+or it is felt that those resources omit important information. These |
+notes are intended to provide an opportunity for those additional |
+resources to be created. |
+</p> |
+ |
+<p> |
+It is intended that anyone who wishes to contribute notes should be |
+able to do so (under editorial control) and that some of the more |
+in-depth postings to the group should become notes, or be |
+incorporated within them. |
+</p> |
+ |
+</body> |
+</html> |
/cljs/faq_notes/faq_notes.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/faq_notes/clj_posts.html |
=================================================================== |
--- cljs/faq_notes/clj_posts.html (nonexistent) |
+++ cljs/faq_notes/clj_posts.html (revision 2) |
@@ -0,0 +1,1209 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" |
+"http://www.w3.org/TR/html4/strict.dtd"> |
+<html lang="en"> |
+<head> |
+<title>Notes on the comp.lang.javascript FAQ</title> |
+<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> |
+<link href="../../faq.css" rel="stylesheet" type="text/css"> |
+<link href="../notes.css" rel="stylesheet" type="text/css"> |
+<meta name="ROBOTS" content="NOINDEX, NOFOLLOW"> |
+<style type="text/css"> |
+.resourceList LI { |
+ margin-bottom: 0.8em; |
+} |
+</style> |
+</head> |
+<body> |
+ |
+<h1>Posting Questions and Replies to comp.lang.javascript</h1> |
+<div id="faqNav"> |
+ <a href="../../">FAQ</a> > <a href="../">FAQ Notes</a> |
+ |
+</div> |
+<ul> |
+ <li><a href="#ps1Intro">Introduction</a></li> |
+ <li><a href="#ps1Lang">Posting Language</a></li> |
+ <li><a href="#ps1OToc">On and Off Topic Posting</a></li> |
+ <li><a href="#ps1Txt">Plain-Text Only</a></li> |
+ <li><a href="#ps1Post">Interleaved Posting, Bottom Posting and Not Top Posting.</a> |
+ <ul> |
+ <li><a href="#ps1InBPost">Interleaved Posting, Bottom Posting</a></li> |
+ <li><a href="#ps1TopPs">Top Posting (don't)</a></li> |
+ </ul> |
+ </li> |
+ <li><a href="#ps1Trim">What to Trim</a></li> |
+ <li><a href="#ps1Marg">Margins and Line Wrapping</a> |
+ <ul> |
+ <li><a href="#ps1Mar">Margins</a></li> |
+ <li><a href="#ps1Lw">Line Wrapping</a></li> |
+ <li><a href="#ps1LwQu">Line Wrapping in Quoted Material</a></li> |
+ </ul> |
+ </li> |
+ <li><a href="#ps1Code">General Code Postings, and when to use a URL</a></li> |
+ <!-- <li><a href="#ps1Proof">Proof-read your message</a></li> --> |
+ <li><a href="#ps1Quest">Well Asked Questions Get the Best Answers</a> |
+ <ul> |
+ <li><a href="#ps1QSub">Appropriate Use of the Subject Header</a></li> |
+ <li><a href="#ps1QRes">Doing Your Own Research</a></li> |
+ <li><a href="#ps1DontWork">"It doesn't work"</a></li> |
+ <li><a href="#ps1CntX">Explain the Whole Context</a></li> |
+ <li><a href="#ps1PR">Proof-Read your Questions</a></li> |
+ </ul> |
+ </li> |
+ <!-- <li><a href="#ps1notHD">comp.lang.javascript is Not a Helpdesk</a></li> --> |
+ <li><a href="#ps1AddR">Additional Reading</a></li> |
+</ul> |
+ |
+<h2 id="ps1Intro">Introduction</h2> |
+<h3>Social Behavior</h3> |
+ |
+<p> |
+There may be several reasons for making posts to comp.lang.javascirpt |
+but all valid reasons would be intended to elicit responses, preferably |
+including responses form the many experienced and knowledgeable |
+regular contributors to the group. The direction of communication is |
+always one-to-many, which places the onus on the composer of a message |
+to consider the many in their audience above any personal preferences. |
+It is always in the best interest |
+of someone posting to the group to recognise that the people whose |
+responses will be of most value to them may have an attitude toward |
+their behaviour on the group, and to try to ensure that it will not be |
+a bad attitude. |
+</p> |
+ |
+<p> |
+It is also always in the best interest of any poster to the group to do |
+everything within their power to behave in a way that makes it quick |
+and easy for the people they expect to answer their questions to read and follow |
+their posts, understand their questions and problems and comprehend and |
+test posted code. The people with the best answers are the most likely |
+to be busy; too busy to be interested in unraveling a badly expressed |
+problem from a mass of incomprehensibly formatted code amid a |
+conversation that is hard to follow. |
+</p> |
+ |
+<p id="ps1Into_3"> |
+Usenet has been around for a long time now and has developed various |
+conventions of its own. Conventions that have evolved to make |
+communicating in the medium as easy and efficient as possible. They |
+are not necessarily adhered to on all groups but where they are |
+recognised they are definitely preferred. And comp.lang.javascript is |
+a group where most of the regulars recognise many Usenet conventions |
+and so the FAQ outlines them. This document is intended to provide |
+additional detail on the subject. |
+</p> |
+ |
+<p id="ps1Into_4"> |
+Following those conventions and additionally posting with a |
+consideration of the other points made on this page related more |
+specifically to posting in comp.lang.javascript, will maximise the |
+potential for any questions asked and posts made to elicit a useful |
+response. At least in part because they make it quicker and easier for |
+those interested in offering help to do so. |
+</p> |
+ |
+<h2 id="ps1Lang">Posting Language</h2> |
+ |
+<p id="ps1Lang_1"> |
+comp.lang.javascript is the international javascript group. There are |
+language specific javascript groups that could be expected to be |
+carried by news servers within the countries concerned. There is, |
+however, no English language specific javascript group so |
+comp.lang.javascript serves that audience. As a result the vast |
+majority of the conversation within the group is in English, and |
+anyone with a javascript interest but incapable of reading/writing any |
+language but English would choose comp.lang.javascript to read and post |
+in. But there are no rules that say that English is the only language |
+that is to be used. |
+</p> |
+ |
+<p id="ps1Lang_2"> |
+As an international group, comp.lang.javascript has contributors form |
+around the world, many of whom speak/read/write English as a second or |
+third (+) language. So a post made in any other language will stand a |
+chance of falling within the linguistic capabilities of someone. But |
+posts in English should be understandable to everyone, including those |
+for whom English is their only language, and thus receive the most |
+attention. |
+</p> |
+ |
+<p id="ps1Lang_3"> |
+Machine translation into English (and sometimes less skilled human |
+translation) sometimes does not produce results that can be |
+understood/followed by English speakers. When a bad translation into |
+English is the only option it might be better for a poster to precede |
+it with a version in their native language. (Faced with a post in a |
+language that is not understood it is natural to scroll down to see |
+if there is any accompanying javascript code that might explain the |
+problem; a following English translation would be discovered along |
+the way). A reader of the group who understands the language used |
+may be able to contribute improvements to the English translation even |
+if they cannot directly address the question raised. |
+</p> |
+ |
+<p id="ps1Lang_4"> |
+However, even though the most common language used in postings to |
+comp.lang.javascript is English, the fact that the group is |
+international and that English should not be expected to be the first |
+language of contributors to the group means that the English used |
+should be formally correct (to the best of the posters ability). |
+Normal English sentence structure should be observed, particularly in |
+terms of capitalisation (which serves to aid reading for everyone). But |
+above all, shorthand abbreviations should not be used, no matter how |
+common they may be in English speaking cultures, as they would not |
+normally be part of the teaching of English as a foreign language. This |
+applies especially to text-message shorthand as they are very much a |
+product of local culture and circumstances in a way that is not |
+relevant to Usenet as a medium or appropriate to an international |
+newsgroup. |
+</p> |
+ |
+<p id="ps1Lang_5"> |
+In the context of an international forum it is also probably best to |
+avoid references that may be ambiguous outside of a national context. |
+Date formats are an obvious example, with the ISO 8601 <code>YYYY-MM-DD</code> format |
+being more appropriate than any preferred local form. Also, references |
+to national bodies by acronym alone will not necessarily convey |
+sufficient meaning to an international audience. |
+</p> |
+ |
+<h2 id="ps1OToc">On and Off Topic Posting</h2> |
+ |
+<p id="ps1OToc_1"> |
+ECMA 262 is the formal specification for ECMAScript, the |
+standard adopted by javascript implementations and thus the |
+specification for javascript. |
+</p> |
+ |
+<h3>ECMAScript and Browsers</h3> |
+<p id="ps1OToc_2"> |
+As comp.lang.javascript deals with ECMAScript and ECMAScript was |
+designed as a general scripting language for scripting any object |
+model, questions relating to any application of ECMAScript are |
+appropriate. The group has a general bias towards the use of |
+ECMAScript in web browsers in an Internet context, and questions |
+asked without additional qualification will tend to be assumed to |
+be related to that environment and context. As a result it is a |
+very good idea for questions asked that are not related to that |
+default context; Intranet, other hosts, OS automation, etc., to |
+include details of that context. |
+</p> |
+ |
+<h3 id="ps1OToc_3">Javascript (not Java)</h3> |
+<p> |
+Because of the name "JavaScript" being applied to the |
+language early in its existence there is often confusion between |
+javascript and the Java programming language. The two are distinct |
+and very different languages. Questions relating to Java programming, |
+Java Applets, Java Server Pages (JSP), etc., would be better asked in |
+comp.lang.java.* groups. Only the use of ECMAScript to interact with, |
+say, Java Applets would be on topic, and then the questions should |
+relate to the ECMAScript aspect of the problem. |
+</p> |
+ |
+<h3 id="ps1OToc_4">Other Languages</h3> |
+<p> |
+Questions relating exclusively to other scripting languages, |
+ mark-up languages ((x)<span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span>) and style sheets |
+(<span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span>, XSL) are off topic and should be addressed to more |
+appropriate newsgroups. |
+</p> |
+ |
+<h3 id="ps1OToc_5">The FAQ</h3> |
+<p> |
+The comp.lang.javascript newsgroup may also validly become its own |
+subject, particularly the content and maintenance of the FAQ resources. |
+But as a subject that is most appropriately raised and discussed by |
+the individuals who invest their time in the group rather than |
+passers-by. |
+</p> |
+ |
+<h3 id="ps1OToc_6">Usenet Behavior (don't)</h3> |
+<p> |
+Usenet, and particularly appropriate behaviour on and for Usenet, is |
+also often raised. This is largely unwelcome but inevitable. Hopefully |
+this document should contribute to a reduction in that noise by stating |
+the group's attitude towards Usenet postings in greater detail than can |
+be accommodated in the FAQ proper. |
+</p> |
+ |
+<h3 id="ps1OToc_7">Spam (don't)</h3> |
+<p> |
+Other things that are off topic for the group include obvious things |
+like pyramid and get rich quick schemes, commercial advertising (with |
+some rare exceptions mentioned below), job adverts, spurious |
+invitations to visit web sites and anything else that might be |
+reasonably regarded as spam. |
+</p> |
+ |
+<h3>Announcements</h3> |
+<p id="ps1OToc_8"> |
+Announcements of product releases and events of particular relevance |
+to javascript are welcome but, for products no more often than once |
+pre major release, and for events preferably only once and certainly |
+not more often than at two month intervals leading up to the event. |
+Be aware that product announcements (particularly commercial |
+javascript) are likely to attract reviews, which should not be |
+expected to be uncritical. |
+</p> |
+ |
+<h2 id="ps1Txt">Plain-Text Only</h2> |
+ |
+<p id="ps1Txt_1"> |
+Messages are posted in plain-text. There is no requirement for Usenet |
+newsreader software to recognise, support or display any other |
+content type, such as <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span>, and it is felt that messages posted to |
+comp.lang.javascript should be available to any and all newsreader |
+software. Any form of attachments are also ruled out. |
+</p> |
+ |
+<p id="ps1Txt_2"> |
+It has also been observed that while most of the world may be happy |
+to use the newsreader bundled with their operating system, experts in |
+various aspects of computing will often go out and acquire software |
+that they believe superior for the task they have for it. Meaning that |
+the people best equipped to offer help in the group are also the people |
+least likely to be using the newsreader that you are familiar with. |
+The expectation should be that others are using software that conforms |
+to the applicable standards and not that they are using software with |
+any particular set of additional or "enhanced" features, no |
+matter how common they may seem. Plain-text posts will be readable by |
+everyone, other content types may be subject to more comment on the |
+inappropriateness of the content type than answers intended to address |
+the question raised. |
+</p> |
+ |
+<h2 id="ps1Post">Interleaved Posting, Bottom Posting and Not Top Posting</h2> |
+ |
+<h3 id="ps1InBPost">Interleaved Posting, Bottom Posting</h3> |
+ |
+<p id="ps1InBPost_1"> |
+The posting style in messages intended as responses to other messages |
+is an area where a long established pattern of behaviour has been |
+recognised as most appropriate for the medium and become an established |
+convention. |
+</p> |
+ |
+<p id="ps1InBPost_2"> |
+Material quoted from the previous message is attributed to its author |
+and indented with a marker character (usually >). It is trimmed down |
+to just sufficient to provide the context in which the response is made |
+(marking the fact that an edit has been made with one of several |
+common notations, such as: <snip>, [snip], [ ... ], etc.) and |
+the responding text is placed <em>below</em> the quoted material |
+to which it is responding, separated from it by a blank line. |
+</p> |
+ |
+<p id="ps1InBPost_3"> |
+If the response addresses several points from the previous message |
+then the parts of the quoted text providing the context for each |
+point are separated by the responses to each point. Producing an |
+interleaved post. If the quoted material is in one block then the |
+response text goes after it at the bottom. Producing a bottom post. |
+</p> |
+ |
+<p id="ps1InBPost_4"> |
+It is not possible to distinguish between bottom posting and an |
+interleaved post that is only responding to one point in the previous |
+message. Personally, I prefer interleaved responses but neither will |
+result in an adverse reaction. The important points are that quoted |
+material should be trimmed to the minimum that provides sufficient |
+context and that responses should follow that quoted material. |
+The conversation, and its chronological sequence, flows in the normal |
+direction of reading; top to bottom. |
+</p> |
+ |
+<p id="ps1InBPost_5"> |
+Failing to quote any of the preceding message is not necessarily |
+wrong, so long as the text posted makes sense without the preceding |
+message, for example, by summarising the points being responded to. |
+But generally it is easier to provide the context for a response with |
+a quoted snippet. But responses need to have a context. |
+</p> |
+ |
+<h3 id="ps1TopPs">Top Posting (don't)</h3> |
+ |
+<p id="ps1TopPs_1"> |
+Top posting is placing the response above the quoted material that is |
+being responded to. The chronological sequence of conversation becomes |
+the reverse of the normal top to bottom reading sequence and, without |
+additional text summarising the points being responded to, it is |
+difficult to determine exactly which points such a reply relates to. |
+</p> |
+ |
+<p id="ps1TopPs_2"> |
+The worst possible style of response posting is top posting over a full |
+verbatim quote of the previous message, but even placing a response |
+above a trimmed quote is wrong. It renders the conversational aspects |
+of a response backwards, requiring people to scroll up and down to |
+reconstruct the context of the response and generally making it hard |
+work to understand the message. The answers come before the questions |
+and the comments precede their subjects. |
+</p> |
+ |
+<p id="ps1TopPs_3"> |
+People do attempt to justify top posting. A common excuse made by top |
+posters is that their newsreader places the cursor at the top of the |
+message so that is the natural place to write the reply. That excuse |
+is worthless as newsreader software does not dictate the style of |
+posting and a cursor that starts at the top of a post does not have |
+to stay there. Indeed it should not be expected to stay there, as the |
+first responsibility of the respondent is to trim the quoted material |
+down to just what is necessary to provide context for their response. |
+A process that may reasonably be achieved by moving down through the |
+quoted material deleting whatever is unneeded and marking those edits. |
+And having done that the cursor will be at or near the bottom. |
+</p> |
+ |
+<p id="ps1TopPs_4"> |
+The other common excuse for top posting is that avoids excessive |
+scrolling in order to find the response. The need for excessive |
+scrolling in an interleaved or bottom posted message is most likely |
+an indicator that the quoted material has not been suitably, or |
+sufficiently, trimmed. But a top posters apparent desire to avoid |
+scrolling is of no value to the regular users of Usenet who are |
+accustomed to interleaved/bottom posting. They may take the top |
+post as a preamble and still scroll down to see if any specific |
+points have been responded to, not discovering that hey have wasted |
+their time until they get to the bottom. A very short top post, |
+without a blank line separating it from the following attribution |
+line, may easily be missed by someone expecting the quoted material |
+to come first, meaning that they do not discover where to look until |
+they have scrolled to the bottom, and then they need to back scroll |
+to the top. The perception is wrong, top posting results in much more |
+unnecessary scrolling than it avoids, and that misperception impacts on |
+regular user of Usenet; the very people whose help and co-operation is |
+being sought. |
+</p> |
+ |
+<p id="ps1TopPs_5"> |
+<strong>Never top post to comp.lang.javascript</strong>. There is an |
+established convention in posting styles on Usenet, and |
+comp.lang.javascript. It is most efficient for everyone if newcomers |
+follow that convention even if it seems strange to do so at first. In |
+the long run it makes life easier for everyone, and the sooner that is |
+recognised the less likelihood there is of being taken for a fool. |
+</p> |
+ |
+<h2 id="ps1Trim">What to Trim</h2> |
+ |
+<p id="ps1Trim_1"> |
+As a general guide, quoted material should almost never exceed the |
+text posted in response. Exceptions might occur when both consist |
+of exactly one line or sentence, or maybe a short code block that |
+only needs a one line comment. |
+</p> |
+ |
+<p id="ps1Trim_2"> |
+Deciding what to trim is a matter of judgment and takes a bit of |
+practice to get right. There are few hard and fast rules and the best |
+general advice has got to be to observe the behaviour of others |
+positing to the group. |
+</p> |
+ |
+<p id="ps1Trim_3"> |
+It is necessary to preserve the context in |
+which a response is made but some things can be trimmed automatically: |
+Signatures (if present); the section at the end of a post (and they |
+should always, and only, be at the end, no matter where any individual |
+newsreader may try to insert them) which starts with a separator |
+consisting of "dash dash space newline(aka return)" on a |
+line of its own, followed by material that is not directly |
+related to the post but may be of more general interest or related |
+to the individual who makes the post, should <strong>always</strong> |
+be trimmed from quoted material. It is never normally relevant to a |
+posted response, but even if a signature is being directly commented |
+upon it is vital to remove the signature separator at least, and best |
+to trim anything it contains that is not being commented upon. |
+</p> |
+ |
+<p id="ps1Trim_4"> |
+In comp.lang.javascript there is rarely much point in quoting |
+javascript code that is not being directly commented upon or |
+corrected. The indenting character (and possible line wrapping) |
+renders any quoted code syntactically invalid so anyone wanting |
+to use the code will have to go back to the message in which it |
+originally appeared anyway. That would certainly apply to a post |
+wishing to thank someone who had provided a complete scripted |
+demonstration for their efforts. |
+</p> |
+ |
+<p id="ps1Trim_5"> |
+No matter what gets trimmed the material that stays should not be |
+altered in terms of spelling, words used and their order, etc. A |
+quote should be a quote not an interpretation. |
+</p> |
+ |
+<h2 id="ps1Marg">Margins and Line Wrapping</h2> |
+<h3 id="ps1Mar">Margins</h3> |
+ |
+<p id="ps1Mar_1"> |
+A line in a plane text Usenet post could be quite long, and some |
+newsreaders would automatically wrap that line to the window in |
+which it was being displayed. Others would provide horizontal scroll |
+bars (usually undesirable) and yet others may not be able to access |
+characters beyond the 80<sup>th</sup> (unlikely these days). There |
+are no rules for handling excessively long lines but Usenet is old |
+and has lived through the time when 80 character wide displays were |
+commonplace. Along the way it became the convention that Usenet posts |
+should have lines no longer than between 70 and 80 characters. And |
+that avoids the need for any specified requirement in the handling of |
+long lines by newsreader software. Lines in that range are unlikely to |
+need to be wrapped for display and will not normally generate |
+horizontal scroll bars. It is also the case that humans generally |
+(and sometimes strongly) prefer to read text that is no more than about |
+80 character per line. |
+</p> |
+ |
+<p id="ps1Mar_2"> |
+It is widely recommended that newsreader software should be configured |
+to automatically wrap at about 72 characters when posting, which works |
+well for posted text but can be problematic for posting long URLs and |
+particularly in our context, posted source code. Others suggest that |
+software should not be allowed to wrap posted code at all and that the |
+poster should always do it manually. In either case it is the |
+individual composing the post that is responsible for, and should be in |
+control of, the wrapping of the content to ensure that it is suitable |
+for posting to the group. |
+</p> |
+ |
+<h3 id="ps1Lw">Line Wrapping</h3> |
+ |
+<p id="ps1Lw_1"> |
+Most URLs are less than 72 character long anyway but some, such as |
+references to Usenet articles in the archives at groups.google.com, |
+are longer. Some newsreader software is smart enough to recognise a |
+URL and not apply its default margin settings to them but in any event |
+delimiting them with "<URL:" at the beginning and |
+">" at the end (preferably with the URL separated from |
+the delimiters with spaces) should be sufficient to indicate to a |
+reader that a line wrapped URL will need some remedial action. |
+</p> |
+ |
+<p id="ps1Lw_2"> |
+Restricting margins to 72 characters usually does not need to affect |
+the functionality of posted code either. Allowing a newsreader to |
+line wrap posted code as it sees fit will usually render that code |
+faulty (and difficult to read) and that will make it difficult for |
+a reader to differentiate between problems within the original code |
+and problems arising form line wrapping. |
+</p> |
+ |
+<h3 id="ps1Lw_3">Code Reformatting</h3> |
+<p> |
+Javascript (ECMAScript) is extremely tolerant of white space (including |
+line breaks) within its source code. There are in fact only a couple of |
+places where white space characters are not allowed. For example, a |
+line break may not be placed between the <code>return</code> keyword |
+and any expression that is to be returned. As a result it is almost |
+always possible to spread a line of javascript that would exceed the |
+newsreaders wrapping margin across two or more lines without affecting |
+its functionality or syntactic correctness. |
+</p> |
+ |
+<p id="ps1Lw_4"> |
+One of the main reasons that Javascript is so tolerant of white space |
+is to allow the structure of the source code (how the code is laid out |
+in a text editor/post) to convey additional meaning (usually related to |
+structure of the code/function/program) and maximise clarity for human |
+readers. The breaking of long lines of source code across several lines |
+should be done in a way that does not detract from the clarity of the |
+code. |
+</p> |
+ |
+<h4 id="ps1Lw_5">Blocks</h4> |
+<p> |
+The main source code structuring consideration that adds clarity is |
+block indenting. A block is defined with curly brackets <code>{</code> |
+and <code>}</code> and represents a block statement (which may contain |
+zero or more other statements). It is normal to indent the statements |
+within a block by one tab character, though that tab is usually set to |
+4 or fewer spaces (two spaces is frequently recommended) width as the |
+normal default 8 spaces width is a bit |
+too deep for most practical uses. However, <em>tab character should not be |
+used for indention in Usenet posts at all</em> as newsreader default tab |
+settings may often be 8 characters but may also be zero characters, |
+defeating the purpose indentation in posted code entirely. Good text |
+editors will usually offer a facility to convert tabs to any number of |
+spaces, which can be used to prepare code for posting. Indenting in |
+code posted to Usenet should be done with space characters. 4 or fewer |
+(two is often recommended) per level of indentation. |
+</p> |
+ |
+<p id="ps1Lw_6"> |
+There are various common styles of block indenting, of which I prefer |
+to leave the opening <code>{</code> at the end of the control statement |
+(on the same line) and list the block contents as one statement per |
+line, indented by 4 <em>or fewer</em> spaces, with the closing |
+<code>}</code> on a new line indented so that it lines up vertically |
+with the start of the control statement, e.g.:- |
+</p> |
+ |
+<pre id="ps1Lw_ex1"> |
+function doSomething(oArea){ |
+ var nArea = oArea.nWidth * oArea.nHeight; |
+ var result = true; |
+ if(!nArea){ |
+ removeRegion(oArea); |
+ result = false; |
+ }else if(oArea.nWidth < oArea.nHeight){ |
+ result = oArea.reShape(nArea); |
+ } |
+ return result; |
+} |
+ |
+<span class="commentJS">/* The same function may also be commonly formatted:- */</span> |
+ |
+function doSomething(oArea) |
+{ |
+ var nArea = oArea.nWidth * oArea.nHeight; |
+ var result = true; |
+ if(!nArea) |
+ { |
+ removeRegion(oArea); |
+ result = false; |
+ } |
+ else if(oArea.nWidth < oArea.nHeight) |
+ { |
+ result = oArea.reShape(nArea); |
+ } |
+ return result; |
+} |
+ |
+<span class="commentJS">/* -or:- */</span> |
+ |
+function doSomething(oArea) |
+ { |
+ var nArea = oArea.nWidth * oArea.nHeight; |
+ var result = true; |
+ if(!nArea) |
+ { |
+ removeRegion(oArea); |
+ result = false; |
+ } |
+ else if(oArea.nWidth < oArea.nHeight) |
+ { |
+ result = oArea.reShape(nArea); |
+ } |
+ return result; |
+ } |
+</pre> |
+ |
+<p id="ps1Lw_7"> |
+It is not that important which style of block indenting is used, |
+everyone has their own preferred style, but it is important that |
+<em>a</em> style of block indenting is used in code posted to the |
+group. In all cases the indenting serves to make the structure of |
+the function apparent in the structure of the source code. It is |
+an aid to human readers of the code and saves a great deal of time |
+for anyone attempting to offer help and so needing to understand |
+the code. |
+</p> |
+ |
+<p id="ps1Lw_8"> |
+Sometimes the line wrapping problem can be avoided by reducing the |
+number of space characters by which the blocks are indented. However, |
+if a statement must be broken across several lines |
+it could be indented to a different level than it's own start, and it |
+could also be indented at a different level to its block contents (if |
+any). If block indenting is at, say, 4 space intervals then indenting a |
+broken line at 1 to 3 characters should serve to make it clear that |
+it is indenting separate from the general block structure of the |
+code, e.g.:- |
+</p> |
+ |
+<pre id="ps1Lw_ex2"> |
+function getRootElement_OrDefault(deflt){ |
+ if((typeof document.compatMode == "string")&& |
+ (document.compatMode.indexOf("CSS") != -1)&& |
+ (document.documentElement)){ <span class="commentJS">//<< broken statement</span> |
+ return document.documentElement; |
+ }else if(document.body){ |
+ return document.body; |
+ }else{ |
+ return deflt; |
+ } |
+} |
+ |
+</pre> |
+ |
+<p id="ps1Lw_9"> |
+Another alternative for formatting statements broken across lines |
+might be to disregard the indenting on the left and line the code |
+that belongs to the broken statement up on the right hand side. |
+e.g.:- |
+</p> |
+ |
+<pre id="ps1Lw_ex3"> |
+this.position = function(){ |
+ var twiceSize; |
+ if(--delay <= 0){ |
+ step(); |
+ if(((z+=fv) >= planeDepth)|| |
+ ((dy+dm) > windowCenterY)|| |
+ ((dx+dm) > windowCenterX)|| |
+ (v < 0)){ <span class="commentJS">//right aligned broken statement</span> |
+ this.reset(); |
+ step(); |
+ } |
+ div.top = (sy+(py*dy)-dm)+cssUnitsOrZero; |
+ div.left = (sx+(px*dx)-dm)+cssUnitsOrZero; |
+ divClip.height = (twiceSize = (dm << 1)+cssUnitsOrZero); |
+ divClip.width = twiceSize; |
+ } |
+ next.position(); |
+}; |
+</pre> |
+ |
+<p id="ps1Lw_10"> |
+Thus the ability to insert line breaks liberally throughout javascript |
+source code allows almost all code to be formatted in a fully |
+functional, well structured and clear way within the restricted |
+margins appropriate in posts to comp.lang.javascript. Efforts put into |
+preparing posted code to be clear and comprehensible to its Usenet |
+audience will be rewarded. But it is important to start any formatting |
+required with the actual code in use, rather than attempting to |
+re-type it, in order not to introduce errors that are not present in |
+the original and so have nothing to do with the original problem. |
+Having prepared the formatting of the code to suite Usenet it is |
+important to re-test it to ensure that it is still as functional, that |
+no errors have been introduced and that it still exhibits whatever |
+behaviour it was that motivated the post in the first place. |
+</p> |
+ |
+<h3 id="ps1LwQu">Line Wrapping in Quoted Material</h3> |
+ |
+<p id="ps1LwQu_1"> |
+If a news post has been wrapped at, say, 72 characters and it is |
+responded to then the indenting character used to mark quoted material |
+will add to the length of that line. Maybe pushing it over the length |
+at which the reply will be wrapped. The result, if posted without |
+adjustment, may look something like this:- |
+</p> |
+ |
+<pre id="ps1LwQu_ex1"> |
+An example OP wrote: |
+> A long line of text quoted from the previous post, that was wrapped |
+at |
+> 72 characters in that post but has been extended to 74 characters |
+long |
+> lines because of the addition of the indenting characters that mark |
+it |
+> as a quotation, but has been re-wrapped to 72 characters in the |
+posted |
+> follow-up that is quoting it. |
+ |
+The comment posted in response to the material quoted above. Originally |
+wrapped in the response at 72 characters. |
+</pre> |
+ |
+<p id="ps1LwQu_2"> |
+The effect is that the words "at", "long", |
+"it" and "posted" are no |
+longer marked as part of the quotation but instead appear to be badly |
+formatted and meaningless comments on that quoted material. Which has |
+itself gained the appearance of being incompetently trimmed. The effect |
+escalates with additional responses, loosing more meaning and becoming |
+less and less clear as to whom any particular part of the text is |
+attributable. |
+</p> |
+ |
+<pre id="ps1LwQu_ex2"> |
+The First Responder wrote: |
+> An example OP wrote: |
+>> The First Responder wrote: |
+>>> An example OP wrote: |
+>>>> A long line of text quoted from the previous post, that was |
+wrapped |
+>>> at |
+>>>> 72 characters in that post but has been extended to 74 characters |
+>>> long |
+>>>> lines because of the addition of the indenting characters that |
+mark |
+>>> it |
+>>>> as a quotation, but has been re-wrapped to 72 characters in the |
+>>> posted |
+>>>> follow-up that is quoting it. |
+>>> |
+>>> The comment posted in response to the material quoted above. |
+>> Originally |
+>>> wrapped in the response at 72 characters. |
+> |
+>> This response is the OP's reply to the comments on the original |
+>> post. It quoted the previous posts in full and was wrapped at 72 |
+>> characters. |
+> |
+>And the original responder added this. |
+ |
+The conversation ended with the OP thanking the responder for their |
+comments. (but who said what?) |
+</pre> |
+ |
+<p id="ps1LwQu_3"> |
+The solution is to be aware that this may happen and re-wrap that |
+quoted material so that it is not effected by the automatic line |
+wrapping when a post is sent, or to increase the wrapping margins by |
+the number of characters inserted to mark a quotation (so long as the |
+result does not exceed 80 characters). Some newsreader software can |
+handle this automatically, and add on software exists for other |
+products (such as OE), but ultimately the responsibility for properly |
+marking and attributing quoted material belongs with the individual |
+making the post. |
+</p> |
+ |
+<p id="ps1LwQu_4"> |
+If the two had taken the effect of the progressive lengthening of lines |
+in quoted material into account the result would have looked like |
+this:- |
+</p> |
+ |
+<pre id="ps1LwQu_ex3"> |
+The First Responder wrote: |
+> An example OP wrote: |
+>> The First Responder wrote: |
+>>> An example OP wrote: |
+>>>> A long line of text quoted from the previous post, that was |
+>>>> wrapped at 72 characters in that post but has been extended to 74 |
+>>>> characters long lines because of the addition of the indenting |
+>>>> characters that mark it as a quotation, but has been re-wrapped to |
+>>>> 72 characters in the posted follow-up that is quoting it. |
+>>> |
+>>> The comment posted in response to the material quoted above. |
+>>> Originally wrapped in the response at 72 characters. |
+> |
+>> This response is the OP's reply to the comments on the original |
+>> post. It quoted the previous posts in full and was wrapped at 72 |
+>> characters. |
+> |
+>And the original responder added this. |
+ |
+The conversation ended with the OP thanking the responder for their |
+comments. |
+</pre> |
+ |
+<p id="ps1LwQu_5"> |
+It would have been clear form the number of quote indicating characters |
+who exactly had said what and the quoted material would have been |
+easier to read and understand. Though in practice there probably should |
+have been much more trimming along the way as the whole conversation |
+would probably not have been needed to show the context of each |
+response. |
+</p> |
+ |
+ |
+<h2 id="ps1Code">General Code Postings, and when to use a URL</h2> |
+ |
+<p id="ps1Code_1"> |
+Often a question cannot usefully be answered without being accompanied |
+with javascript source code. Even a very detailed explanation of a |
+process will not tend to narrow the possibilities down to just one |
+method, and deciding whether a reported effect is due to a |
+characteristic of an execution environment or code that is taking the |
+wrong approach cannot be done without seeing the source code. |
+</p> |
+ |
+<p id="ps1Code_2"> |
+In some cases small snippets of code, say an individual function's |
+definition, might be sufficient. Though it is usually necessary to know |
+how such a function is being called and what arguments it is using. But |
+ideally questions should be accompanied by an easily testable example |
+that demonstrates the characteristics that provoked the question. |
+</p> |
+ |
+<p id="ps1Code_3"> |
+Easily testable because there is no better aid to debugging than being |
+able to reproduce a problem. Time spent turning a snippet of code into |
+testable web page (or whatever) is not rewarded if the results do not |
+exhibit the problem described. And asking many people to repeat that |
+process when it could have been done by the questioner once, in a way |
+that guaranteed a demonstration of the problem, is not a good use of |
+the group or the time of its participants. |
+</p> |
+ |
+<p id="ps1Code_4"> |
+However, posting the entire source code of a web page that happens to |
+include the problematic script is rarely the answer. For one thing web |
+pages often import <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span>, other script files and graphics (the latter |
+simply could not be posted to the group). But web pages also often |
+consist of large amounts of <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span>, which would require careful |
+re-wrapping to fit within the posting margins and be left correct, and |
+much of the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> would be irrelevant to the post. |
+</p> |
+ |
+<p id="ps1Code_5"> |
+There is also the question of bandwidth in transmission and capacity in |
+storage. Every post is stored, at least for a time, on every news server |
+carrying the group world wide and usually also on the hard disk of |
+everyone who reads the group. And to get from server to server, and |
+eventually to the many readers, it must be transmitted, consuming |
+bandwidth related to the size of the post. The more irrelevant |
+information that any post contains the more those resources are wasted |
+(this is also a reason for appropriate trimming of quoted material). |
+</p> |
+ |
+<p id="ps1Code_6"> |
+The comp.lang.javascript FAQ makes the injunction that posting code of |
+more than 500 lines is unacceptable. That is the theoretical upper |
+limit that should never be exceeded, but a post of even half that |
+length would have to be exceptional. |
+</p> |
+ |
+<p id="ps1Code_7"> |
+The easiest way of demonstrating a problem in context without posting |
+excessive amounts of code and <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> is to make a page that exhibits the |
+problem available online and post the URL of that page along with the |
+question. Possibly accompanied by a snippet of the code highlighting |
+the suspected cause. |
+</p> |
+ |
+<p id="ps1Code_8"> |
+The circumstances under which making a page that demonstrates the |
+problem available online is advisable are, whenever that page is |
+interacting within a frameset, or whenever images play a significant |
+part in a problem. As those circumstances are time consuming to |
+reproduce from posted code and cannot always be recreated for testing. |
+But any request to have people examine excessive amounts of code |
+and/or <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> should also be made available on line instead of in a post. |
+</p> |
+ |
+<p id="ps1Code_9"> |
+Unfortunately not all participants in the group are viewing Usenet in a |
+way that makes easily following a URL to an example page viable. Often |
+downloading new Usenet posts as a batch and then viewing them off line. |
+Re-connecting to view an example page is not always desirable (due to |
+local conditions, slow modem connections and potential associated |
+expense) and can be unrewarding if the page viewed is a mush of <abbr title="What You See Is What You Get">WYSIWYG</abbr> |
+generated bloated <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span>-like noise. Where it takes a considerable time |
+to even locate the cause of what may still turn out to be a trivial |
+problem. |
+</p> |
+ |
+<p id="ps1Code_10"> |
+Then again there are people using the group who much prefer examples to |
+be available online. Either way what is not wanted is for questions to |
+be asked without making the corresponding code available in some way, |
+or the posting of excessive amounts of code. |
+</p> |
+ |
+<p id="ps1Code_11"> |
+A good compromise, and a valuable debugging technique, is the creation |
+of a demonstration test-case page. A page containing no more than |
+sufficient <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> and javascript to allow others to reproduce the problem |
+and see the relevant code without anything extraneous. Such a test-case |
+page would almost always be short enough to post with the question |
+(properly formatted) and could additionally be made available online for |
+the convenience of those that would prefer to use a URL to load it |
+directly into a browser for testing. |
+</p> |
+ |
+<p id="ps1Code_12"> |
+Creating such a test-case page can be valuable in itself as attempting |
+to reduce a problem from a larger context to an isolated demonstration |
+will often reveal the cause of that problem along the way. The act of |
+cutting out what initially seems irrelevant often reveals that the |
+problem in fact results form an unexpected interaction with something |
+that was assumed to be unconnected. And if the problem can be |
+demonstrated in isolation then it is relatively easy for readers of the |
+question to reproduce the problem and identify its cause, resulting in |
+less discussion of superfluous issues and usually a quicker resolution |
+of the question. |
+</p> |
+ |
+<p id="ps1Code_13"> |
+It is very important to test test-case pages prior to posting them to |
+ensure that they do indeed exhibit the characteristic that motivated |
+the question. At least if you want to be taken seriously in future. And |
+when such a test-case is posted to the group it should be formatted and |
+indented to facilitate the essayist reading of the code and testing by |
+no more than copying the page into a text editor and saving it locally |
+as a <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> file. |
+</p> |
+ |
+ |
+<h2 id="ps1Quest">Well Asked Questions Get the Best Answers</h2> |
+ |
+<p id="ps1Quest_1"> |
+Beyond any considerations of posting style and formatting, the quality |
+of questions asked has a considerable impact upon the number and |
+quality of answers given, and the time taken to elicit a useful |
+response. Vague questions are likely to be answered with requests for |
+clarification. Terse general questions are likely to elicit yes or no |
+answers (often both). And questions that have been asked, and well |
+answered, before (especially frequently or in the recent past) are as |
+likely as not to be ignored. |
+</p> |
+ |
+<p id="ps1Quest_2"> |
+When asking a question it would almost always be a good idea to put |
+yourself in the position of the reader of the question, read it back to |
+yourself and ask yourself; Does this question actually ask what I |
+want to know, and is it sufficiently clear and detailed to elicit that |
+answer? |
+</p> |
+ |
+<p id="ps1Quest_3"> |
+The following is a short list of recurring features of badly asked |
+questions:- |
+</p> |
+ |
+ |
+<h3 id="ps1QSub">Appropriate Use of the Subject Header</h3> |
+ |
+<p id="ps1QSub_1"> |
+Another Usenet convention holds that the Subject header should not be |
+expected to be available to a reader of any message. While it is |
+unlikely that there are any newsreaders currently in use in which the |
+user is not presented with the Subject header, it remains |
+inappropriate to ask a question in the subject header (or to assume |
+that its contents will provide supplementary information about a |
+question) and doing so is as likely to invoke a lesson in Usenet |
+etiquette as an answer to the question. But a question is not really |
+a subject anyway. The subject should describe what the question is |
+in relation to, and is useful for archive searching and |
+categorisation rather than as a means of communication. |
+</p> |
+ |
+<p id="ps1QSub_2"> |
+Any question asked should always appear in the body of the post, and in |
+a form that does not assume the availability of the Subject header to |
+the reader. |
+</p> |
+ |
+<p id="ps1QSub_3"> |
+The Subject header should also not be wasted. Placing "please |
+help" and the like in the subject header is unwelcome and |
+counterproductive. Take the opportunity to construct a Subject |
+header that states the type of the problem, what it relates to. |
+Subject headers that state the real subject will attract the |
+attention of people with a special interest in that subject, |
+exactly those people best able to offer help. |
+</p> |
+ |
+<h3 id="ps1QRes">Doing Your Own Research</h3> |
+ |
+<p id="ps1QRes_1"> |
+Many questions, at least the questions literally asked, could quickly |
+be answered with a little research, and the chances are that regulars |
+on the group know how easily those answers could have been found with |
+a little effort. The group is not intended to be a vending machine for |
+trivial information about javascript, that wouldn't be an interesting |
+group to participate in. |
+</p> |
+ |
+<p id="ps1QRes_2"> |
+On the other hand, evidence that some effort has been put into |
+researching a problem before asking a question tends to be looked upon |
+kindly (though claiming to have exhausted all lines of research when that |
+is obviously not the case would have the opposite effect). |
+</p> |
+ |
+<p id="ps1QRes_3"> |
+The obvious first place to look for answers is in |
+<a href="../clj_faq.html">the group's FAQ</a>. That will |
+mean reading all of the FAQ because the answers to some problems (or |
+sufficient clues to those answers) will be found within the answers to |
+seemingly unrelated questions, or the resources linked to from the FAQ. |
+That in itself is a fairly big task, but if not undertaken will just |
+result in questions being answered with references back to the FAQ. |
+There is also a Usenet convention that whenever a newsgroup |
+(particularly technical groups) provides a FAQ resource, that FQA should |
+be read by anyone wishing to post to the group <em>prior</em> to making |
+their first post. So reading the FAQ is <em>not optional</em> anyway. |
+</p> |
+ |
+<p id="ps1QRes_4"> |
+The Internet provides a massive resource for researching virtually any |
+question, and particularly questions relating to computing. Search |
+engines are the primary research tool and among those Google search is |
+extremely useful. But when a question relates to javascript in a way |
+that indicates that it may be suitable to be asked on |
+comp.lang.javascript the best place to research the question is |
+<a href="http://groups.google.com/groups?q=comp.lang.javascript"> |
+groups.google.com</a>, as that resource holds a searchable archive of |
+almost all postings ever made to the group. There is an |
+<a href="http://groups.google.com/advanced_group_search?group=comp.lang.javascript"> |
+"Advanced Search" page</a>, where entering |
+"comp.lang.javascript" in the Newsgroup field and suitable keywords |
+in the other fields provided will return all messages posted to the group |
+that match the search criteria. As most questions will have been asked |
+before many answers can be obtained from the groups.google.com archives. |
+But be aware of the date of posts found as the archive goes back to |
+1996 and some things have changed over the intervening years. |
+</p> |
+ |
+<p id="ps1QRes_5"> |
+Reading back over recent posts to the group, for a minimum of a week |
+and preferably more than a month will avoid the need to re-ask a |
+question that has been asked and answered in recent memory. Not all |
+news servers will hold all messages over that period so |
+<a href="http://groups.google.com/groups?q=comp.lang.javascript"> |
+the group archives at groups.google.com</a> can be useful in this |
+respect also. |
+</p> |
+ |
+<h3 id="ps1DontWork">"It doesn't work"</h3> |
+ |
+<p id="ps1DontWork_1"> |
+People don't tend to question code that |
+does exactly what they want it to do. Sometimes they may ask how it |
+does exactly what they want but generally it is superfluous to state |
+that code that does not address a situation doesn't work. |
+</p> |
+ |
+<p id="ps1DontWork_2"> |
+To start with computer code always does exactly what is asked of it, |
+that is the nature of computers. So it does "work", it is |
+just that it doesn't do what is wanted of it. And that is a problem |
+because code that does not do something that is wanted of it cannot |
+itself explain what that something was. |
+</p> |
+ |
+<p id="ps1DontWork_3"> |
+It is the task of a human designer to decide what is wanted form code, |
+to specify the task. The reader of a question can do no more than |
+guess as to the task unless the questioner explains the specification |
+for the code, and that specification needs to be specific. That |
+information is needed when assessing what would qualify as |
+"works" in the context of the question. |
+</p> |
+ |
+<p id="ps1DontWork_4"> |
+But in addition to knowing what would qualify as working it is also |
+necessary to know in what way code is failing to work. There is a big |
+difference between code that appears to do nothing when executed, code |
+that does something undesirable in addition to what is expected of it |
+and code that does something else entirely. |
+</p> |
+ |
+<p id="ps1DontWork_5"> |
+Instead of stating the self-evident "It doesn't work", the |
+posters of questions should attempt to provide answers to:- |
+</p> |
+ |
+<dl id="ps1DontWork_df"> |
+ <dt id="ps1DontWork_p1">1. What you have done?</dt> |
+ |
+ <dd id="ps1DontWork_d1">Providing access the code (possibly in the form of a test |
+ case), explaining the steps required to initiate the |
+ undesirable effect and the environments (usually web |
+ browsers) where the problem has been observed, so that it |
+ can be reproduced and tested. |
+ <dd> |
+ |
+ <dt id="ps1DontWork_p2">2. What you expected to happen?</dt> |
+ |
+ <dd id="ps1DontWork_d2">Both specifically in the case of the code under discussion and |
+ generally with regard to the design specification. |
+ <dd> |
+ |
+ <dt id="ps1DontWork_p3">3. What really happened?</dt> |
+ |
+ <dd id="ps1DontWork_d3">What was observed to happen and any error messaged generated. |
+ So that when (and if) the problem is reproduced in testing it |
+ is possible to identify it as the effect under discussion. |
+ <dd> |
+</dl> |
+ |
+<h3 id="ps1CntX">Explain the Whole Context</h3> |
+ |
+<p id="ps1CntX_1"> |
+The context in which a question is asked or a problem exists is very |
+important to the type of answers given or solutions proposed. Beyond |
+the obvious required details such as the execution host(s), scripts |
+used and how they are used, There are details like whether a project |
+is for the Internet or an Intranet. Because on comp.lang.javascript |
+the default assumption is that the context will be browser scripting |
+for the Internet, many approaches/solutions are ruled out, but some may |
+be completely reasonable and practical in the more restricted context |
+of a company Intranet (or on more controlled hosts such as the windows |
+scripting host or server-side javascript). |
+</p> |
+ |
+<p id="ps1CntX_2"> |
+There have been many occasions where many answers to questions have |
+stressed the unsuitability of particular approaches to use on the |
+Internet only for the original questioner to respond by explaining |
+that they don't apply because their context is an Intranet. That |
+wastes the time of everyone who composed a response to the original |
+question; if they had been in possession of the real context from the |
+outset they could have got on with proposing/discussing solutions that |
+were appropriate, or moved on to something more interesting. |
+</p> |
+ |
+<p id="ps1CntX_3"> |
+But the full context of a question goes beyond such details and answers |
+the question: why? Often a question will be asking about a particular |
+approach that, to the questioner, is a perceived solution to a problem. |
+The answer to the question why would explain what that problem is, and |
+knowing what that problem is will allow respondents to assess the |
+suitability of the approach at addressing the problem and possibly |
+suggest other, and superior, solutions. There is very little that is |
+genuinely new and unique, whatever the wider problem is the chances are |
+that someone will be familiar with it and be in a position to identify |
+the best solution (even if that is just confirming that the proposed |
+solution is the best available). Questions raised on the group should |
+always include the answer to the question: why? |
+</p> |
+ |
+<h3 id="ps1PR">Proof-Read your Questions</h3> |
+ |
+<p id="ps1PR_1"> |
+Proof-read your message two or three times before posting. Ensure that |
+it is as error free as possible and does convey the question and |
+provide all of the necessary information in a way that will not be |
+subject to misinterpretation. |
+</p> |
+ |
+<!-- <h2><a name="ps1notHD" id="ps1notHD">comp.lang.javascript is Not a Helpdesk</a></h2> |
+ |
+<p id="ps1notHD_1"> |
+The comp.lang.javascript newsgroup is a discussion forum on the subject |
+of ECMAScript (javascript). It is not a helpdesk and its participants |
+make their contributions voluntarily in their own time and with their |
+own resources for whatever reasons they see fit. Just because the |
+majority of the discussion starts with someone posting a question, |
+often asking for help with some aspect of javascript, does not mean |
+that anyone should have any expectation of receiving any help or |
+assistance from any ensuing discussion. So, although help and |
+assistance is often (if not usually) offered during the following |
+discussion, that is just a positive side effect of the group and not |
+its reason for existing. |
+</p> |
+ |
+<p id="ps1notHD_2"> |
+The real benefit of the group goes to its regular participants, who, |
+in participating in the discussion, attempting to address the diverse |
+situations and problems raised and exposing their code to critical |
+public scrutiny, get to hone their code authoring and script design |
+skills and knowledge with the active assistance and critical feed-back |
+of their peers. |
+</p> |
+ |
+<p id="ps1notHD_3"> |
+The whole process would not work as well if people did not post |
+questions relating to a diversity of problem situations to the group |
+in the hope of getting some assistance, and people would never do that |
+if there were not a good chance of actually getting assistance. But the |
+people posting such questions need to remember that they have no right |
+to assistance, and cannot demand, or even expect it. Instead, wanting |
+to take advantage of the potentially beneficial side effect of the |
+existence of the group, they should encourage the group to give them |
+assistance, by making doing so as easy and convenient as possible. The |
+preceding document is intended to make it as clear as possible how to |
+go about achieving that aim. |
+</p> --> |
+ |
+<h2 id="ps1AddR">Additional Reading</h2> |
+ |
+<ul class="resourceList" id="ps1AddR_l"> |
+ <li><a href="http://www.cs.tut.fi/~jkorpela/usenet/dont.html">The seven don'ts of Usenet<br>http://www.cs.tut.fi/~jkorpela/usenet/dont.html</a></li> |
+ <li><a href="http://oakroadsystems.com/genl/unice.htm">Playing Nice on Usenet<br>http://oakroadsystems.com/genl/unice.htm</a></li> |
+ <li><a href="http://www.netmeister.org/news/learn2quote2.html">How do I quote correctly in Usenet? - Quoting and Answering<br>http://www.netmeister.org/news/learn2quote2.html</a></li> |
+ <li><a href="http://www.xs4all.nl/%7ewijnands/nnq/nquote.html">Quoting Style in Newsgroup Postings<br>http://www.xs4all.nl/%7ewijnands/nnq/nquote.html </a></li> |
+ <li><a href="http://www.cs.tut.fi/~jkorpela/usenet/xpost.html">Why and how to crosspost<br>http://www.cs.tut.fi/~jkorpela/usenet/xpost.html</a></li> |
+ <li><a href="http://kb.indiana.edu/data/affn.html?cust=12244">How can I post a message to more than one Usenet newsgroup?<br>http://kb.indiana.edu/data/affn.html?cust=12244</a></li> |
+ <li><a href="http://catb.org/%7Eesr/faqs/smart-questions.html">How To Ask Questions The Smart Way<br>http://catb.org/%7Eesr/faqs/smart-questions.html</a></li> |
+ <li><a href="http://www.chiark.greenend.org.uk/~sgtatham/bugs.html">How to Report Bugs Effectively<br>http://www.chiark.greenend.org.uk/~sgtatham/bugs.html</a></li> |
+</ul> |
+</body> |
+</html> |
/cljs/faq_notes/clj_posts.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/faq_notes/type_convert.html |
=================================================================== |
--- cljs/faq_notes/type_convert.html (nonexistent) |
+++ cljs/faq_notes/type_convert.html (revision 2) |
@@ -0,0 +1,1319 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" |
+"http://www.w3.org/TR/html4/strict.dtd"> |
+<html lang="en"> |
+<head> |
+ <title>Javascript Type-Conversion</title> |
+ <meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> |
+<link href="../../faq.css" rel="stylesheet" type="text/css"> |
+<link href="../notes.css" rel="stylesheet" type="text/css"> |
+<style type="text/css"> |
+td { |
+ text-align:center; |
+} |
+pre.st { |
+ background-color:#EEEEFF; |
+ margin:0px; |
+ padding:0px; |
+ text-align:left; |
+ border:0px none #EEEEFF; |
+} |
+caption { |
+ font-weight:bold; |
+} |
+th, td { |
+ vertical-align:baseline; |
+ background-color:#EEEEFF; |
+ color:#000000; |
+ white-space:nowrap; |
+ padding:2px |
+} |
+.true { |
+ color:#003444; |
+ background-color:#E0FFE0; |
+} |
+.false { |
+ color:#003444; |
+ background-color:#FFE0E0; |
+} |
+table { |
+ margin:1em 2.5em; |
+} |
+ </style> |
+ </head> |
+ <body> |
+ |
+<h1>Javascript Type-Conversion</h1> |
+<div id="faqNav"> |
+ <a href="/faq/">FAQ</a> > <a href="/faq/notes/">FAQ Notes</a> |
+</div> |
+ |
+<ul> |
+ <li><a href="#tcInt">Introduction</a></li> |
+ <li><a href="#tcBool">Converting to Boolean</a></li> |
+ <li><a href="#tcString">Converting to String</a></li> |
+ <li><a href="#tcNumber">Converting to Number</a></li> |
+ <li><a href="#tcParse">Parsing to Number</a> |
+ <ul> |
+ <li><a href="#tcParseFl">parseFloat</a></li> |
+ <li><a href="#tcParseIn">parseInt</a></li> |
+ <li><a href="#tcPrIntRx">parseInt with a radix argument</a></li> |
+ </ul> |
+ </li> |
+ <li><a href="#tcToInt32">ToInt32</a></li> |
+ <li><a href="#tcUserIn">Converting User Input</a> |
+ <ul> |
+ <li><a href="#tcRegEx">Regular expression examples</a></li> |
+ </ul> |
+ </li> |
+</ul> |
+ |
+<h2 id="tcInt">Introduction</h2> |
+ |
+<p id="tcInt_1"> |
+Javascript (ECMAScript) is a loosely typed language. That does not mean |
+that it has no data types just that the value of a variable or a Javascript |
+object property does not need to have a particular type of value assigned |
+to it, or that it should always hold the same type of value. Javascript |
+also freely type-converts values into a type suitable for (or required by) |
+the context of their use. |
+</p> |
+ |
+<p id="tcInt_2"> |
+Javascript being loosely typed and willing to type-convert still does not |
+save the programmer from needing to think about the actual type of values |
+that they are dealing with. A very common error in browser scripting, for |
+example, is to read the value property of a form control into which the |
+user is expected to type a number and then add that value to another |
+number. Because the value properties of form controls are strings (even if |
+the character sequence they contain represents a number) the attempt to |
+add that string to a value, even if that value happens to be a number, |
+results in the second value being type-converted into a string and |
+concatenated to the end of the first string value from the from control. |
+</p> |
+ |
+<p id="tcInt_3"> |
+That problem arises from the dual nature of the <code>+</code> operator |
+used for both numeric addition and string concatenation. With which the |
+nature of the operation performed is determined by the context, where |
+only if both operands are numbers to start with will the <code>+</code> |
+operator perform addition. Otherwise it converts all of its operands to |
+strings and does concatenation. |
+</p> |
+ |
+<p id="tcInt_4"> |
+The following discussion is illustrated with Javascript generated tables |
+of values resulting from the conversion operations. The headers of those |
+tables display the values as represented in the Javascript source code |
+used rather than their internal representation. So, for example |
+<code>123e-2</code> as a number was the character sequence typed into |
+the source code, the interpreter reads that and generates the |
+number value 1.23 from it for internal use. The various values used for |
+the tests have been chosen to illustrate aspects of type |
+converting, those aspects may not apply to all of the tables presented. |
+However, all of the test values are included in all of the tables (except |
+where no type converting occurs) for full comparison. The bodies of the |
+tables list the results of the various type conversion operations. |
+</p> |
+ |
+<p id="tcInt_5"> |
+If you are accepting/using this page's <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> style suggestions the type |
+of the values at various stages is illustrated by the colour of the text |
+used. The following key shows those type/colour relationships, they are |
+derived from the string values returned by the <code>typeof</code> |
+operator (which returns <code>"object"</code> |
+for the <code>null</code> type when in reality <code>null</code> is |
+distinct from objects). |
+</p> |
+ |
+<table id="tcInt_key"> |
+ <tbody> |
+ <tr><th>Key</th></tr> |
+ <tr><td class="st">string</td></tr> |
+ <tr><td class="nm">number</td></tr> |
+ <tr><td class="bl">boolean</td></tr> |
+ <tr><td class="ob">object</td></tr> |
+ <tr><td class="fn" style="text-align:center;">function</td></tr> |
+ <tr><td class="ob">null</td></tr> |
+ <tr><td class="un">undefined</td></tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcInt_6"> |
+The boolean values of results also have a coloured background to highlight |
+ <code>true</code> or <code>false</code>. |
+</p> |
+ |
+<h2 id="tcBool">Converting to Boolean</h2> |
+ |
+<p id="tcBool_1"> |
+When evaluating the expression of an <code>if</code> statement the Javascript |
+interpreter will type-convert the result of that expression to boolean |
+in order to make its decision. Also various operators internally |
+type-convert their operands to boolean in order to determine what |
+action to take. These include the logical operators like AND |
+(<code>&&</code>), OR (<code>||</code>) and NOT (<code>!</code>). The NOT |
+operator type-converts its operand to boolean and if that value is |
+boolean true it returns false and if false it returns true. As the |
+result of a NOT operation is a boolean value that is the inverse of |
+the type-converted true-ness of its operand, two NOT operations |
+together will return a boolean value that is equivalent to the result |
+of type-converting the operand to boolean:- |
+</p> |
+ |
+<pre id="tcBool_ex1"> |
+var boolValue = !!x; |
+</pre> |
+ |
+<p id="tcBool_2"> |
+That technique has been used to generate the following tables. |
+</p> |
+ |
+<p id="tcBool_3"> |
+An alternative method of generating a boolean value that represents |
+the type-converted true-ness of a value is to pass that value to |
+the <code>Boolean</code> constructor called as a function:- |
+</p> |
+ |
+<pre id="tcBool_ex2"> |
+var boolValue = Boolean(x); |
+</pre> |
+ |
+<table> |
+ <caption>Double NOT (!!col) : Numeric Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="nm">-1.6</th> |
+ <th class="nm">-0</th> |
+ <th class="nm">+0</th> |
+ <th class="nm">1</th> |
+ <th class="nm">1.6</th> |
+ <th class="nm">8</th> |
+ <th class="nm">16</th> |
+ <th class="nm">16.8</th> |
+ <th class="nm">123e-2</th> |
+ <th class="nm">-Infinity</th> |
+ <th class="nm">+Infinity</th> |
+ <th class="nm">NaN</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>!!col</th> |
+ <td class="true">true</td> |
+ <td class="false">false</td> |
+ <td class="false">false</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="false">false</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcBool_4"> |
+When numbers are converted to boolean, zero becomes false and all other |
+numbers are true. With the excepting of the special numeric value |
+<code>NaN</code> (Not a Number) which is used when another type is |
+converted to a number but that conversion does not result in a |
+meaningful number. <code>NaN</code> is always false. The values of |
+positive and negative infinity, while not finite numbers, are non-zero |
+numeric values and always type-convert to boolean <code>true</code>. |
+</p> |
+ |
+<table> |
+ <caption>Double NOT (!!col) : String Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="st">""<br>(empty<br>string)</th> |
+ <th class="st">"-1.6"</th> |
+ <th class="st">"0"</th> |
+ <th class="st">"1"</th> |
+ <th class="st">"1.6"</th> |
+ <th class="st">"8"</th> |
+ <th class="st">"16"</th> |
+ <th class="st">"16.8"</th> |
+ <th class="st">"123e-2"</th> |
+ <th class="st">"010"<br>(Octal)</th> |
+ <th class="st">"0x10"<br>(Hex)</th> |
+ <th class="st">"0xFF"<br>(Hex)</th> |
+ <th class="st">"-010"</th> |
+ <th class="st">"-0x10"</th> |
+ <th class="st">"xx"</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>!!col</th> |
+ <td class="false">false</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcBool_5"> |
+Type conversion rules are even simpler for string to boolean conversion |
+as all non-empty strings always become true and empty strings become |
+false. |
+</p> |
+ |
+<table> |
+ <caption>Double NOT (!!col) : Other Values</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="un">undefined</th> |
+ <th class="ob">null</th> |
+ <th class="bl">true</th> |
+ <th class="bl">false</th> |
+ <th class="ob">new Object()</th> |
+ <th class="fn">function(){<br> return;<br>}</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>!!col</th> |
+ <td class="false">false</td> |
+ <td class="false">false</td> |
+ <td class="true">true</td> |
+ <td class="false">false</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcBool_6"> |
+For the other types, <code>undefined</code> and <code>null</code> are |
+converted to false, boolean values are not converted and objects and |
+functions are always true. |
+</p> |
+ |
+<p id="tcBool_7"> |
+This is the most valuable aspect of type-converting to boolean as it |
+allows a script to distinguish between properties in an environment |
+that may be undefined or may refer to an object. Treating an undefined |
+(or null) value as if it was an object will produce errors. So when |
+there is a doubt (as there usually is where web browsers are concerned) |
+then code can avoid generating errors by wrapping the code that wants |
+to access an object in an <code>if</code> test. Supplying the suspect |
+reference to the object as the expression. The expression will be type |
+converted to boolean and result in <code>false</code> if the object |
+does not exist and <code>true</code> if it does. |
+</p> |
+ |
+<pre id="tcBool_ex3"> |
+if(document.documentElement){ |
+ scrollX = document.documentElement.scrollLeft; |
+} |
+</pre> |
+ |
+<p id="tcBool_8"> |
+The double NOT operation also allows the setting of boolean flags that |
+can be used to indicate the presence of various objects:- |
+</p> |
+ |
+<pre id="tcBool_ex4"> |
+var hasDocEl = !!document.documentElement; |
+... |
+if(hasDocEl){ |
+ scrollX = document.documentElement.scrollLeft; |
+} |
+</pre> |
+ |
+<h2 id="tcString">Converting to String</h2> |
+ |
+<p id="tcString_1"> |
+As mentioned above, type conversion to a string most often results |
+from the action of the + operator whenever one of its operators in |
+not a number. The easiest way of getting the string that results |
+from type-conversion is to concatenate a value to an empty string. |
+That technique has been used to generate the following tables. |
+</p> |
+ |
+<p id="tcString_2"> |
+An alternative method of converting a value into a string is to |
+pass it as an argument to the <code>String</code> constructor |
+called as a function:- |
+</p> |
+ |
+<pre id="tcString_ex1"> |
+var stringValue = String(x); |
+</pre> |
+ |
+<table> |
+ <caption>type-convert to string ("" + col) : Numeric Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="nm">-1.6</th> |
+ <th class="nm">-0</th> |
+ <th class="nm">+0</th> |
+ <th class="nm">1</th> |
+ <th class="nm">1.6</th> |
+ <th class="nm">8</th> |
+ <th class="nm">16</th> |
+ <th class="nm">16.8</th> |
+ <th class="nm">123e-2</th> |
+ <th class="nm">-Infinity</th> |
+ <th class="nm">+Infinity</th> |
+ <th class="nm">NaN</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>"" + col</th> |
+ <td class="st">-1.6</td> |
+ <td class="st">0</td> |
+ <td class="st">0</td> |
+ <td class="st">1</td> |
+ <td class="st">1.6</td> |
+ <td class="st">8</td> |
+ <td class="st">16</td> |
+ <td class="st">16.8</td> |
+ <td class="st">1.23</td> |
+ <td class="st">-Infinity</td> |
+ <td class="st">Infinity</td> |
+ <td class="st">NaN</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcString_3"> |
+Notice that the number generated from the source code <code>123e-2</code> |
+has resulted in the string <code>"1.23"</code> because that is |
+the string representation of the internal number created from the source |
+code. However, Javascript's internal number representations take the form |
+of IEEE double precision floating point numbers and that means that they |
+cannot represent all numbers with precision. The results of mathematical |
+operations may only produce close approximations and when they are |
+converted to strings the string represents the approximation and may be |
+unexpected and undesirable. It is often necessary to use custom functions |
+to generate string representations of numbers in an acceptable format, |
+the type-conversion mechanism is rarely suited to generating numeric output |
+intended for presentation. |
+</p> |
+ |
+<table> |
+ <caption>type-convert to string ("" + col) : Other Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="un">undefined</th> |
+ <th class="ob">null</th> |
+ <th class="bl">true</th> |
+ <th class="bl">false</th> |
+ <th class="ob">new Object()</th> |
+ <th class="fn">function(){<br> return;<br>}</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>"" + col</th> |
+ <td class="st">undefined</td> |
+ <td class="st">null</td> |
+ <td class="st">true</td> |
+ <td class="st">false</td> |
+ <td class="st">[object Object]</td> |
+ <td><pre class="st">function(){ |
+ return; |
+}</pre></td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcString_4"> |
+When objects or functions are type-converted to strings their |
+<code>toString</code> method is called. These default to |
+<code>Object.prototype.toString</code> and |
+<code>Function.prototype.toString</code> but may be overloaded |
+with a function assigned to a "toString" property of |
+the object/function. Type-converting a function to a string does |
+not necessarily result in the function's source code. The behaviour |
+of <code>Function.prototype.toString</code> is implementation |
+depended and varies quite a lot, as do the results from |
+"host objects" and methods (the objects and methods |
+provided by the environment, such as DOM elements). |
+</p> |
+ |
+<h2 id="tcNumber">Converting to Number</h2> |
+ |
+<p id="tcNumber_1"> |
+Converting values to numbers, especially strings to numbers, is an |
+extremely common requirement and many methods can be used. Any |
+mathematical operator except the concatenation/addition operator |
+will force type-conversion. So conversion of a string to a number |
+might entail performing a mathematical operation on the string |
+representation of the number that would not affect the resulting |
+number, such as subtracting zero or multiplying by one. |
+</p> |
+ |
+<pre id="tcNumber_ex1"> |
+var numValue = stringValue - 0; |
+<span class="commentJS">/* or */</span> |
+var numValue = stringValue * 1; |
+<span class="commentJS">/* or */</span> |
+var numValue = stringValue / 1; |
+</pre> |
+ |
+<p id="tcNumber_2"> |
+However, the unary <code>+</code> operator also type-converts its |
+operand to a number and because it does not do any additional |
+mathematical operations it is the fastest method for type-converting |
+a string into a number. |
+</p> |
+ |
+<p id="tcNumber_2b"> |
+Incidentally, the unary <code>-</code> (minus) operator also |
+type-converts its operand (if necessary) in addition to |
+subsequently negating its value. |
+</p> |
+ |
+<pre id="tcNumber_ex2"> |
+var numValue = (+stringValue); |
+ |
+<span class="commentJS">/* The preceding unary + expression has been parenthesised. That is |
+ unnecessary but is often felt to make the code easier to comprehend |
+ and make it clear which operations are being applied. Especially |
+ avoiding confusion with pre and post increment and addition |
+ operations. Compare:- |
+ |
+var n = anyNumVar++ + +stringVar + ++anotherNumVar; |
+ |
+ - with - |
+ |
+var n = (anyNumVar++) + (+stringVar) + (++anotherNumVar); |
+ ^^ ^ ^^ |
+ (post increment) + (unary plus) + (pre increment) |
+*/</span> |
+</pre> |
+ |
+<p id="tcNumber_3"> |
+While unary <code>+</code> is the fastest method for converting a |
+string to a number a final method is available that uses the |
+Javascript type-conversion algorithms. The <code>Number</code> |
+constructor can be called with the string value as its argument |
+and its return value is a number representing the result of the |
+type-conversion. |
+</p> |
+ |
+<pre id="tcNumber_ex3"> |
+var numValue = Number(stringValue); |
+</pre> |
+ |
+<p id="tcNumber_4"> |
+The Number constructor is the slowest of the type-converting |
+methods but when speed is not an overriding consideration its |
+use does produce the clearest source code. |
+</p> |
+ |
+<p id="tcNumber_5"> |
+The following tables show the results of type-conversion to a number using |
+the unary <code>+</code> operator. Though all of the preceding |
+alternative method produce the same results as they all use exactly the |
+same algorithm to do the conversion. |
+</p> |
+ |
+<table> |
+ <caption>type-convert to number (+col) : String Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="st">""<br>(empty<br>string)</th> |
+ <th class="st">"-1.6"</th> |
+ <th class="st">"0"</th> |
+ <th class="st">"1"</th> |
+ <th class="st">"1.6"</th> |
+ <th class="st">"8"</th> |
+ <th class="st">"16"</th> |
+ <th class="st">"16.8"</th> |
+ <th class="st">"123e-2"</th> |
+ <th class="st">"010"<br>(Octal)</th> |
+ <th class="st">"0x10"<br>(Hex)</th> |
+ <th class="st">"0xFF"<br>(Hex)</th> |
+ <th class="st">"-010"</th> |
+ <th class="st">"-0x10"</th> |
+ <th class="st">"xx"</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>+col</th> |
+ <td class="nm">0</td> |
+ <td class="nm">-1.6</td> |
+ <td class="nm">0</td> |
+ <td class="nm">1</td> |
+ <td class="nm">1.6</td> |
+ <td class="nm">8</td> |
+ <td class="nm">16</td> |
+ <td class="nm">16.8</td> |
+ <td class="nm">1.23</td> |
+ <td class="nm">10</td> |
+ <td class="nm">16</td> |
+ <td class="nm">255</td> |
+ <td class="nm">-10</td> |
+ <td class="nm">NaN</td> |
+ <td class="nm">NaN</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcNumber_6"> |
+The important considerations when converting strings to numbers with |
+the type-converting methods is the results from strings that do not |
+represent numbers. The empty string is converted into the number zero, |
+depending on the application this can be harmless or disastrous, but |
+it is important to be aware that it is going to happen. In other |
+contexts strings that follow the Javascript format for octal number |
+(leading zero) can be problematic but type conversion treats them |
+as base 10 anyway. However, strings that follow the format for |
+hexadecimal numbers (leading <code>0x</code> or <code>0X</code>) |
+are read as hexadecimal. Strings that cannot be read as a number |
+type-convert to <code>NaN</code>, which can be tested for with |
+the <code>isNaN</code> function. Strings representing numbers in an |
+exponential format (<code>"123e-2"</code>) are understood |
+along with leading minus signs. |
+</p> |
+ |
+<table> |
+ <caption>type-convert to number (+col) : Other Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="un">undefined</th> |
+ <th class="ob">null</th> |
+ <th class="bl">true</th> |
+ <th class="bl">false</th> |
+ <th class="ob">new Object()</th> |
+ <th class="fn">function(){<br> return;<br>}</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>+col</th> |
+ <td class="nm">NaN</td> |
+ <td class="nm">0</td> |
+ <td class="nm">1</td> |
+ <td class="nm">0</td> |
+ <td class="nm">NaN</td> |
+ <td class="nm">NaN</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcNumber_7"> |
+Objects and functions always type-convert to <code>NaN</code> numbers, as do |
+<code>undefined</code> values but it is worth noting that <code>null</code> |
+type-converts to zero. Probably because it is being type-converted to boolean |
+first and then to number and, as is clear from the boolean results |
+above, <code>null</code> would become boolean <code>false</code> which |
+would then become numeric zero. There is almost no need to type convert |
+these types of values into numbers. How they convert is only really |
+relevant to a consideration of the accidental result of converting a |
+value that is expected to be a string but actually turns out to be one |
+of these (and/or performing an mathematical operation with one of these as an operand). |
+</p> |
+ |
+<h2 id="tcParse">Parsing to Number</h2> |
+ |
+<p id="tcParse_1"> |
+An alternative method of converting a string into a number is to use |
+one of the global functions designed to parse a string and return a |
+number. The <code>parseFloat</code> function accepts a string argument |
+and returns a floating point number resulting from parsing that string. |
+Non-string arguments are first type-converted to a string as described |
+above. |
+</p> |
+ |
+<p id="tcParse_2"> |
+The string parsing functions read the string character by character until |
+they encounter a character that cannot be part of the number, at which |
+point they stop and return a number based on the characters that they |
+have seen that can be part of the number. This feature of their action |
+can be usefully exploited, for example, given a string representing a |
+<span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> length value such as <code>"34.5em"</code> |
+<code>parseFloat</code> would be able to ignore the <code>"em"</code> |
+because those characters cannot be combined with the preceding set to |
+produce a valid number. The returned number would be 34.5, the numeric |
+part of the <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> string stripped of its units. |
+</p> |
+ |
+<h3 id="tcParseFl">parseFloat</h3> |
+ |
+<table> |
+ <caption>parseFloat(col) : String Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="st">""<br>(empty<br>string)</th> |
+ <th class="st">"-1.6"</th> |
+ <th class="st">"0"</th> |
+ <th class="st">"1"</th> |
+ <th class="st">"1.6"</th> |
+ <th class="st">"8"</th> |
+ <th class="st">"16"</th> |
+ <th class="st">"16.8"</th> |
+ <th class="st">"123e-2"</th> |
+ <th class="st">"010"<br>(Octal)</th> |
+ <th class="st">"0x10"<br>(Hex)</th> |
+ <th class="st">"0xFF"<br>(Hex)</th> |
+ <th class="st">"-010"</th> |
+ <th class="st">"-0x10"</th> |
+ <th class="st">"xx"</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>parseFloat(col)</th> |
+ <td class="nm">NaN</td> |
+ <td class="nm">-1.6</td> |
+ <td class="nm">0</td> |
+ <td class="nm">1</td> |
+ <td class="nm">1.6</td> |
+ <td class="nm">8</td> |
+ <td class="nm">16</td> |
+ <td class="nm">16.8</td> |
+ <td class="nm">1.23</td> |
+ <td class="nm">10</td> |
+ <td class="nm">0</td> |
+ <td class="nm">0</td> |
+ <td class="nm">-10</td> |
+ <td class="nm">0</td> |
+ <td class="nm">NaN</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcParseFl_1"> |
+With <code>parseFloat</code> empty strings return <code>NaN </code> |
+along with strings that cannot be subject to numeric interpretation. |
+The exponential format is understood and the leading zero in the |
+octal format does not hinder the string's interpretation as a |
+decimal number. Hexadecimal strings are interpreted as the number |
+zero because the following <code>"x"</code> cannot be |
+interpreted as part of a number so parsing stops after the leading zero. |
+</p> |
+ |
+<table> |
+ <caption>parseFloat(col) : Other Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="un">undefined</th> |
+ <th class="ob">null</th> |
+ <th class="bl">true</th> |
+ <th class="bl">false</th> |
+ <th class="ob">new Object()</th> |
+ <th class="fn">function(){<br> return;<br>}</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>parseFloat(col)</th> |
+ <td class="nm">NaN</td> |
+ <td class="nm">NaN</td> |
+ <td class="nm">NaN</td> |
+ <td class="nm">NaN</td> |
+ <td class="nm">NaN</td> |
+ <td class="nm">NaN</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcParseFl_2"> |
+Non-string values are first converted into a string that is employed |
+by <code>parseFloat</code>. As that type-conversion to a string would |
+not normally result in a string that could be interpreted as a number |
+the result is <code>NaN</code>. Objects and functions may have custom |
+<code>toString</code> methods that may return strings that could be |
+interpreted as numbers but that would be an unusual requirement. |
+</p> |
+ |
+<h3 id="tcParseIn">parseInt</h3> |
+ |
+<p id="tcParseIn_1"> |
+The <code>parseInt</code> function works in a similar way to |
+<code>parseFloat</code> except that it is trying to interpret its |
+string argument into an integer and as a result recognises fewer |
+character as possible candidates to be part of that number. |
+</p> |
+ |
+<p id="tcParseIn_2"> |
+<code>parseInt</code> is occasionally used as a means of turning a |
+floating point number into an integer. It is very ill suited to that |
+task because if its argument is of numeric type it will first be |
+converted into a string and then parsed as a number, very inefficient. |
+This can produce very wrong results with numbers such as |
+<code>2e-200</code>, for which the next smaller integer is zero, but |
+with which <code>parseInt</code> returns <code>2</code>. Also, because |
+of the number format used by javascript, numbers are often represented |
+by near approximations. So, for example, 1/2 + 1/3 + 1/6 = |
+0.9999999999999999, which isn't quite one and parseInt would return |
+zero if asked to act on the result of the operation. |
+</p> |
+ |
+<p id="tcParseIn_3"> |
+For rounding |
+numbers to integers one of <code>Math.round</code>, <code>Math.ceil</code> |
+and <code>Math.floor</code> are preferable, and for a desired result |
+that can be expressed as a 32 bit signed integer the bitwise operation |
+described below might also suit. |
+</p> |
+ |
+<table> |
+ <caption>parseInt(col) : Numeric Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="nm">-1.6</th> |
+ <th class="nm">-0</th> |
+ <th class="nm">+0</th> |
+ <th class="nm">1</th> |
+ <th class="nm">1.6</th> |
+ <th class="nm">8</th> |
+ <th class="nm">16</th> |
+ <th class="nm">16.8</th> |
+ <th class="nm">123e-2</th> |
+ <th class="nm">-Infinity</th> |
+ <th class="nm">+Infinity</th> |
+ <th class="nm">NaN</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>parseInt(col)</th> |
+ <td class="nm">-1</td> |
+ <td class="nm">0</td> |
+ <td class="nm">0</td> |
+ <td class="nm">1</td> |
+ <td class="nm">1</td> |
+ <td class="nm">8</td> |
+ <td class="nm">16</td> |
+ <td class="nm">16</td> |
+ <td class="nm">1</td> |
+ <td class="nm">NaN</td> |
+ <td class="nm">NaN</td> |
+ <td class="nm">NaN</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcParseIn_4"> |
+When it is acting on number the effect of the initial type-conversion |
+of the argument to a string is evident in the results. Note that the |
+value <code>123e-2</code> is internally the number <code>1.23</code> |
+and that type converts into the string <code>"1.23"</code>, |
+so that entry in the table above might look odd but it is correct. |
+</p> |
+ |
+<table> |
+ <caption>parseInt(col) : String Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="st">""<br>(empty<br>string)</th> |
+ <th class="st">"-1.6"</th> |
+ <th class="st">"0"</th> |
+ <th class="st">"1"</th> |
+ <th class="st">"1.6"</th> |
+ <th class="st">"8"</th> |
+ <th class="st">"16"</th> |
+ <th class="st">"16.8"</th> |
+ <th class="st">"123e-2"</th> |
+ <th class="st">"010"<br>(Octal)</th> |
+ <th class="st">"0x10"<br>(Hex)</th> |
+ <th class="st">"0xFF"<br>(Hex)</th> |
+ <th class="st">"-010"</th> |
+ <th class="st">"-0x10"</th> |
+ <th class="st">"xx"</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>parseInt(col)</th> |
+ <td class="nm">NaN</td> |
+ <td class="nm">-1</td> |
+ <td class="nm">0</td> |
+ <td class="nm">1</td> |
+ <td class="nm">1</td> |
+ <td class="nm">8</td> |
+ <td class="nm">16</td> |
+ <td class="nm">16</td> |
+ <td class="nm">123</td> |
+ <td class="nm">8</td> |
+ <td class="nm">16</td> |
+ <td class="nm">255</td> |
+ <td class="nm">-8</td> |
+ <td class="nm">-16</td> |
+ <td class="nm">NaN</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcParseIn_5"> |
+Strings in octal and hexadecimal number formats do represent integers |
+and <code>parseInt</code> is capable of interpreting them in accordance |
+with the rules for Javascript source code, even when they have leading |
+minus signs. |
+</p> |
+ |
+<table> |
+ <caption>parseInt(col) : Other Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="un">undefined</th> |
+ <th class="ob">null</th> |
+ <th class="bl">true</th> |
+ <th class="bl">false</th> |
+ <th class="ob">new Object()</th> |
+ <th class="fn">function(){<br> return;<br>}</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>parseInt(col)</th> |
+ <td class="nm">NaN</td> |
+ <td class="nm">NaN</td> |
+ <td class="nm">NaN</td> |
+ <td class="nm">NaN</td> |
+ <td class="nm">NaN</td> |
+ <td class="nm">NaN</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcParseIn_6"> |
+As <code>parseInt</code> type-converts its non-string arguments to |
+strings it always produces the same results for <code>boolean</code>, |
+<code>null</code>, <code>undefined</code>, object and function |
+arguments as <code>parseFloat</code> (assuming objects and functions |
+do not have custom <code>toString</code> methods). |
+</p> |
+ |
+<h3 id="tcPrIntRx">parseInt with a radix argument</h3> |
+ |
+<p id="tcPrIntRx_1"> |
+It is rarely desirable to allow <code>parseInt</code> to deduce the |
+base in which the number is represented from the string as leading zeros are |
+rarely intended to indicate data in octal format (particularly with |
+user input). To deal with this problem <code>parseInt</code> recognises |
+a second, radix, argument that can be used to specify the base in which the |
+string is to be interpreted. Specifying a second argument of 10 causes |
+<code>parseInt</code> to interpret the strings as only base 10. |
+</p> |
+ |
+<table> |
+ <caption>parseInt(col, 10) : String Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="st">""<br>(empty<br>string)</th> |
+ <th class="st">"-1.6"</th> |
+ <th class="st">"0"</th> |
+ <th class="st">"1"</th> |
+ <th class="st">"1.6"</th> |
+ <th class="st">"8"</th> |
+ <th class="st">"16"</th> |
+ <th class="st">"16.8"</th> |
+ <th class="st">"123e-2"</th> |
+ <th class="st">"010"<br>(Octal)</th> |
+ <th class="st">"0x10"<br>(Hex)</th> |
+ <th class="st">"0xFF"<br>(Hex)</th> |
+ <th class="st">"-010"</th> |
+ <th class="st">"-0x10"</th> |
+ <th class="st">"xx"</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>parseInt(col, 10)</th> |
+ <td class="nm">NaN</td> |
+ <td class="nm">-1</td> |
+ <td class="nm">0</td> |
+ <td class="nm">1</td> |
+ <td class="nm">1</td> |
+ <td class="nm">8</td> |
+ <td class="nm">16</td> |
+ <td class="nm">16</td> |
+ <td class="nm">123</td> |
+ <td class="nm">10</td> |
+ <td class="nm">0</td> |
+ <td class="nm">0</td> |
+ <td class="nm">-10</td> |
+ <td class="nm">0</td> |
+ <td class="nm">NaN</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcPrIntRx_2"> |
+The string in octal format is now interpreted as base 10 and the |
+hexadecimal strings can now only be zero as parsing has to stop |
+when the <code>"x"</code> is encountered. |
+</p> |
+ |
+<p id="tcPrIntRx_3"> |
+Number bases 2 to 36 can be used with <code>parseInt</code>. The |
+following is base 16. |
+</p> |
+ |
+<table> |
+ <caption>parseInt(col, 16) : String Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="st">""<br>(empty<br>string)</th> |
+ <th class="st">"-1.6"</th> |
+ <th class="st">"0"</th> |
+ <th class="st">"1"</th> |
+ <th class="st">"1.6"</th> |
+ <th class="st">"8"</th> |
+ <th class="st">"16"</th> |
+ <th class="st">"16.8"</th> |
+ <th class="st">"123e-2"</th> |
+ <th class="st">"010"<br>(Octal)</th> |
+ <th class="st">"0x10"<br>(Hex)</th> |
+ <th class="st">"0xFF"<br>(Hex)</th> |
+ <th class="st">"-010"</th> |
+ <th class="st">"-0x10"</th> |
+ <th class="st">"xx"</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>parseInt(col, 16)</th> |
+ <td class="nm">NaN</td> |
+ <td class="nm">-1</td> |
+ <td class="nm">0</td> |
+ <td class="nm">1</td> |
+ <td class="nm">1</td> |
+ <td class="nm">8</td> |
+ <td class="nm">22</td> |
+ <td class="nm">22</td> |
+ <td class="nm">4670</td> |
+ <td class="nm">16</td> |
+ <td class="nm">16</td> |
+ <td class="nm">255</td> |
+ <td class="nm">-16</td> |
+ <td class="nm">-16</td> |
+ <td class="nm">NaN</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcPrIntRx_4"> |
+The hexadecimal <code>0x</code> format is recognised again with the |
+base 16 interpretation. |
+</p> |
+ |
+<p id="tcPrIntRx_5"> |
+Finally base 3:- |
+</p> |
+ |
+<table> |
+ <caption>parseInt(col, 3) : Numeric Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="nm">-1.6</th> |
+ <th class="nm">-0</th> |
+ <th class="nm">+0</th> |
+ <th class="nm">1</th> |
+ <th class="nm">1.6</th> |
+ <th class="nm">8</th> |
+ <th class="nm">16</th> |
+ <th class="nm">16.8</th> |
+ <th class="nm">123e-2</th> |
+ <th class="nm">-Infinity</th> |
+ <th class="nm">+Infinity</th> |
+ <th class="nm">NaN</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>parseInt(col, 3)</th> |
+ <td class="nm">-1</td> |
+ <td class="nm">0</td> |
+ <td class="nm">0</td> |
+ <td class="nm">1</td> |
+ <td class="nm">1</td> |
+ <td class="nm">NaN</td> |
+ <td class="nm">1</td> |
+ <td class="nm">1</td> |
+ <td class="nm">1</td> |
+ <td class="nm">NaN</td> |
+ <td class="nm">NaN</td> |
+ <td class="nm">NaN</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcPrIntRx_6"> |
+The consequences of the type-converting of numeric arguments to |
+strings is evident again. The number <code>8</code> is coming out |
+as <code>NaN</code> because the <code>"8"</code> character |
+cannot be interpreted as base 3, leaving an empty sequence of |
+acceptable characters and producing the same result as an empty string. |
+</p> |
+ |
+<table> |
+ <caption>parseInt(col, 3) : String Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="st">""<br>(empty<br>string)</th> |
+ <th class="st">"-1.6"</th> |
+ <th class="st">"0"</th> |
+ <th class="st">"1"</th> |
+ <th class="st">"1.6"</th> |
+ <th class="st">"8"</th> |
+ <th class="st">"16"</th> |
+ <th class="st">"16.8"</th> |
+ <th class="st">"123e-2"</th> |
+ <th class="st">"010"<br>(Octal)</th> |
+ <th class="st">"0x10"<br>(Hex)</th> |
+ <th class="st">"0xFF"<br>(Hex)</th> |
+ <th class="st">"-010"</th> |
+ <th class="st">"-0x10"</th> |
+ <th class="st">"xx"</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>parseInt(col, 3)</th> |
+ <td class="nm">NaN</td> |
+ <td class="nm">-1</td> |
+ <td class="nm">0</td> |
+ <td class="nm">1</td> |
+ <td class="nm">1</td> |
+ <td class="nm">NaN</td> |
+ <td class="nm">1</td> |
+ <td class="nm">1</td> |
+ <td class="nm">5</td> |
+ <td class="nm">3</td> |
+ <td class="nm">0</td> |
+ <td class="nm">0</td> |
+ <td class="nm">-3</td> |
+ <td class="nm">0</td> |
+ <td class="nm">NaN</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<h2 id="tcToInt32">ToInt32</h2> |
+ |
+<p id="tcToInt32_1"> |
+<code>ToInt32</code> is an <em>internal</em> function only available to the |
+Javascript implementation and cannot be called directly from scripts |
+in the way that <code>parseInt</code> can. It is a bit unusual to mention it in |
+connection with converting Javascript values to numbers but it can |
+be used in a limited set of circumstances. The bitwise operators such |
+as bitwise OR (<code>|</code>) and bitwise AND (<code>&</code>) operate on |
+numbers so they type-convert their operands to numbers. However, they |
+also only operate on 32 bit signed integers so given the (possibly |
+type-converted) numeric value they call the <em>internal</em> |
+<code>ToInt32</code> function with that number as its argument and |
+use the returned value as their operand. That returned value is always |
+a 32 bit signed integer. |
+</p> |
+ |
+<p id="tcToInt32_2"> |
+The effect can be like <code>parseInt</code> combined with type-converting |
+to numbers. While the result is limited in range to 32 bits, it is |
+<em>always</em> numeric and never <code>NaN</code>, or ± |
+<code>Infinity</code>. |
+</p> |
+ |
+<p id="tcToInt32_3"> |
+As with using mathematical operators in operations that have no effect on |
+the value of any resulting number it is possible to perform a bitwise |
+operation that will not affect the value returned from the call to |
+<code>ToInt32</code>. The tables below were generated using a bitwise |
+OR zero operation. |
+</p> |
+ |
+<table> |
+ <caption> ToInt32 (col|0) : Numeric Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="nm">-1.6</th> |
+ <th class="nm">-0</th> |
+ <th class="nm">+0</th> |
+ <th class="nm">1</th> |
+ <th class="nm">1.6</th> |
+ <th class="nm">8</th> |
+ <th class="nm">16</th> |
+ <th class="nm">16.8</th> |
+ <th class="nm">123e-2</th> |
+ <th class="nm">-Infinity</th> |
+ <th class="nm">+Infinity</th> |
+ <th class="nm">NaN</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>col|0</th> |
+ <td class="nm">-1</td> |
+ <td class="nm">0</td> |
+ <td class="nm">0</td> |
+ <td class="nm">1</td> |
+ <td class="nm">1</td> |
+ <td class="nm">8</td> |
+ <td class="nm">16</td> |
+ <td class="nm">16</td> |
+ <td class="nm">1</td> |
+ <td class="nm">0</td> |
+ <td class="nm">0</td> |
+ <td class="nm">0</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcToInt32_4"> |
+<code>NaN</code> and ±<code>Infinity</code> become zero and |
+floating point values are <em>truncated</em> to integers. |
+</p> |
+ |
+<table> |
+ <caption> ToInt32 (col|0) : String Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="st">""<br>(empty<br>string)</th> |
+ <th class="st">"-1.6"</th> |
+ <th class="st">"0"</th> |
+ <th class="st">"1"</th> |
+ <th class="st">"1.6"</th> |
+ <th class="st">"8"</th> |
+ <th class="st">"16"</th> |
+ <th class="st">"16.8"</th> |
+ <th class="st">"123e-2"</th> |
+ <th class="st">"010"<br>(Octal)</th> |
+ <th class="st">"0x10"<br>(Hex)</th> |
+ <th class="st">"0xFF"<br>(Hex)</th> |
+ <th class="st">"-010"</th> |
+ <th class="st">"-0x10"</th> |
+ <th class="st">"xx"</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>col|0</th> |
+ <td class="nm">0</td> |
+ <td class="nm">-1</td> |
+ <td class="nm">0</td> |
+ <td class="nm">1</td> |
+ <td class="nm">1</td> |
+ <td class="nm">8</td> |
+ <td class="nm">16</td> |
+ <td class="nm">16</td> |
+ <td class="nm">1</td> |
+ <td class="nm">10</td> |
+ <td class="nm">16</td> |
+ <td class="nm">255</td> |
+ <td class="nm">-10</td> |
+ <td class="nm">0</td> |
+ <td class="nm">0</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcToInt32_5"> |
+String values that would type-convert to <code>NaN</code> are returned |
+as zero from <code>ToInt32</code>. |
+</p> |
+ |
+<table> |
+ <caption> ToInt32 (col|0) : Other Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="un">undefined</th> |
+ <th class="ob">null</th> |
+ <th class="bl">true</th> |
+ <th class="bl">false</th> |
+ <th class="ob">new Object()</th> |
+ <th class="fn">function(){<br> return;<br>}</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>col|0</th> |
+ <td class="nm">0</td> |
+ <td class="nm">0</td> |
+ <td class="nm">1</td> |
+ <td class="nm">0</td> |
+ <td class="nm">0</td> |
+ <td class="nm">0</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcToInt32_6"> |
+Even <code>undefined</code>, objects and functions are converted to zero value |
+numbers by this operation. Note though that boolean <code>true</code> is |
+converted to the number 1. |
+</p> |
+ |
+ |
+<h2 id="tcUserIn">Converting User Input</h2> |
+ |
+<p id="tcUserIn_1"> |
+Most of the mechanisms for getting input from the user, |
+<code><input type="text"></code> and |
+<code>prompt</code> for example, provide their results in the form |
+of strings. If the user is expected to input a number they still |
+might enter anything (at the least they may just make a typo). If |
+the string needs to be converted into a number for later operations |
+one of the methods mentioned above can be chosen based on what best |
+suits the nature of the input expected but some of the results |
+generated with erroneous input may be difficult to detect and handle. |
+</p> |
+ |
+<p id="tcUserIn_2"> |
+Prior to converting a string to a number it may be advantageous |
+to use a Regular Expression to test the contents of the string |
+to ensure that they conform to an acceptable format. That would |
+serve to eliminate some of the string values that may otherwise |
+suffer from the quirks of the string to number converting |
+processes when applied to unexpected string values. |
+</p> |
+ |
+ |
+<h3 id="tcRegEx">Regular expression examples</h3> |
+ |
+<pre id="tcRegExEm"> |
+/^\d+$/ <span class="commentJS">//All-digit</span> |
+/^\s*[-+]?\d+\s*$/ <span class="commentJS">//Unbroken Signed integer & spaces</span> |
+/^\d{1,5}$/ <span class="commentJS">//1 to 5 digits</span> |
+/^\d+\.\d\d$/ <span class="commentJS">//Money</span> |
+/^\d+(\.\d{2})$/ <span class="commentJS">//Money</span> |
+/^\d{1,3}(,\d\d\d)*\.\d\d$/ <span class="commentJS">//comma-separated money - 12,432.57</span> |
+ |
+ <span class="commentJS">// optional comma-separated money - 12,432.57 or 12432.57</span> |
+/^\d{1,3}(,\d\d\d)*\.\d\d$|^\d+\.\d\d$/ |
+ |
+</pre> |
+</body> |
+</html> |
/cljs/faq_notes/type_convert.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/faq_notes/script_tags.html |
=================================================================== |
--- cljs/faq_notes/script_tags.html (nonexistent) |
+++ cljs/faq_notes/script_tags.html (revision 2) |
@@ -0,0 +1,949 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
+<html lang="en"><head><title>How to Include Scripts in HTML Documents</title> |
+<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> |
+<link href="../faq.css" rel="stylesheet" type="text/css"> |
+<link href="faq_notes.css" rel="stylesheet" type="text/css"> |
+<style type="text/css"> |
+BLOCKQUOTE PRE { |
+ background-color:#EEEEFF; |
+ color:#000000; |
+ border:#EEEEFF 0px none; |
+ margin:0; |
+ padding:0; |
+} |
+BLOCKQUOTE H5 { |
+ margin-left:0; |
+} |
+CODE { white-space:nowrap; } |
+.elContent { |
+ background-color:#EEEEFF; |
+ color:#900000; |
+} |
+</style> |
+</head> |
+<body> |
+ |
+<h1><a name="hsHead" id="hsHead">How to Include Scripts in <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> Documents</a></h1> |
+ |
+<ul> |
+ <li><a href="#hsIntro">Introduction</a></li> |
+ <li><a href="#hsSE">SCRIPT Elements</a> |
+ <ul> |
+ <li><a href="#hsAt">Attributes</a> |
+ <ol> |
+ <li><a href="#hsAtch">charset</a></li> |
+ <li><a href="#hsAtty">type</a></li> |
+ <li><a href="#hsAtln">language</a></li> |
+ <li><a href="#hsAtsc">src</a></li> |
+ <li><a href="#hsAtdf">defer</a></li> |
+ </ol> |
+ </li> |
+ </ul> |
+ </li> |
+ <li><a href="#hsStFm">The Standard Formulations</a></li> |
+ <li><a href="#hsPrCn">Permissible Contexts for Script Elements</a></li> |
+ <li><a href="#hsCt">The Content of Script Elements</a> |
+ <ul> |
+ <li><a href="#hsOld">Hiding Scripts from Older Browsers</a></li> |
+ <li><a href="#hsETO">Closing Script Tags and "</" (end-tag open delimiter)</a></li> |
+ </ul> |
+ </li> |
+ <li><a href="#hsExF">External Javascript Files</a> |
+ <ul> |
+ <li><a href="#hsExC">The content of External Javascript Files.</a></li> |
+ </ul> |
+ </li> |
+ <li> |
+ <a href="#hsMix">Script Elements that Import Javascript Files and Have Contents</a> |
+ </li> |
+ <li><a href="#hsEh">Event Handling Attributes: Intrinsic Events</a> |
+ <ul> |
+ <li><a href="#hsEhD">The Default Language for Intrinsic Events</a></li> |
+ </ul> |
+ </li> |
+ <li><a href="#hsNs">NOSCRIPT Elements</a></li> |
+</ul> |
+ |
+<h2><a name="hsIntro" id="hsIntro">Introduction</a></h2> |
+ |
+ |
+<p> |
+There are three ways of including scripts in <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> documents:- |
+</p> |
+ |
+<ol> |
+ <li>As the string value provided for an event handling attribute such as onclick (intrinsic events).</li> |
+ <li>As the contents of a SCRIPT element (between opening and closing script tags in certain permissible locations within <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> source code.</li> |
+ <li>As a separate script file imported into an <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> page by having the URL of the file assigned to the SRC attribute of a SCRIPT element, again at certain permissible locations within the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> source.</li> |
+</ol> |
+ |
+<h2><a name="hsSE" id="hsSE">SCRIPT Elements</a></h2> |
+ |
+<p> |
+The current <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> version is 4.01. The <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> 4.01 transitional DTD |
+defines a script element with:- |
+</p> |
+ |
+<blockquote cite="http://www.w3.org/TR/html4/loose.dtd" style="font-family:Courier, monospace;"> |
+<!ELEMENT SCRIPT <span class="elContent">- -</span> %Script; -- script statements --><br> |
+<!ATTLIST SCRIPT<br> |
+<pre> |
+ charset %Charset; #IMPLIED - char encoding of linked resource - |
+ type %ContentType; #REQUIRED - content type of script language - |
+ language CDATA #IMPLIED - predefined script language name - |
+ src %URI; #IMPLIED - URI for an external script - |
+ defer (defer) #IMPLIED - UA may defer execution of script - |
+ event CDATA #IMPLIED - reserved for possible future use - |
+ for %URI; #IMPLIED - reserved for possible future use - |
+ </pre> |
+ > |
+</blockquote> |
+ |
+<p> |
+(The <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> 4.01 strict DTD omits the <code>language</code> attribute |
+as it is deprecated in the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> 4.01 standard.) |
+</p> |
+ |
+<p> |
+Script elements are defined with opening and closing script tags. The |
+two dashes after the element name in the DTD means that neither opening nor |
+closing tag may be omitted, even when the element is importing a |
+javascript file and has no contents. |
+</p> |
+ |
+<h3><a name="hsAt" id="hsAt">Attributes</a></h3> |
+ |
+<h4><a name="hsAtch" id="hsAtch">charset</a></h4> |
+ |
+<p> |
+The <code>charset</code> attribute can declare the character encoding of an external |
+javascript file that is being imported using the <code>src</code> attribute. In all |
+cases it is preferable that the server sending the file provide |
+character encoding information in Content-Type |
+<span class="initialism" title="HyperText Transfer Protocol "> |
+<abbr title=" Transfer Protocol ">HTTP</abbr></span> headers (with the |
+slight problem that there was no official content-type for use with |
+scripts; see the <code>type</code> attribute below). |
+</p> |
+ |
+<p> |
+Javascript itself uses a very limited repertoire of characters but the |
+content of string literals in non-Latin languages may necessitate an |
+interest in character encodings with script files. That is not a |
+problem that I have faced to date so I don't know how it should best |
+be handled. I am yet to see a <code>charset</code> attribute used in |
+a script tag. |
+</p> |
+ |
+<h4><a name="hsAtty" id="hsAtty">type</a></h4> |
+ |
+<p> |
+The <code>type</code> attribute is required in <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> 4 but the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> 4 |
+specification is not very helpful on the subject. It says:- |
+</p> |
+ |
+<blockquote cite="http://www.w3.org/TR/html4/interact/scripts.html#h-18.2.1"> |
+<h5>type = content-type [CI]</h5> |
+This attribute specifies the scripting language of the element's |
+contents and overrides the default scripting language. The scripting |
+language is specified as a content type (e.g., |
+"text/javascript"). Authors must supply a value for this |
+attribute. There is no default value for this attribute. |
+</blockquote> |
+ |
+<p> |
+(The [CI] means that the attribute's value is case insensitive.) |
+</p> |
+ |
+<p> |
+Pursuing the permissible values of content-type through the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> |
+specification leads to a list of currently recognised content types |
+(MIME or Media types). Up until mid 2005 that list did not include |
+anything related to ECMAScript or javascript. So although the attribute |
+is required, and so must have a value, there was no standardised |
+content-type for that value. However, the HTML 4 specification did give |
+text/javascript as an example (even though it was not a recognised |
+standard content type) so it was that value that has traditionally been |
+used with the <code>type</code> attribute when including or importing |
+ECMAScript/javascript into an HTML page. |
+</p> |
+ |
+<p> |
+The MIME types introduced in 2005 are application/ecmascript, |
+application/javascript and text/javascript. The last of these, and the |
+value that has traditionally been used; text/javascript, was official |
+deprecated and so should be phased-out over time. However, at the point |
+of officially recognising these new MIME types no browsers exist that |
+will recognise either of application/ecmascript and application/javascript. |
+This means that if either are actually used for the value of the <code>type</code> |
+attribute the likelihood is that the script in question will never be |
+executed. |
+</p> |
+ |
+<p> |
+So for the present, and probably many years to come, text/javascript is |
+the only viable value for use with the <code>type</code> attribute when using javascript. |
+</p> |
+ |
+<pre> |
+type="text/javascript" |
+</pre> |
+ |
+<h4><a name="hsAtln" id="hsAtln">language</a></h4> |
+ |
+<p> |
+The <code>language</code> attribute is deprecated (and not allowed under |
+the strict DTD) and it is unnecessary when the <code>type</code> attribute |
+is required, as that attribute will determine the language used. |
+</p> |
+ |
+<p> |
+The <code>language</code> attribute can be more specific than the |
+<code>type</code> attribute because it can also specify the language |
+version. In almost all respects specifying a language version is not |
+helpful and even potentially dangerous. |
+</p> |
+ |
+<p> |
+By default a web browser will execute a script using the latest version |
+of the language that it supports. Generally all current (March 2004) |
+browsers support all of the language features specified in ECMA 262 2nd |
+edition (approximately JavaScript 1.3) and most fully support the 3rd |
+edition. Restricting the language features used to those defined in |
+ECMA 262 2nd edition (with additional care in some less used areas) |
+should result in scripts that will happily execute on all current |
+browsers without a need to specify a language version. |
+</p> |
+ |
+<p> |
+Netscape initially attempted to tie the DOM features of their browser |
+to the language version, which would have allowed a specified language |
+version to imply the DOM features supported. That idea was abandoned |
+because other browsers produced by their competitors introduced |
+scripting with near identical languages but significantly different |
+DOMs. DOM support should be determined independently of language |
+version using object/feature detecting. |
+</p> |
+ |
+<p> |
+The potential danger with specifying a language version comes with |
+specifying version 1.2. Version 1.2 was an aberration. It deviated |
+significantly from earlier versions of the language in anticipation |
+of changes to the ECMA specification, but those changes were never |
+made. Netscape had to reverse the changes it had made to version |
+1.2 in version 1.3 in order to conform with what was eventually |
+published as ECMA 262 2nd edition. The only browsers released for |
+which version 1.2 was the default JavaScript version were Netscape |
+4.00 to 4.05 (and you won't find many of those left in the wild). |
+</p> |
+ |
+<p> |
+The problem is that if you specify version 1.2 in a <code>language</code> attribute |
+you may actually get it, with all of its deviant characteristics, but |
+at the same time most browsers will not exhibit those characteristics. |
+It is always a bad idea to encourage the same code to be interpreted in |
+two different ways, and certainly never without fully understanding how |
+the language versions differ. The specific problem can be avoided by |
+never specifying the language version as 1.2. The issue can be avoided |
+by never providing the deprecated <code>language</code> attribute at all. |
+</p> |
+ |
+<h4><a name="hsAtsc" id="hsAtsc">src</a></h4> |
+ |
+<p> |
+The SRC attribute specifies the URL of an external javascript file that |
+is to be imported by the script element. If no file is being imported |
+by the element (the script is the element's contents) then the |
+<code>src</code> attribute is omitted. |
+</p> |
+ |
+<h4><a name="hsAtdf" id="hsAtdf">defer</a></h4> |
+ |
+<p> |
+The <code>defer</code> attribute is specified as providing a |
+"hint" to the browser as to whether it needs to process |
+the script immediately (as it usually would), or whether it can carry |
+on parsing the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> following the script element and leave the |
+javascript interpreter to process the script in its own time. |
+</p> |
+ |
+<p> |
+If a script uses the <code>document.write</code> method to insert |
+content into the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> being processed then the script element |
+containing that script must not be deferred as the inserted <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> |
+could end up at any point in the document (or even be inserted after |
+the current document has closed, replacing it). If a script is |
+deferred additional care must be taken before any part of it, such |
+as a function it defines, is interacted with by other scripts (such |
+as intrinsic events). |
+</p> |
+ |
+<p> |
+It is unusual for a script element to have a <code>defer</code> |
+attribute. And many browsers will not recognise/act upon a |
+<code>defer</code> attribute even if one is present. |
+</p> |
+ |
+<h2><a name="hsStFm" id="hsStFm">The Standard Formulations</a></h2> |
+ |
+<p> |
+Leaving the <code>defer</code> and <code>charset</code> attributes |
+aside, the normal formulation for a valid <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> 4 script element that |
+imports a javascript file is:- |
+</p> |
+ |
+<pre> |
+<script type="text/javascript" |
+ src="http://example.com/scriptFile.js"></script> |
+ |
+<span class="commentJS"><!-- or using an example relative URL --></span> |
+ |
+<script type="text/javascript" src="../scripts/scriptFile.js"></script> |
+</pre> |
+ |
+<p> |
+<span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> is case insensitive so the tag name and attribute names can be |
+in upper or lower (or mixed) case (current practice tends to prefer |
+lower case). |
+</p> |
+ |
+<p> |
+The attribute values must be quoted because in both cases they include |
+characters that are forbidden in unquoted attribute values (forbidden |
+characters would be any character that is not: letters (a-z and A-Z), |
+digits (0-9), hyphens (ASCII decimal 45), periods (ASCII decimal 46), |
+underscores (ASCII decimal 95), and colons (ASCII decimal 58)). The |
+quote characters used may be double quotes (<code>"</code>) or single quotes |
+(<code>'</code>). Common practice prefers double quotes for <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> attributes. |
+</p> |
+ |
+<p> |
+Traditionally javascript files are given a two-letter extension of <code>.js</code>. |
+That extension is not required, any valid URL to a resource that |
+returns content that can be interpreted as valid javascript source |
+code will work. In addition, browsers do not appear to be interested |
+in any Content Type headers sent with the javascript source, which is |
+probably a good thing as officially recognised content types have only |
+just (mid 2005) been introduced. |
+</p> |
+ |
+<p> |
+Script that is to be included in an <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> page is placed as the content |
+of a script element. Appearing between the opening and closing script |
+tags:- |
+</p> |
+ |
+<pre> |
+<script type="text/javascript"> |
+function exampleFunctionDeclaration(n){ |
+ return (n * 4); |
+} |
+</sciprt> |
+</pre> |
+ |
+<p> |
+The same case sensitivity and attribute value quoting considerations |
+apply to this application of the script tags as applied to their use |
+when importing external script files. |
+</p> |
+ |
+ |
+<h2><a name="hsPrCn" id="hsPrCn">Permissible Contexts for Script Elements</a></h2> |
+ |
+<p> |
+Script elements may not appear in all contexts in an <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> document. |
+They may be children of the <code>HEAD</code> element because the DTD |
+defines the content of the <code>HEAD</code> element as including |
+<code>%head_misc;</code> content which includes <code>SCRIPT</code> in |
+its definition. Script elements may also appear within the |
+<code>BODY</code> element in any context that is specified as |
+<code>%flow;</code>, <code>%inline;</code>, <code>%special;</code> or |
+specifically <code>SCRIPT</code> by the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> DTDs. This is because |
+<code>%flow;</code> includes all elements defined as |
+<code>%inline;</code>, which includes all elements defined as |
+<code>%special;</code>, which includes <code>SCRIP</code> in its |
+definition (among others). |
+</p> |
+ |
+<p> |
+Reading the DTDs and looking out for these categories will indicate |
+where script elements are allowed to appear. For example, the (<span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> |
+4.01 transitional) DTD definition for the paragraph element reads:- |
+</p> |
+ |
+<blockquote cite="http://www.w3.org/TR/html4/loose.dtd"> |
+<pre> |
+<!ELEMENT P - O (<span class="elContent">%inline;</span>)* -- paragraph --> |
+</pre> |
+</blockquote> |
+ |
+<p> |
+The content for the <code>P</code> element is <code>%inline;</code> and |
+<code>%inline;</code> encompasses <code>SCRIPT</code>. Similarly:- |
+</p> |
+ |
+<blockquote cite="http://www.w3.org/TR/html4/loose.dtd"> |
+<pre> |
+<!ELEMENT DD - O (<span class="elContent">%flow;</span>)* -- definition description --> |
+</pre> |
+</blockquote> |
+ |
+<p> |
+The <code>DD</code> element has <code>%flow;</code> defining its content so it is |
+allowed <code>SCRIPT</code> as its content (or part of it). Whereas:- |
+</p> |
+ |
+<blockquote cite="http://www.w3.org/TR/html4/loose.dtd"> |
+<pre> |
+<!ELEMENT DL - - (<span class="elContent">DT|DD</span>)+ -- definition list --> |
+</pre> |
+</blockquote> |
+ |
+<p> |
+The <code>DL</code> element is only allowed <code>DT</code> and |
+<code>DD</code> elements as its children. So a script element |
+cannot appear as a child of a <code>DL</code> element in valid <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> 4. |
+</p> |
+ |
+<p> |
+The DTD for the particular flavour of <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> being authored is the best |
+guide as the where in a document script elements may appear, but note |
+that the different versions of the DTD differ slightly in terms of the |
+content defined for some elements. |
+</p> |
+ |
+<h2><a name="hsCt" id="hsCt">The Content of Script Elements</a></h2> |
+ |
+<p> |
+Script elements that have source code as their contents and appear on |
+an <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> page need some special consideration. |
+</p> |
+ |
+<h3><a name="hsOld" id="hsOld">Hiding Scripts from Older Browsers</a></h3> |
+ |
+<p> |
+When scripting was first introduced the preceding generations of |
+browsers had no concept of what a script element was, and would treat |
+the content of the unrecognised script tags in the way unrecognised |
+tags are normally handled in <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span>. The content is treated as <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> |
+source, which, for a scripts, meant including it as text in a page. |
+The results did not look good and a mechanism was provided to hide the |
+script element contents from browsers that did not know how to handle |
+script elements. |
+</p> |
+ |
+<p> |
+Javascript has an end of line comment symbol consisting of two slashes |
+(<code>//</code>). All characters between that symbol and the end of |
+the line are treated as a comment and ignored. <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> also provides a |
+means of commenting out parts of its source, an opening comment |
+tag <code><!--</code> and a closing comment tag |
+<code>--></code> (strictly these are not opening and closing tags |
+in HTML, it is the pairs of dashes that start and end a comment. The |
+surrounding <code><!</code> and <code>></code> represent a |
+processing instruction, which is the only context in which a comment |
+is recognised in HTML.). |
+</p> |
+ |
+<p> |
+The trick to hiding javascript source code from |
+browsers that did not recognise the script element, so it would not |
+be shown on the page, was to allow script included in an <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> page to |
+use an additional end of line comment symbol that corresponded with |
+the <code><!--</code> opening comment tag used by <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span>. The script |
+author would then place this tag/comment symbol at the start of the |
+script source code (on a line of its own, so as not to comment out |
+any javascript code) and then use the normal javascript end of line |
+comment symbol to comment out (from the javascript interpreter) an |
+<span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> end of comment tag. |
+</p> |
+ |
+<pre> |
+<script type="text/javascript"> |
+<span class="commentJS"><!--</span> |
+function exampleFunctionDeclaration(n){ |
+ return (n * 4); |
+} |
+<span class="commentJS">// --></span> |
+</sciprt> |
+</pre> |
+ |
+<p> |
+A browser incapable of recognising the script element would treat its |
+content as <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> |
+source and so it would interpret the script within the script element |
+as effectively commented out, thus not displaying it on the page. |
+</p> |
+ |
+<p> |
+When scripting was introduced the practice was necessary and highly |
+recommended, but that was some time ago and browsers and <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> versions |
+have moved on two or three generations. We are now at a point where |
+the oldest browsers in current use are already two generations into |
+<span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> versions that formalised script elements. They all know what a |
+script element is and how its contents should be handled. Even |
+browsers that cannot execute scripts know that they are supposed to |
+ignore the content of script elements. |
+</p> |
+ |
+<p> |
+The practice of hiding scripts from "older" browsers has |
+become an anachronism, no longer needed and no longer used by informed |
+javascript authors. It is still often seen because it is recommended |
+in out of date books and in out of date javascript tutorials on the |
+web. And the readers of those books and tutorials continue to use and |
+promote it, not realising that it no longer serves any real purpose. |
+</p> |
+ |
+<p> |
+The existence of this additional comment syntax in javascript included |
+in <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> pages also lead to <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> style comments being used extensively |
+in on-page javascript. This was, and is, a very bad idea. Javascript |
+has end of line and multi-line comment syntaxes and they should be used |
+exclusively to comment javascript source code. |
+</p> |
+ |
+<h3><a name="hsETO" id="hsETO">Closing Script Tags and "</" (end-tag open delimiter)</a></h3> |
+ |
+<p> |
+When a script is included on an <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> page the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> parser needs to |
+decide how much of the page's source text to pass on to the javascript |
+interpreter and where it should start processing other <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> again. |
+Officially an <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> parser is required to take the first occurrence of |
+the character sequence "<code></</code>" it finds after |
+the opening script tag as marking the end of the script element. In |
+practice browsers seem to be a lot more lax and only terminate the |
+script section when they encounter the character sequence |
+"<code></script></code>". |
+</p> |
+ |
+<p> |
+That seems reasonable (if lax) but it does not eliminate all problems. |
+Suppose that a script includes <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> source in the form of a string |
+literal, and that source includes a closing script tag, as might be |
+the case when using <code>document.write</code> to write a new script |
+element to the page:- |
+</p> |
+ |
+<pre> |
+<script type="text/javascript"> |
+document.write( |
+ '<script type="text/javascript" src="scriptFile.js"></script>'); |
+</script> |
+</pre> |
+ |
+<p> |
+That is an example simplified to the point of being futile but it |
+should be obvious that if the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> parser considers the first |
+occurrence of "<code></script></code>" as terminating |
+the script element the results will be undesirable. |
+</p> |
+ |
+<p> |
+The solution is to do something to make the character sequence within |
+the javascript string of <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> different from the sequence that will be |
+recognised as the closing script tag. This is often done by splitting |
+the string and using a concatenation operation to let the script |
+produce the same output:- |
+</p> |
+ |
+<pre> |
+<script type="text/javascript"> |
+document.write( |
+ '<script type="text/javascript" src="scriptFile.js"></scr'+'ipt>'); |
+</script> |
+</pre> |
+ |
+<p> |
+This conceals the closing script tag from the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> parser but it is not |
+a good idea because string concatenation is a surprisingly heavyweight |
+operation and the same goal of disrupting the character sequence that |
+the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> parser will mistake for a closing tag can be achieved by using |
+the javascript escape character to escape any character in the closing |
+script tag:- |
+</p> |
+ |
+<pre> |
+<script type="text/javascript"> |
+document.write( |
+ '<script type="text/javascript" src="scriptFile.js"></script\>'); |
+</script> |
+</pre> |
+ |
+<p> |
+The <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> parser will now not find the character sequence |
+"<code></script></code>" until it encounters the real |
+closing script tag, but the internal representation of the string is not |
+affected by the use of the escape character in the javascript source |
+and no additional operations are needed. |
+</p> |
+ |
+<p> |
+However, as I said, it is the character sequence |
+"<code></</code>" that is officially to be taken as |
+terminating a script element's contents. While no current browsers are |
+known to be that strict it is entirely realistic that some browsers may |
+exist (or be introduced) that takes the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> specifications to hart and |
+treat "<code></</code>" as the end of the script content. |
+But <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> validaters already tend to take the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> specification |
+seriously and will report many mark-up errors as a result of getting |
+the impression that a script element has terminated sooner than a |
+browser would think it had. |
+</p> |
+ |
+<p> |
+The above use of the escape character may placate all known browsers |
+but it will not address the requirements of the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> specification. |
+But they can both be addressed by escaping a different character, |
+specifically the forward slash:- |
+</p> |
+ |
+<pre> |
+<script type="text/javascript"> |
+document.write( |
+ '<script type="text/javascript" src="scriptFile.js"><\/script>'); |
+</script> |
+</pre> |
+ |
+<p> |
+Of course now it is not just the closing script tag that needs to be |
+escaped but all occurrences of closing tags appearing in string |
+literals. All occurrences of "<code></</code>" would need |
+to be escaped to "<code><\/</code>" to completely avoid |
+<span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> parser and validation problems. Alternatively the javascript |
+source could be moved to an external file as then it is never |
+examined by an <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> parser or considered in <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> validation. |
+</p> |
+ |
+<h2><a name="hsExF" id="hsExF">External Javascript Files</a></h2> |
+ |
+<p> |
+Placing javascript source code in external files has several |
+advantages. For those who are required to use a browser that is |
+javascript incapable/disabled it can significantly reduce download |
+time as those browsers just will not bother getting the external file |
+as they have no use for it, scripts on an <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> page must be downloaded |
+with the page if the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> is to be used. |
+</p> |
+ |
+<p> |
+External javascript files can also be cached separately from <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> pages |
+so they may need to be downloaded less often even for the users of |
+javascript capable/enabled browsers. |
+</p> |
+ |
+<p> |
+They entirely remove the need to worry about script hiding (no longer |
+needed anyway), escaping <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> closing tags in strings or any other |
+factors relating to the parsing of mark-up languages. |
+</p> |
+ |
+<p> |
+Javascript imported by using the <code>src</code> attribute of a script element is |
+used in place of the content for the script element that imported it. |
+The position of that element in the page defines the |
+"location" of the script in the document. If the file |
+executes <code>document.write</code> then any content written will be |
+inserted following the script element that imported the file, and any |
+other elements on the page referenced by that script as it loads will |
+need to have already been parsed by the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> parser at that point or |
+they will not be found in the DOM. |
+</p> |
+ |
+<h3><a name="hsExC" id="hsExC">The Content of External Javascript Files.</a></h3> |
+ |
+<p> |
+Javascript files imported using the <code>src</code> attribute of script elements |
+must contain <em>only</em> javascript source code. They must not contain any |
+<span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span>. It is a surprisingly common error for opening and closing script |
+tags and/or the "hide from older browsers" <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> comment |
+tags to be included in external script files, in that context they are |
+javascript syntax errors and nothing else. |
+</p> |
+ |
+<h2><a name="hsMix" id="hsMix">Script Elements that Import Javascript Files and Have Contents</a></h2> |
+ |
+<p> |
+Script elements may attempt to both import a file and contain script |
+contents. The idea here is to provide some scripted action in the event |
+that the external file cannot be loaded for some reason. Such a script |
+element may look like:- |
+</p> |
+ |
+<pre> |
+<script type="text/javascript" src="../scripts/scriptFile.js"> |
+ var externalScriptLoaded = false; |
+</script> |
+</pre> |
+ |
+<p> |
+The browser should handle this formulation of the script element by |
+attempting to load the external file, but in the even of that attempt |
+failing instead the contents of the script element are executed. So, in |
+the example above, if the external file is loaded and executed the |
+contents of the element would not be executed. That external file |
+would itself define the <code>externalScriptLoaded</code> global |
+variable and assign it a value of boolean <code>true</code>. If the |
+file did not load the contents would be executed, again creating |
+the <code>externalScriptLoaded</code> variable, but this time |
+assigning it a <code>false</code> value. Another script on the page |
+can then read the <code>externalScriptLoaded</code> variable as a |
+means of determining whether the external script loaded successfully. |
+</p> |
+ |
+<p> |
+The definition of failing to load an external script is centred |
+around <span class="initialism" title="HyperText Transfer Protocol "> |
+<abbr title=" Transfer Protocol ">HTTP</abbr></span>. If no connection |
+to the server can be made, or an |
+<span class="initialism" title="HyperText Transfer Protocol "> |
+<abbr title=" Transfer Protocol ">HTTP</abbr></span> error response, |
+such as <code>404</code>, is returned, then the external script has |
+failed to load and the browser can execute the contents of the |
+element. However, many servers are set up in such a way that they |
+do not actually return the expected |
+<span class="initialism" title="HyperText Transfer Protocol "> |
+<abbr title=" Transfer Protocol ">HTTP</abbr></span> error responses, |
+but instead return an <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> page that is intended to inform the user |
+of the error. This is fine for humans but from the point of view of |
+the browser such a response is indistinguishable from a returned |
+(but erroneous) javascript source file (This is in part because |
+the browser disregards content-type headers sent with external |
+javascript files so even if the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> error reporting page is sent |
+with a text/html content type the browser will still assume that |
+it contains javascript source). The browser attempts to |
+execute the returned <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> source as javascript and fails at the |
+first inevitable syntax error. But erroring while executing what |
+the browser thought was an external javascript file does not |
+result in the execution of the code within the script element. |
+</p> |
+ |
+<p> |
+In practice script elements are rarely used where an external |
+file is imported and script contents are provided for the element. |
+If a separate script wanted to verify that an externally imported |
+script was available it would not need the mechanism demonstrated |
+in the example above as javascript provides many ways of verifying |
+the existence of javascript defined entities. So, for example, if |
+the external script defined a function called <code>functionName</code>, the |
+availability of that function could be verified as:- |
+</p> |
+ |
+<pre> |
+if(typeof functionName == "function"){ |
+ functionName(); |
+} |
+</pre> |
+ |
+<p> |
+- and if a function defined in an external file is available then |
+that external file must have been successfully loaded. |
+</p> |
+ |
+<h2><a name="hsEh" id="hsEh">Event Handling Attributes: Intrinsic Events</a></h2> |
+ |
+<p> |
+The final place where javascript can be included in an <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> document is |
+as the value strings provided for event handling attributes. |
+</p> |
+ |
+<p> |
+The values of event handling attributes will almost certainly need to |
+be quoted because it is nearly impossible to write a javascript |
+statement that only uses the characters allowed in an unquoted |
+attribute value. And quoting can get quite involved in attribute values |
+because they need to be quoted in the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> source so whatever type of |
+quote marks are used in the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> cannot be used within the javascript |
+code provided as the value because the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> parser would take them as |
+ending the string for the attribute value. While javascript string |
+literals allow the use of double quotes or single quotes as delimiters |
+and allow the type of quote not used as the delimiter to appear within |
+the string literal unescaped. |
+</p> |
+ |
+<p> |
+So, given a desire to assign the string <code>"don't do |
+that"</code> to an element's value property in an onclick event, |
+because of the single quote appearing in the string itself the attribute |
+value <code>onclick='this.value = "don't do that";'</code> |
+will not work because the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> parser will take the second single quote |
+as ending the attribute value. It will not work to simply escape the |
+single quote as <code>onclick='this.value = "don\'t do |
+that";'</code> because the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> parser doesn't know anything about |
+javascript escapes and still sees the second single quote in the middle |
+of the javascript string. |
+</p> |
+ |
+<p> |
+In this case escaping the single quote and reversing the quoting |
+between the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> and the javascript |
+<code>onclick="this.value = 'don\'t do that';"</code> or |
+using a javascript hex escape (which the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> parser will not see as a |
+quote) <code>onclick='this.value = "don\x27t do that";'</code> |
+would solve the problem. But quotes in event handling attribute strings |
+that define code that uses string literals often needs to be thought |
+about. |
+</p> |
+ |
+<h3><a name="hsEhD" id="hsEhD">The Default Language for Intrinsic Events</a></h3> |
+ |
+<p> |
+All else being equal, web browsers seem to all default the scripting |
+language used with intrinsic events to javascript (ECMAScript, in |
+whichever implementation is provided) and there is no formal mechanism |
+for associating a scripting language with individual event handling |
+attributes (unlike script elements which must be provided with a |
+<code>type</code> attribute). |
+</p> |
+ |
+<p> |
+The <span class="initialism" title="HyperText Mark-up Language"> |
+<abbr title="HyperText Mark-up Language">HTML</abbr></span> |
+specification calls for a page wide default scripting language |
+to be set, and that is the only specified way to set the scripting |
+language for intrinsic events. |
+</p> |
+ |
+<p> |
+To this end The <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> specification proposes the inclusion in the |
+<code>HEAD</code> section of a page of a <code>META</code> tag:- |
+</p> |
+ |
+<blockquote cite="http://www.w3.org/TR/html4/interact/scripts.html#h-18.2.2.1"> |
+<pre> |
+<meta http-equiv="Content-Script-Type" content="text/javascript"> |
+</pre> |
+</blockquote> |
+ |
+<p> |
+This is supposed to assert the default type of script language on a |
+page (possibly overridden by the (required) <code>type</code> |
+attributes provided for individual script elements). As a result it |
+is <em>formally correct</em> to include this tag in <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> 4.01 documents |
+(or provide a corresponding <span class="initialism" title="HyperText Transfer Protocol "><abbr title=" Transfer Protocol ">HTTP</abbr></span> header when the page is served). |
+</p> |
+ |
+<p> |
+However, there is no evidence that any current browsers pay any attention to |
+this <code>META</code> element at all (or would have any interest in a corresponding |
+<span class="initialism" title="HyperText Transfer Protocol "><abbr title=" Transfer Protocol ">HTTP</abbr></span> |
+header), but then there are not many browsers that can execute any |
+scripting language but javascript. This entire proposed mechanism |
+has also been subject to criticism, and many recommend disregarding |
+it entirely in favour of relying on the tendency of browsers to |
+default to interpreting intrinsic event code as javascript. |
+</p> |
+ |
+<h2><a name="hsNs" id="hsNs">NOSCRIPT Elements</a></h2> |
+ |
+<p> |
+The general idea of a <code>NOSCRIPT</code> element is to provide a |
+holder for <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> marked-up content |
+that will only be displayed when scripting is not enabled/available on |
+a web browsers. At first sight this seems to be a useful idea, and a |
+contribution towards providing clean degradation in circumstances where |
+scripts cannot be executed. Showing content that would be a substitute |
+for any content that would otherwise have been provided by a script. |
+</p> |
+ |
+<p> |
+However, <code>SCRIPT</code> and <code>NOSCRIPT</code> elements are not |
+actually directly substitutable in |
+<span class="initialism" title="HyperText Mark-up Language"> |
+<abbr title="HyperText Mark-up Language">HTML</abbr></span>. That is, you |
+cannot use a <code>NOSCRIPT</code> element in all of the contexts in |
+which you can use a <code>SCRIPT</code> element and produce valid |
+<span class="initialism" title="HyperText Mark-up Language"> |
+<abbr title="HyperText Mark-up Language">HTML</abbr></span> as a result. |
+</p> |
+ |
+<p> |
+The <span class="initialism" title="HyperText Mark-up Language"> |
+<abbr title="HyperText Mark-up Language">HTML</abbr></span> DTDs |
+categories <code>SCRIPT</code> and <code>NOSCRIPT</code> differently: |
+<code>SCRIPT</code> is an <code>%inline</code>, <code>%special</code> or <code>%head.misc</code> element, |
+it may appear in the <code>HEAD</code> of a document (as a child of |
+a <code>HEAD</code> element (<code>%head.misc</code>)), or in any context that |
+allows inline or <code>%special</code> content (descendants of the <code>BODY</code> |
+element, but not in all contexts). The <code>NOSCRIPT</code> element |
+is categorised as <code>%block</code>, and as a result it cannot appear in the |
+<code>HEAD</code> at all, and may only appear in the body in a context |
+that allows <code>%block</code> content (<code>%flow</code> or <code>%block</code> but not <code>%inline</code>). This |
+means that the one cannot always stand as a direct substitute for the |
+other in a valid <span class="initialism" title="HyperText Mark-up Language"> |
+<abbr title="HyperText Mark-up Language">HTML</abbr></span> document. |
+</p> |
+ |
+<p> |
+<span class="initialism" title="HyperText Mark-up Language"> |
+<abbr title="HyperText Mark-up Language">HTML</abbr></span> <code>NOSCRIPT</code> |
+elements probably seemed like a good idea when they were first introduced. |
+They were probably even viable at the time because so few browsers were |
+able to execute javascript that a division between <code>SCRIPT</code> |
+and <code>NOSCRIPT</code> could encompass all of the possibilities. The |
+problem with them now is the diversity of javascript capable web |
+browsers, with their differing object models and language implementations. |
+</p> |
+ |
+<p> |
+While it remains the case that any browser on which scripting is disabled |
+or unavailable will use any <code>NOSCRIPT</code> elements provided in |
+an <span class="initialism" title="HyperText Mark-up Language"> |
+<abbr title="HyperText Mark-up Language">HTML</abbr></span> page, it is not the |
+case that all javascript supporting and enabled browsers will be able |
+to successfully execute any script specified within (or imported by) a |
+<code>SCRIPT</code> element. The browser may lack the features needed |
+by the script, or just not be sufficiently dynamic to present any |
+content that the script intends to insert into the document. |
+</p> |
+ |
+<p> |
+Even browser features as seemingly universal as the |
+<code>document.write</code> function are not universally supported |
+(even on modern browsers), and anything even remotely dynamic is bound |
+to fail somewhere. So instead of having to cope with two certain |
+outcomes, successful execution and no script execution at all, it is |
+actually necessary to cope with 3 possible outcomes, adding the |
+possibility that scripting is supported by the browser but the features |
+required by any individual script are not available. In that third |
+case the script fails to provide what it was intended to provide, but |
+the contents of the <code>NOSCRIPT</code> elements are not presented |
+either. |
+</p> |
+ |
+<p> |
+This effectively renders <code>NOSCRIPT</code> elements next to |
+useless when it comes to providing clean degradation. They leave |
+an unbridgeable gap between browsers unwilling or unable to execute |
+scripts at all and browsers that will fully support any given script. |
+And whatever content seemed to make sense within those |
+<code>NOSCRIPT</code> elements must also make sense in the context |
+of a javascript capable browser that does not support the features |
+required by a script. |
+</p> |
+ |
+<p> |
+Recognising a requirement for clean degradation in script design, |
+and the inability of <code>NOSCRIPT</code> elements to contribute |
+towards facilitating it, many recommend never using |
+<code>NOSCRIPT</code> elements. Instead providing content that |
+works in place of active script support within the |
+<span class="initialism" title="HyperText Mark-up Language"> |
+<abbr title="HyperText Mark-up Language">HTML</abbr></span> and then |
+having their scripts remove, or transform by manipulation, that |
+content only when the browser proves sufficiently supportive for |
+the script to be viable. This technique allows the design to only |
+consider two conditions; the browser fully supports the script |
+and will execute it, or the browser does not support the scripts |
+so whatever was originally included in the |
+<span class="initialism" title="HyperText Mark-up Language"> |
+<abbr title="HyperText Mark-up Language">HTML</abbr></span> will be |
+what the user is exposed to. |
+</p> |
+ |
+<p id="rToc"> |
+<a href="faq_notes.html#toc">comp.lang.javascript FAQ notes T.O.C.</a> |
+</p> |
+ |
+</body> |
+</html> |
\ No newline at end of file |
/cljs/faq_notes/script_tags.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/faq_notes/cljs_charter.html |
=================================================================== |
--- cljs/faq_notes/cljs_charter.html (nonexistent) |
+++ cljs/faq_notes/cljs_charter.html (revision 2) |
@@ -0,0 +1,146 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
+<html lang="en"><head><title>CALL FOR VOTES -- comp.lang.javascript</title> |
+<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> |
+<link href="../faq.css" rel="stylesheet" type="text/css"> |
+<link href="faq_notes.css" rel="stylesheet" type="text/css"> |
+</head> |
+<body> |
+ |
+<h1><a name="chT" id="chT">The comp.lang.javascript Charter</a></h1> |
+ |
+<p> |
+The following is the text of the last Call For Votes (CFV) that |
+resulted in the creation of the comp.lang.javascript newsgroup |
+(as extracted from the archives at google groups). It defines |
+the Charter for the proposed group, and as the vote was successful |
+the charter as stated below is the charter currently in force for |
+the comp.lang.javascript. |
+</p> |
+ |
+<pre> |
+LAST CALL FOR VOTES (of 2) |
+ unmoderated group comp.lang.javascript |
+ |
+Newsgroups line: |
+comp.lang.javascript Netscape Communications Corp.'s JavaScript language. |
+ |
+Votes must be received by 23:59:59 UTC, 26 Jan 1996. |
+ |
+This vote is being conducted by a neutral third party. Questions |
+about the proposed group should be directed to the proponent. |
+ |
+Proponent: Thomas Winzig <thomas.winzig@webcom.com> |
+Votetaker: Steve Bonine <spb@ntrs.com> |
+ |
+RATIONALE: comp.lang.javascript |
+ |
+Since Netscape Communication Corp.'s release of the Java-complementary |
+scripting language, JavaScript, there has been a steady increase in |
+the amount of JavaScript related questions and discussion in the |
+comp.lang.java usenet newsgroup. Since these two languages are |
+distinctly different, and might draw discussion from two generally |
+different 'crowds' (professional programmers and casual programmers), |
+I formally propose the creation of comp.lang.javascript for discussion |
+of everything related to the JavaScript scripting language. |
+ |
+At this point in time, with JavaScript still in Beta test, the amount |
+of JavaScript related postings to comp.lang.java is "acceptable" by |
+most. However, as JavaScript reaches completion, there will need to be |
+a place for it's separate discussion. |
+ |
+Truthfully, the JavaScript newsgroup could fit into a number of UseNet |
+heirarchies, but I think the moderator of comp.infosystems.www.announce |
+(M. L. Grant) explained it best when he said: |
+ |
+"...since javascript is different from java itself, it should be |
+in its own hierarchy. A sixteenth comp.infosystems.www.* newsgroup |
+is not needed; and putting it in the java groups will encourage the |
+same confusion that comp.windows endures (HINT: the group is *not* |
+about Microsoft operating systems)." |
+ |
+CHARTER: comp.lang.javascript |
+ |
+The proposed comp.lang.javascript will be open to discussion on all |
+aspects of JavaScript, as it relates to HTML, Java, Perl, the World |
+Wide Web in general, and other related languages. The scope of |
+discussion will specifically exclude matters which are *solely* |
+related to Sun Microsystems, Inc.'s Java language, which should be |
+discussed in comp.lang.java. |
+ |
+END CHARTER. |
+ |
+HOW TO VOTE: |
+ |
+Send E-MAIL (posts to a newsgroup are not votes) to: |
+ |
+ voting@ntrs.com |
+ |
+Replying to this article should work, but check the address before you mail |
+your vote. Your mail message must contain one and only one of the following |
+vote statements for each group: |
+ |
+ I vote YES on comp.lang.javascript |
+ I vote NO on comp.lang.javascript |
+ |
+Names are required for this vote. The counting software will extract your name |
+from the mail message if your mailer is properly configured; if your mail |
+software does not indicate your name, you must include the following statement: |
+ |
+ Voter name: Your name here |
+ |
+You can also vote ABSTAIN or CANCEL. These votes are not counted in the |
+results, and CANCEL removes your name from the vote listing in the result. |
+ |
+Vote counting is automated. Failure to follow these directions may mean that |
+your vote does not get counted. If you do not receive an acknowledgment of |
+your vote within three days contact the votetaker about the problem. IT'S YOUR |
+RESPONSIBILITY TO MAKE SURE YOUR VOTE IS REGISTERED CORRECTLY. |
+ |
+If you wish to change your vote, simply vote again from the same account; |
+duplicate votes are resolved in favor of the most recent vote. |
+ |
+THIS IS NOT A SECRET VOTE. Names, addresses, and votes will be published in |
+a RESULTS article in the same newsgroups in which this CFV appears. |
+ |
+The purpose of a Usenet vote is to determine if there is sufficient interest in |
+the Usenet community to create a new newsgroup. Soliciting votes from |
+disinterested parties defeats this purpose. Please do not distribute this CFV; |
+direct people to the CFV in news.announce.newgroups. Distributing pre-marked |
+or edited copies of this CFV is prohibited, and votes from such sources will be |
+removed from the final vote total. |
+ |
+Standard Guidelines for voting apply. One person, one vote. Votes must be |
+mailed directly from the voter to the votetaker. Anonymous, forwarded or proxy |
+votes are not valid. Votes mailed by WWW servers are considered to be |
+anonymous votes. |
+</pre> |
+ |
+<p> |
+In my opinion the charter says little that isn't obvious, but it |
+also exhibits symptoms of its historic origin; an attempt to avoid |
+javascript questions being asked in comp.lang.java groups. 50% of |
+the charter's text being devoted to excluding the discussion of the |
+Java language |
+</p> |
+ |
+<p> |
+In a modern context the subject of the group is interpreted as being |
+all ECMAScript implementations as that is the standard that |
+JavaScript (TM) now implements, and it is the implementation of that |
+standard that allows other languages to be categorised as javascript. |
+</p> |
+ |
+<p> |
+No applications of javascript/ECMAScript are excluded from discussion |
+on the group, and the group's apparent bias towards web browser |
+scripting for the Internet is a consequence of the historical origin |
+of the language, and the fact that browser scripting remains its most |
+common application. |
+</p> |
+ |
+<p id="rToc"> |
+<a href="faq_notes.html#toc">comp.lang.javascript FAQ notes T.O.C.</a> |
+</p> |
+ |
+</body> |
+</html> |
\ No newline at end of file |
/cljs/faq_notes/cljs_charter.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/faq_notes/faq_notes.css |
=================================================================== |
--- cljs/faq_notes/faq_notes.css (nonexistent) |
+++ cljs/faq_notes/faq_notes.css (revision 2) |
@@ -0,0 +1,51 @@ |
+P CODE, LI CODE { |
+ background-color:#FFFFDD; |
+ color:#000000; |
+ padding:0; |
+ margin:0; |
+} |
+BLOCKQUOTE { |
+ background-color:#EEEEFF; |
+ color:#000000; |
+ padding:0.5em; |
+} |
+BLOCKQUOTE DD PRE, BLOCKQUOTE DD CODE { |
+ background-color:#EEEEFF; |
+ color:#000000; |
+ border:#EEEEFF 0px none; |
+ margin:0.5em; |
+ padding:0; |
+} |
+BLOCKQUOTE DT { |
+ font-weight:bold; |
+ margin-bottom:0.5em; |
+} |
+.commentJS { |
+ background-color:#FFFFCC; |
+ color:#004800; |
+} |
+.person { |
+ font-weight:bold; |
+} |
+.fn { |
+ text-align:left; |
+ color:#B00000; |
+ } |
+.ob { |
+ color:#AA6500; |
+} |
+.st { |
+ color:#0000DD; |
+} |
+.nm { |
+ color:#006000; |
+ } |
+.bl{ |
+ color:#003444; |
+} |
+.un { |
+ color:#666666; |
+} |
+DL { |
+ MARGIN-TOP: 0.5em; FONT-SIZE: 100%; MARGIN-BOTTOM: 0.5em; MARGIN-LEFT: 2.5em |
+} |
\ No newline at end of file |
/cljs/faq_notes/faq_notes.css |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/faq_notes/form_access.html |
=================================================================== |
--- cljs/faq_notes/form_access.html (nonexistent) |
+++ cljs/faq_notes/form_access.html (revision 2) |
@@ -0,0 +1,729 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" |
+ "http://www.w3.org/TR/html4/strict.dtd"> |
+<html lang="en"> |
+<head><title>Referencing Forms and Form Controls</title> |
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> |
+<link href="../../faq.css" rel="stylesheet" type="text/css"> |
+<link href="../notes.css" rel="stylesheet" type="text/css"> |
+<style type="text/css"> |
+.commentJS { |
+ background-color: #FFFFCC; |
+ color: #004800; |
+} |
+P CODE { |
+ background-color: #FFFFDD; |
+ color: #000000; |
+ padding: 0ex; |
+ margin: 0ex; |
+} |
+</style> |
+</head> |
+<body> |
+ |
+<h1 id="faHead">Referencing Forms and Form Controls</h1> |
+<div id="faqNav"> |
+ <a href="../../">FAQ</a> > <a href="../">FAQ Notes</a> |
+</div> |
+ |
+<ul> |
+ <li><a href="#faInt">Introduction</a> |
+ <ul> |
+ <li><a href="#faInF">Forms</a></li> |
+ <li><a href="#faInC">Form Controls</a></li> |
+ </ul> |
+ </li> |
+ <li><a href="#faShrt">Shortcut Accessors</a></li> |
+ <li><a href="#faComMis">The Most Common Mistake</a></li> |
+ <li><a href="#faAnon">Anonymous Form References</a></li> |
+ <li><a href="#faBut">Radio Button and Other Control Collections</a></li> |
+ <li><a href="#faEff">Efficient use of Form Accessors</a></li> |
+</ul> |
+ |
+<h2 id="faInt">Introduction</h2> |
+<h3 id="faInF">Forms</h3> |
+<p id="faInF_1"> |
+When the W3C defined the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> DOM specification much of what they included |
+represented a formalisation of existing browser behaviour. In particular they |
+defined "convenience" properties on the <code>HTMLDocument</code> |
+interface that reproduce document level collections common in preceding |
+browsers. Of specific interest here is the <code>document.forms</code> |
+collection, which makes all of the <code>FORM</code> elements on a page |
+available as (zero based) indexed members of the collection. Allowing, |
+for example, the second <code>FORM</code> element on a page to be |
+referenced as:- |
+</p> |
+ |
+<pre id="faInF_ex1"> |
+var formElement = document.forms[1]; |
+</pre> |
+ |
+<p id="faInF_2"> |
+<span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> (but not necessarily XHTML) <code>FORM</code> elements are allowed |
+<code>NAME</code> attributes and the <code>document.forms</code> collection |
+also makes <code>FORM</code> elements with <code>NAME</code> attributes |
+available as named members, under a property name that corresponds with |
+value of the <code>NAME</code> attribute. So given a form with the |
+attribute <code>name="myForm"</code> the form can be referenced |
+as:- |
+</p> |
+ |
+<pre id="faInF_ex2"> |
+var formElement = document.forms.myForm; |
+ |
+<span class="commentJS">/* - or - */</span> |
+ |
+var formElement = document.forms["myForm"]; |
+ |
+<span class="commentJS">/* The latter, bracket notation, does not impose the same restrictions |
+ on the character sequence used for the name as is imposed by the |
+ preceding dot notation, which is restricted to only using character |
+ sequences that would fulfill the ECMAScript definition of an |
+ identifier. |
+ |
+ Bracket notation is often preferred when accessing form elements as |
+ it helps to document itself by making it clear in the source code |
+ which property names originate in the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> rather than the DOM. |
+*/</span> |
+</pre> |
+ |
+<p id="faInF_3"> |
+The <code>document.forms</code> collection had exhibited this behaviour |
+in all of the preceding browsers that implemented it (which included |
+all the browsers that understood what a form was) and as a result |
+represents the most cross-browser method of accessing <code>FORM</code> |
+elements. It is both W3C <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> DOM standard compliant and |
+back-compatible with pre-existing browsers. |
+</p> |
+ |
+<p id="faInF_4"> |
+The W3C went on to require <code>FORM</code> elements with |
+<code>ID</code> attributes to also be made available as named properties |
+of the <code>document.forms</code> collection. That represented a |
+formalisation of behaviour already exhibited in IE 4 but not by |
+Netscape 4 (and earlier). Referencing <code>ID</code>ed <code>FORM</code> |
+elements as named properties of the <code>document.forms</code> collection |
+should work reliably in all W3C <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> DOM compliant browsers but some |
+back-compatibility will be sacrificed if <code>ID</code>s are used instead |
+of <code>NAME</code>s (though not nearly as much as would be lost if |
+<code>ID</code>ed form elements were referenced using the |
+<code>document.getElementById</code> method). |
+</p> |
+ |
+<p id="faInF_5"> |
+When writing <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> that conforms to a DTD that allows <code>FORM</code> |
+elements to have <code>NAME</code> attributes it is possible to also give |
+the <code>FORM</code> element an <code>ID</code> attribute that corresponds |
+with its <code>NAME</code> attribute (so long as the <code>ID</code> is |
+unique on the page). The form will appear as a member of the |
+<code>document.forms</code> collection under a property name that |
+corresponds with the value of the <code>NAME</code> and <code>ID</code> |
+attributes (as they are identical). |
+</p> |
+ |
+<h3 id="faInC">Form Controls</h3> |
+ |
+<p id="faInC_1"> |
+Traditionally browsers that implemented the <code>document.forms</code> |
+collection also made the controls within a form available as a |
+collection accessible as a property of the <code>FORM</code> element |
+under the name <code>elements</code>. The W3C <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> DOM also formalised |
+this collection in the <code>HTMLFormElement</code> interface. |
+Controls within a form can be referenced as integer indexed members of |
+that collection:- |
+</p> |
+ |
+<pre id="faInC_ex1"> |
+var formElement = document.forms["myForm"]; |
+var controlElement = formElement.elements[2]; <span class="commentJS">//Third control in the form.</span> |
+</pre> |
+ |
+<p id="faInC_2"> |
+Controlls with <code>NAME</code> attributes are again made available as |
+named properties of the collection. So a control with |
+<code>name="myControl"</code> can be referenced as:- |
+</p> |
+ |
+<pre id="faInC_ex2"> |
+var controlElement = formElement.elements["myControl"]; |
+</pre> |
+ |
+<p id="faInC_3"> |
+Again the W3C also specified that controls with <code>ID</code> |
+attributes should be made available as named members of the |
+elements collection under their <code>ID</code>s (with the same |
+implications for back-compatibility with really ancient browsers). |
+All official (x)<span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> DTDs allow form controls to have |
+<code>NAME</code> attributes because without a <code>NAME</code> |
+attribute the value of the control cannot be sent as a |
+name/value pair when the form is submitted. |
+</p> |
+ |
+<h2 id="faShrt">Shortcut Accessors</h2> |
+ |
+<p id="faShrt_1"> |
+In addition to making named <code>FORM</code> elements available |
+as named properties of the <code>document.forms</code> collection |
+web browsers also make them available as named properties of the |
+<code>document</code> object. So:- |
+</p> |
+ |
+<pre id="faShrt_ex1"> |
+var formElement = document.myForm; |
+</pre> |
+ |
+<p id="faShrt_2"> |
+-will reference the same FORM element as:- |
+</p> |
+ |
+<pre id="faShrt_ex2"> |
+var formElement = document.forms.myForm; |
+</pre> |
+ |
+<p id="faShrt_3"> |
+And the same is true using bracket notation:- |
+</p> |
+ |
+<pre id="faShrt_ex3"> |
+var formElement = document["myForm"]; |
+ |
+<span class="commentJS">/* instead of:- */ </span> |
+ |
+var formElement = document.forms["myForm"]; |
+</pre> |
+ |
+<p id="faShrt_4"> |
+The W3C did not include this shortcut in the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> DOM specifications |
+so code that uses it cannot be described as standards compliant and, |
+while nobody has been able to name an <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> browser where the shortcut |
+accessors do not work when referencing named <code>FORM</code> |
+elements, it would still be possible for a future standards compliant |
+browser not to support the shortcut accessors. |
+</p> |
+ |
+<p id="faShrt_5"> |
+<code>FORM</code> elements that only have <code>ID</code> attributes |
+cannot be accessed as properties of the <code>document</code> object |
+under a property name that corresponds with their <code>ID</code> |
+attributes. While by W3C <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> DOM specification (but not necessarily |
+on older browsers) <code>ID</code>ed forms are made available as named |
+properties of the <code>document.forms</code> collections under a |
+property name that corresponds with the <code>ID</code>. |
+</p> |
+ |
+<p id="faShrt_6"> |
+Form controls can be referenced as named properties of the |
+<code>FORM</code> element that contains them with a shortcut accessor:- |
+</p> |
+ |
+<pre id="faShrt_ex4"> |
+var formControl = formElement.myControl; |
+ |
+<span class="commentJS">/* instead of :- */</span> |
+ |
+var formControl = fromElement.elements.myControl; |
+</pre> |
+ |
+<p id="faShrt_7"> |
+But in the case of form controls, elements with <code>ID</code> |
+attributes may be available as properties of the <code>FORM</code> |
+element under a property name that corresponds with their |
+<code>ID</code> (at least on more recent browsers). |
+</p> |
+ |
+<p id="faShrt_8"> |
+The main argument in favour of using shortcut accessors (apart from the |
+reduced amount of typing) is that they are resolved fractionally quicker |
+than accessors that employ the <code>forms</code> and |
+<code>elements</code> collections. That follows from the fact that fewer |
+object references need to be resolved before the reference to the element |
+of interest is returned. |
+</p> |
+ |
+<p id="faShrt_9"> |
+While arguments against the shortcut accessors point out that named image, |
+embed and other elements are also made available as named properties of |
+the <code>document</code> object, making it ambiguous when reading the |
+source code whether the shortcut accessor is referring to a form or some |
+other named property of the <code>document</code> object. When a |
+<code>FORM</code> element is referenced as a member of the |
+<code>document.forms</code> collection, or a control as a member of the |
+<code>elements</code> collection, there can be no doubt while reading |
+the source code as to the type of element that is the subject of the |
+reference. |
+</p> |
+ |
+<h2 id="faComMis">The Most Common Mistake</h2> |
+ |
+<p id="faComMis_1"> |
+The most common mistake made when defining the form <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> that a script |
+will interact with follows from the existence of the shortcut accessors |
+for form controls. It is to give the control a <code>NAME</code> (or |
+possibly <code>ID</code>) that corresponds with an existing property of |
+<code>FORM</code> elements. And the most common example of that is an |
+<code>INPUT</code> element of <code>type="submit"</code> with |
+the <code>NAME</code> "submit". Because the named controls are |
+made available as named properties of the <code>FORM</code> element this |
+<code>INPUT</code> element is made available under the property name |
+<code>"submit"</code>. Unfortunately <code>FORM</code> elements |
+already have a property with the name <code>"submit"</code>, it |
+is the <code>submit</code> method that can be used to submit the form |
+with a script. The misguided choice of name for the <code>INPUT</code> |
+element effectively renders the form's <code>submit</code> method |
+unscriptable. And the same is true for all controls with names that |
+correspond any with existing <code>FORM</code> element properties. |
+</p> |
+ |
+<p id="faComMis_2"> |
+Because ECMAScript is case sensitive it may only be necessary to |
+capitalise the name of the <code>INPUT</code> element to avoid the |
+conflict. However, it would probably be safest to adopt a naming |
+convention for form controls that ensured that they do not |
+correspond with existing properties of the <code>FORM</code> elements |
+regardless of case. Especially as theW3C <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> specification implies |
+that referring to named properties of collections can be case |
+insensitive in <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> DOMs. In reality I don't know of any |
+implementations in which it is but it would be better to err on the side |
+of caution. |
+</p> |
+ |
+<p id="faComMis_3"> |
+Another naming conflict that should be avoided would arise if named form |
+controls had names that correspond with the string representations of |
+integers, such as <code>name="1"</code> as they will almost |
+certainly result in inconsistent results (across browsers) when being |
+referenced because the controls are already available by integer index |
+and it would become unclear which control was being referenced by |
+accessors such as <code>formElement.elements[1]</code> or |
+<code>formElement.elements["1"]</code> (by the ECMAScript |
+specification the preceding two property accessors are equivalent). |
+Unless the control with the name <code>"1"</code> also |
+happened to be the control with the index 1. This problem would also |
+apply to <code>FORM</code> elements within the <code>document.forms</code> |
+collection. |
+</p> |
+ |
+<p id="faComMis_4"> |
+Generally it is best to only give form controls names that cannot |
+conflict with existing properties of <code>FORM</code> elements |
+and <code>FORM</code> elements names that cannot conflict with |
+existing properties of the <code>document.forms</code> collection |
+or the <code>document</code> object. |
+</p> |
+ |
+<h2 id="faAnon">Anonymous Form References</h2> |
+ |
+<p id="faAnon_1"> |
+Because <code>FORM</code> elements are available as integer indexed |
+member of the <code>document.forms</code> collection it is not |
+necessary to know the name of a form (or for the form to have a |
+name) to acquire a reference to it. While being able to refer to a |
+form anonymously with its index might seem like a good approach |
+towards making more general/flexible functions for form validation |
+and the like, in practice referring to forms by their index actually |
+makes code less flexible and harder to maintain. As soon as the |
+number or layout of forms on a page is changed their indexes also |
+change, requiring that all of the references by index be located |
+and altered. |
+</p> |
+ |
+<p id="faAnon_2"> |
+One method of avoiding having to know the name of a <code>FORM</code> |
+element within a function that is to act upon a form is to pass a |
+reference to the form object as an argument in the function call. |
+This is easiest achieved from the code provided as the value for |
+an event handling attribute because that code is used by the browser |
+to create an event handling function that is assigned as a method of |
+the element to which it is attached. And in any function executed as |
+a method of an object the <code>this</code> keyword is a reference to |
+the object with which the execution of the method is associated. The |
+most common need to anonymously pass a reference to a <code>FORM</code> |
+element is as an argument to a form validation function in the |
+onsubmit handler of the form. In that case the event handling function |
+is a method of the <code>FORM</code> element so the <code>this</code> |
+keyword refers to the form directly:- |
+</p> |
+ |
+<pre id="faAnon_ex1"> |
+function validateForm(formRef){ |
+ <span class="commentJS">/* Use the reference to the form passed as the formal |
+ parameter - formRef - to acquire a reference to the form |
+ control with the name "textField": |
+ */</span> |
+ var el = formRef && formRef.elements["textField"]; |
+ <span class="commentJS">/* If the control reference exists return its value property |
+ converted to a boolean value (false if empty, true otherwise) |
+ else return true so the form is submitted and the server can |
+ do the validation: |
+ */</span> |
+ return !el || Boolean(el.value); |
+} |
+... |
+<form action="http://example.com/somePage.asp" |
+ onsubmit="return validateForm(this);"> |
+ <input type="text" name="textField" value=""> |
+ <input type="submit" name="Submit_Button" value="Submit"> |
+</form> |
+</pre> |
+ |
+<p id="faAnon_3"> |
+Because the above function receives the reference to the form that it |
+is to validate as an argument when it is called it can also be used |
+with any number of other forms. Although in the case of the above |
+function each of those forms would need to contain a field called |
+<code>"textField"</code>, but that string name could also be |
+passed as an argument, making the function more general. |
+</p> |
+ |
+<p id="faAnon_4"> |
+Form control objects all have a property named |
+<code>"form"</code> that holds a reference to the |
+<code>FORM</code> element that contains them. As a result the event |
+handling functions attached to form controls can pass an anonymous |
+reference to the form that contains them as <code>this.form</code>. |
+Obviously a function called from an event handler on a control can |
+be passes an anonymous reference to the control itself as |
+<code>this</code>. |
+</p> |
+ |
+<h2 id="faBut">Radio Button and Other Control Collections</h2> |
+ |
+<p id="faBut_1"> |
+Radio button controls work to provide a selection of one item of many |
+when each of the radio button alternatives has the same |
+<code>NAME</code> attribute. But it is also possible to give other types |
+of control the same <code>NAME</code> attribute. |
+</p> |
+ |
+<p id="faBut_2"> |
+When controls that share the same <code>NAME</code> attribute they can |
+still be accessed as integer indexed members of the <code>FORM</code> |
+element's <code>elements</code> collection but when the member of the |
+<code>elements</code> collection is accessed using the <code>NAME</code> |
+attribute value as a property name browsers return a collection all of |
+the elements with the corresponding NAME attributes. So given the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span>:- |
+</p> |
+ |
+<pre id="faBut_ex1"> |
+<form name="testForm" action="http://example.com/somePage.jsp"> |
+ <ul style="list-style-type:none;"> |
+ <li><input type="radio" name="radioSet" value="R1">option 1</li> |
+ <li><input type="radio" name="radioSet" value="R2">option 2</li> |
+ <li><input type="radio" name="radioSet" value="R3">option 3</li> |
+ <li><input type="radio" name="radioSet" value="R4">option 4</li> |
+ </ul> |
+ <input type="submit" name="Submit_Button" value="Send"> |
+</form> |
+</pre> |
+ |
+<p id="faBut_3"> |
+A property accessor referring to the member of the <code>FORM</code>'s |
+<code>elements</code> collection by the property name |
+<code>"radioSet"</code> will not return a reference to any one |
+of the named radio buttons but instead returns a collection of all of the |
+like-named radio controls. |
+</p> |
+ |
+<p id="faBut_4"> |
+The individual radio buttons within that collection are referred to as |
+integer indexed members of that collection. So to find the button that |
+is checked one might loop through all of the members of the collection |
+of like-named radio buttons and copy a reference to the button with its |
+<code>checked</code> property set to boolean <code>true</code>. |
+</p> |
+ |
+ |
+<pre id="faBut_ex2"> |
+var radioCollection, checkedButton; |
+var frm = document.forms["testForm"]; |
+if(frm){ |
+ radioCollection = frm.elements["radioSet"]; |
+ if(radioCollection){ |
+ <span class="commentJS">/* The collection of like-named radio buttons has a length |
+ property and that is used to limit a for loop:- |
+ */</span> |
+ for(var c = 0;c < radioCollection.length;c++){ |
+ <span class="commentJS">/* The individual radio buttons are accessed as indexed |
+ members of the collection using the loop counter - c |
+ - from the for loop: |
+ */</span> |
+ if(radioCollection[c].checked){ |
+ <span class="commentJS">/* When a radio button element is found with its |
+ checked property set to boolean true a reference |
+ to that element is assigned to the local variable |
+ - checkedButton - and the loop is terminated with |
+ the - break - statement as only one button in a set |
+ of like-named radio buttons will be checked at a |
+ time, so any remaining buttons in the collection |
+ must have checked properties set to false: |
+ */</span> |
+ checkedButton = radioCollection[c]; |
+ break; |
+ } |
+ } |
+ if(checkedButton){ |
+ <span class="commentJS">/* Do something with the reference to the checked radio |
+ button (if any). |
+ */</span> |
+ ... |
+ } |
+ } |
+} |
+</pre> |
+ |
+<p id="faBut_5"> |
+It is not unusual when a form is generated by a server-side script that |
+some forms may have one or more like-named controls. If there is only |
+one control inserted in the form then accessing a member of the |
+<code>elements</code> collection with its name will return a reference |
+to that one control, but if there are multiple elements the returned |
+reference will be to a collection of such controls. While it may be |
+possible to branch client-side code that wants to interact with those |
+controls to handle the two alternatives it adds an unnecessary |
+maintenance burden to do so. |
+</p> |
+ |
+<p id="faBut_6"> |
+As handling a returned collection usually involves looping through that |
+collection the simplest way of implementing the client-side code to |
+deal with both collections and individual controls being returned by |
+named properties of the <code>elements</code> collection is to |
+normalise the references to individual controls so that they can be |
+handled as if they were a collection. Looping through a collection |
+involves using the <code>length</code> property of the collection to |
+limit the loop statement and accessing the controls within the |
+collection by integer index. This is exactly the way in which code |
+would loop through the elements of an <code>Array</code>. To allow a |
+script to handle both possibilities with the same code the return of |
+a reference to an individual control could be detected and then that |
+reference used to create a one-element <code>Array</code>. Subsequent |
+code would then treat the <code>Array</code> as if it was a collection and |
+loop through it, but as there is only one element the loop body would |
+only be executed once. |
+</p> |
+ |
+<pre id="faBut_ex3"> |
+var radioCollection, checkedButton; |
+var frm = document.forms["testForm"]; |
+if(frm){ |
+ radioCollection = frm.elements["radioSet"]; |
+ if(radioCollection){ |
+ <span class="commentJS">/* But the returned reference might not be a collection in this |
+ case. Instead it may be a reference to just one control if |
+ there is only one in this form with the name "radioSet". |
+ If it is a reference to an individual control it is going to |
+ be necessary to normalise it. Because radio button controls |
+ do not have - length - properties and collections do that is |
+ the property that is going to be tested: |
+ */</span> |
+ if(typeof radioCollection.length != "number"){ |
+ <span class="commentJS">/* The length property is not a number so this cannot be a |
+ collection and must be normalised so that the following |
+ loop statement can handle it correctly. Normalisation is |
+ done by making a reference to the control currently |
+ referred to by the - radioCollection - local variable |
+ into the first (and only) element of a new Array object |
+ and then assigning a reference to that array to the - |
+ radioCollection - local variable: |
+ */</span> |
+ radioCollection = [radioCollection]; |
+ } |
+ <span class="commentJS">/* The execution of the body of the - for - loop is limited by |
+ the - length - property of the collection/Array. |
+ */</span> |
+ for(var c = 0;c < radioCollection.length;c++){ |
+ <span class="commentJS">/* The individual radio buttons are accessed as indexed |
+ members of the collection/Array using the loop counter |
+ - c - from the for loop: |
+ */</span> |
+ if(radioCollection[c].cheked){ |
+ checkedButton = radioCollection[c]; |
+ break; |
+ } |
+ } |
+ if(checkedButton){ |
+ <span class="commentJS">/* do something with the reference to the checked radio |
+ button (if any). |
+ */</span> |
+ ... |
+ } |
+ } |
+} |
+</pre> |
+ |
+<p id="faBut_7"> |
+While it is normal for radio button controls to be like-named it is |
+also possible for all other controls to be included in a form with |
+multiple controls of the same type and like names. The same |
+referencing techniques can be used with any type of control (even |
+mixed types with like-names, though that is almost never done). But |
+deciding whether a reference needs to be normalised by making it into |
+the only element of an <code>Array</code> by testing the |
+<code>length</code> property of that reference to see if it doesn't |
+exist will not work with <code>SELECT</code> elements as they have |
+a <code>length</code> property of their own. It also would not help |
+to be testing some other characteristic of a collection, such as their |
+<code>item</code> method, as <code>SELECT</code> elements usually have |
+all of the methods and properties of a collection as they are |
+implemented as collections of <code>OPTION</code> elements. |
+</p> |
+ |
+<p id="faBut_8"> |
+Turning the problem around and testing a returned reference to see if |
+it has the characteristics of a <code>SELECT</code> element (such as |
+an <code>options</code> property) would be better but some collection |
+implementations have all of the properties and methods of the first |
+element within that collection as well as the properties and methods |
+of a collection (e.g. on IceBrowser 5). That means that it would not be |
+easy to distinguish a collection of <code>SELECT</code> controls |
+from an individual <code>SELECT</code> control. However, a more |
+elaborate test might go:- |
+</p> |
+ |
+<pre id="faBut_ex4"> |
+<span class="commentJS">/* Normalise a reference that may be an individual from control |
+ (including SELECT elements) or may be a collection of controls |
+ into a form that can be handled in a - for - loop controlled with |
+ its - length - property and accessed by integer index. |
+*/</span> |
+if((typeof contrlCollection.length != "number")|| <span class="commentJS">//no length propety:</span> |
+ <span class="commentJS">/* or:- */</span> |
+ ((contrlCollection.options)&& <span class="commentJS">//it has an options colleciton and:</span> |
+ ((!contrlCollection[0])|| <span class="commentJS">//no object at index 0 - not a collection</span> |
+ <span class="commentJS">/* or:- */</span> |
+ (contrlCollection[0] == contrlCollection.options[0])))){ |
+ <span class="commentJS">/* The object at index 0 in contrlCollection is the same object |
+ as is at index 0 in contrlCollection.options so this must be |
+ an individual SELECT element not a collection of them because a |
+ collection of SELECT elements would not have an OPTION element |
+ at index zero. |
+ */</span> |
+ contrlCollection = [contrlCollection]; |
+} |
+</pre> |
+ |
+<h2 id="faEff">Efficient use of Form Accessors</h2> |
+ |
+<p id="faEff_1"> |
+Code that interacts with <code>FORM</code> elements and controls |
+through the <code>document.forms</code> collection and the form's |
+<code>elements</code> collection usually does not do enough work to |
+make the efficiency of the code significant. But with large forms with |
+many controls an inefficiently coded validation function (or some other |
+interaction, like keeping running totals) can negatively impact on the |
+user's experience. It can also be argued that considering the |
+efficiency of implementation is a worthwhile habit even when it would |
+make no perceivable difference. |
+</p> |
+ |
+<p id="faEff_2"> |
+A significant aspect of the efficient coding of form interacting code |
+is the re-resolving of references to various objects. This trivial |
+example code copies the values of 5 <code>INPUT</code> elements to |
+local variables:- |
+</p> |
+ |
+<pre id="faEff_ex1"> |
+var txt1 = document.forms["formName"].elements["field1"].value; |
+var txt2 = document.forms["formName"].elements["field2"].value; |
+var txt3 = document.forms["formName"].elements["field3"].value; |
+var txt4 = document.forms["formName"].elements["field4"].value; |
+var txt5 = document.forms["formName"].elements["field5"].value; |
+</pre> |
+ |
+<p id="faEff_3"> |
+The shortcut accessors require the resolution of fewer object |
+references:- |
+</p> |
+ |
+<pre id="faEff_ex2"> |
+var txt1 = document["formName"]["field1"].value; |
+var txt2 = document["formName"]["field2"].value; |
+var txt3 = document["formName"]["field3"].value; |
+var txt4 = document["formName"]["field4"].value; |
+var txt5 = document["formName"]["field5"].value; |
+</pre> |
+ |
+<p id="faEff_4"> |
+But their use still involves re-resolving the form object each time a |
+form control is accessed. It would be unnecessary to re-resolve this |
+reference if a reference to the form was assigned to a local variable:- |
+</p> |
+ |
+<pre id="faEff_ex3"> |
+<span class="commentJS">/* Assign a reference to the form object to the local variable - frm - |
+ and then make subsequent control references relative to that local |
+ variable: |
+*/</span> |
+var frm = document.forms["formName"]; |
+var txt1 = frm.elements["field1"].value; |
+var txt2 = frm.elements["field2"].value; |
+var txt3 = frm.elements["field3"].value; |
+var txt4 = frm.elements["field4"].value; |
+var txt5 = frm.elements["field5"].value; |
+</pre> |
+ |
+<p id="faEff_5"> |
+The effect would be much the same as when a reference to the form |
+object has been passed to a function and control references are |
+accessed relative to the parameter holding the form reference. |
+</p> |
+ |
+<p id="faEff_6"> |
+It is still not optimum to be re-resolving the <code>elements</code> |
+collection, and it is practical to assign a reference to that object |
+to a local variable instead of a reference to the form object:- |
+</p> |
+ |
+<pre id="faEff_ex4"> |
+<span class="commentJS">/* Assign a reference to the form's elements collection to the local |
+ variable - frmEls - and then make subsequent control references |
+ relative to that local variable: |
+*/</span> |
+var frmEls = document.forms["formName"].elements; |
+var txt1 = frmEls["field1"].value; |
+var txt2 = frmEls["field2"].value; |
+var txt3 = frmEls["field3"].value; |
+var txt4 = frmEls["field4"].value; |
+var txt5 = frmEls["field5"].value; |
+</pre> |
+ |
+<p id="faEff_7"> |
+With the original long form accessor the resolution starts with |
+resolving the <code>"document"</code> identifier. The |
+identifier is first looked for among the local variables of the |
+function (as a named property of the internal |
+"Variable" object, by ECMA specification), |
+when it is not found the scope chain is searched, object by object |
+down the chain, for a property with the corresponding name. When the |
+scope resolution for <code>"document"</code> gets to the |
+global object (at the end of the scope chain) it will find a property |
+called <code>"document"</code>, a reference to the |
+<code>document</code> object, and the first identifier in the accessor |
+will have been resolved. The next identifier is |
+<code>"forms"</code> and that is located as a property of the |
+<code>document</code>. Then the <code>"formName"</code> |
+property is identified in the <code>forms</code> collection. Next the |
+<code>"elements"</code> property of the form is located, |
+followed by the control name in that object and finally the |
+<code>"value"</code> property of the control is returned. |
+</p> |
+ |
+<p id="faEff_8"> |
+When a reference to the <code>elements</code> collection is assigned to |
+a local variable the first identifier in the property accessor is |
+identified as that local variable, the control name is identified as a |
+property of the <code>elements</code> collection referenced and the |
+<code>"value"</code> property of the control is returned. |
+</p> |
+ |
+<p id="faEff_9"> |
+Obviously there is a big difference in the amount of work involved in |
+acquiring the <code>value</code> of the control in each case. That |
+difference will not be that significant if only a couple of values are |
+accessed, but even with as few as half a dozen control property |
+accesses the second approach will obviously be much more efficient, |
+and with increasing numbers of controls the difference could easily |
+become apparent to the user. |
+</p> |
+</body> |
+</html> |
/cljs/faq_notes/form_access.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/faq_notes/alt_dynwrite.html |
=================================================================== |
--- cljs/faq_notes/alt_dynwrite.html (nonexistent) |
+++ cljs/faq_notes/alt_dynwrite.html (revision 2) |
@@ -0,0 +1,569 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
+<html lang="en"><head><title>An Alternative DynWrite function</title> |
+<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> |
+<link href="../faq.css" rel="stylesheet" type="text/css"> |
+<link href="faq_notes.css" rel="stylesheet" type="text/css"> |
+</head> |
+<body> |
+ |
+<h1><a name="alDynWr" id="alDynWr">An Alternative DynWrite function</a></h1> |
+ |
+<ul> |
+ <li><a href="#DynWr">The DynWrite function.</a></li> |
+ <li><a href="#getEl">Element retrieval given the element ID as a string.</a></li> |
+ <li><a href="#innHTest">innerHTML Testing Strategy.</a></li> |
+ <li><a href="#AltDynWr">Alternative DynWrite function.</a></li> |
+</ul> |
+ |
+ |
+<h2><a name="DynWr" id="DynWr">The Original DynWrite function.</a></h2> |
+ |
+<p id="DynWr_1"> |
+<a href="http://jibbering.com/faq/#FAQ4_15">The quick answer in section |
+4.15 of the FAQ</a> defines a function called <code>DynWrite</code> that will insert <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> |
+content into an <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> page by writing a string of <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> to the <code>innerHTML</code> |
+property of an IDed element, but only on browsers that fully support |
+the (Microsoft IE originated) <code>innerHTML</code> extension. |
+</p> |
+ |
+<p id="DynWr_2"> |
+On browsers that do not provide a suitable mechanism for accessing the |
+element, do not implement the <code>innerHTML</code> extension and browsers that |
+implement <code>innerHTML</code> as a read-only property (along with Javascript |
+incapable/disabled browsers) no content will be inserted with this |
+function. |
+</p> |
+ |
+<p id="DynWr_3"> |
+On browsers that lack the element retrieval mechanism the <code>DynWrite</code> |
+function is created as a simple function that just returns false. That |
+would allow code that called <code>DynWrite</code> to check the value returned from |
+a call to <code>DynWrite</code> and, if it was false, know that there would be no |
+point in continuing to use the function as content will never be |
+inserted into the document. |
+</p> |
+ |
+<p id="DynWr_4"> |
+Unfortunately the other branch, when an element retrieval mechanism is |
+available, produces a function that will retrieve the element and write |
+to its <code>innerHTML</code> property, returning true. On the browsers that do not |
+implement, or fully implement, <code>innerHTML</code> this action should have no |
+harmful side effects, merely creating a new <code>innerHTML</code> property on the |
+element in browsers that do not implement the extension at all and |
+leaving read-only <code>innerHTML</code> properties unchanged. But the true return |
+value cannot be taken as an indicator of the success of the action. |
+</p> |
+ |
+<p id="DynWr_5"> |
+Ideally the return value from <code>DynWrite</code> should be a reasonable |
+indicator of the success of the attempt to insert contents into the |
+<span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> as that would facilitate controlled degradation on un-supporting |
+browsers. |
+</p> |
+ |
+<p id="DynWr_6"> |
+However, it is necessary to have a reference to an element in order |
+to examine it to see if it does support <code>innerHTML</code> and the testing |
+would alter the contents of that element (though possibly only |
+temporarily). As a page loads elements usually become available |
+(or, at least, referencable) after their opening <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> tag has been |
+parsed, so code defined (or imported) in the HEAD section of a page |
+could access the <code><span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span></code> element and the <code>HEAD</code> element along with, |
+possibly, the <code>TITLE</code> and any other preceding elements. |
+</p> |
+ |
+<p id="DynWr_7"> |
+It would be theoretically possible acquire a reference to one of |
+these elements and determine whether it has an <code>innerHTML</code> property |
+and maybe then attempt to write to it to see if that had the desired |
+effect. In reality there is at least one <code>innerHTML</code> supporting |
+browser that will allow the dynamic modification of the content of |
+any element within the BODY but generates run-time errors if an |
+attempt is made to test, read or modify the <code>innerHTML</code> property of |
+elements within the HEAD. That rules out examining the elements |
+within the HEAD for <code>innerHTML</code> support and means that when <code>DynWrite</code> |
+is initially configured it cannot know whether it is going to be |
+effective or not. |
+</p> |
+ |
+<p id="DynWr_8"> |
+It would, in principle, be possible to write the <code>DynWrite</code> functions |
+so that it tests the element that it is asked to insert <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> into |
+prior to making the attempt so that it could act (or not) and then |
+return true/false based on the result of those tests. But that would |
+be inefficient as it would require that the test be carried out on |
+every invocation of <code>DynWrite</code>. Iit may also be visually undesirable as |
+the testing strategy (described below) involves setting the <code>innerHTML</code> |
+to a test value resulting in two <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> modification per write operation |
+(which may become visually apparent). |
+</p> |
+ |
+<p id="DynWr_9"> |
+An alternative is to exploit the flexibility of Javascript by |
+initially assigning a function to <code>DynWrite</code> that could carry out |
+the required tests and then re-assign <code>DynWrite</code> to a function that |
+returned a true/false value that more accurately reflected the |
+browser's support for the <code>innerHTML</code> extension. Allowing the tests |
+to be performed on an element that should be available at the time |
+of the test and the content of which is intended that it be replaced |
+so it will not matter if it is replaced with the test value because |
+if it was successfully replaced for the test it would then be |
+re-replaced with the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> that was intended to be inserted. It also |
+allows the test to only be performed once as success or failure on |
+the first attempt should indicate the same outcome on subsequent |
+attempts. |
+</p> |
+ |
+<p id="DynWr_10"> |
+<code>DynWrite</code> is initially configured based on the browser's apparent |
+ability to retrieve a reference to a DOM element given its ID in |
+the form of a string. On modern browsers the document.getElementById |
+function can be used to return a reference to an element given the |
+ID as a string. Older browsers may not implement the getElementById |
+function, but some may provide an alternative mechanism such as |
+document.all. |
+</p> |
+ |
+<h2><a name="getEl" id="getEl">Element retrieval given the element ID as a string.</a></h2> |
+ |
+<p id="getEl_1"> |
+Several approaches can be taken towards maximising the ability |
+to retrieve references to DOM elements. |
+</p> |
+ |
+<p id="getEl_2"> |
+1. Writing a general element retrieval function such as:- |
+</p> |
+ |
+<pre id="getEl_ex1"> |
+function getElementWithId(id){ |
+ var obj = null; |
+ if(document.getElementById){ |
+ <span class="commentJS">/* Prefer the widely supported W3C DOM method, if |
+ available:- |
+ */</span> |
+ obj = document.getElementById(id); |
+ }else if(document.all){ |
+ <span class="commentJS">/* Branch to use document.all on document.all only |
+ browsers. Requires that IDs are unique to the page |
+ and do not coincide with NAME attributes on other |
+ elements:- |
+ */</span> |
+ obj = document.all[id]; |
+ } |
+ <span class="commentJS">/* If no appropriate element retrieval mechanism exists on |
+ this browser this function always returns null:- |
+ */</span> |
+ return obj; |
+} |
+</pre> |
+ |
+<p id="getEl_3"> |
+2. Assigning one of many functions tailored to element retrieval on |
+the current browser to a global variable that can then be used to |
+call the element retrieval function. |
+</p> |
+ |
+<pre id="getEl_ex2"> |
+var getElementWithId; |
+if(document.getElementById){ |
+ <span class="commentJS">/* Prefer the widely supported W3C DOM method, if |
+ available:- |
+ */</span> |
+ getElementWithId = function(id){ |
+ return document.getElementById(id); |
+ } |
+}else if(document.all){ |
+ <span class="commentJS">/* Branch to use document.all on document.all only |
+ browsers. Requires that IDs are unique to the page |
+ and do not coincide with NAME attributes on other |
+ elements:- |
+ */</span> |
+ getElementWithId = function(id){ |
+ return document.all[id]; |
+ } |
+}else{ |
+ <span class="commentJS">/* No appropriate element retrieval mechanism exists on |
+ this browser. So assign this function as a safe dummy. |
+ Values returned form calls to getElementWithId probably |
+ should be tested to ensure that they are non-null prior |
+ to use anyway so this branch always returns null:- |
+ */</span> |
+ getElementWithId = function(id){ |
+ return null; |
+ } |
+} |
+</pre> |
+ |
+<p id="getEl_4"> |
+3. Using a feature of a browser to emulate getElementById on a browser |
+that does not implement it. So that getElementById can be used as a |
+general element reference retrieval method. |
+</p> |
+ |
+<pre id="getEl_ex3"> |
+<span class="commentJS">/* Emulate getElementById on document.all only browsers. Requires |
+ that IDs are unique to the page and do not coincide with NAME |
+ attributes on other elements:- |
+*/</span> |
+if((!document.getElementById) && document.all){ |
+ document.getElementById = function(id){return document.all[id];}; |
+} |
+</pre> |
+ |
+<p id="getEl_5"> |
+The reason for the comment about the use of ID and NAME attributes is |
+that the <code>document.all</code> collection does not have exactly |
+analogous behaviour with the <code>document.getElementById</code> method. |
+If multiple elements have the same ID (or share an ID with the NAME of |
+other elements) then <code>document.all</code> returns a collection |
+instead of an individual element, while <code>document.getElementById</code> |
+only ever returns an individual element or <code>null</code>. However, |
+ID attributes are supposed to be unique to an <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> page if that page |
+is valid <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> 4 so multiple identical IDs should not be a problem. |
+The issue with IDs coinciding with NAMEs remains, though it would not |
+be good <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> design to provoke that problem. |
+</p> |
+ |
+<p id="getEl_6"> |
+Also, when a string used to refer to a property of the <code>document.all</code> |
+collection does not refer to an element or a collection of elements |
+<code>undefined</code> is returned by the above function. In most |
+type-converting tests <code>undefined</code> and <code>null</code> |
+behave the same (they both convert to boolean <code>false</code>) |
+so the distinction is not necessarily important. |
+</p> |
+ |
+<p id="getEl_7"> |
+However, a more cautious but slower getElementById emulation could be |
+used. Including tests that ensure that its behaviour exactly matched |
+the W3C getElementById method. |
+</p> |
+ |
+<pre id="getEl_ex4"> |
+<span class="commentJS">/* Emulate getElementById on document.all only browsers. */</span> |
+if((!document.getElementById) && document.all){ |
+ document.getElementById = function(id){ |
+ var tempEl = null, el = document.all[id]; |
+ if(el){ <span class="commentJS">//document.all returned something.</span> |
+ if((!el.id)||(el.id != id)){ |
+ <span class="commentJS">/* Either this is a collection or the only element |
+ available under the property name provided as the |
+ - id - parameter is a named element: |
+ */</span> |
+ if(el.length){ <span class="commentJS">//assume it is a collection.</span> |
+ <span class="commentJS">/* But it might be an element with a NAME |
+ corresponding with the id parameter that has |
+ collection-like behaviour such as a form or a |
+ select element so proceed with caution: |
+ */</span> |
+ for(var c = 0;c < el.length;c++){ |
+ if((el[c].id)&&(el[c].id == id)){ |
+ <span class="commentJS">/* Set tempEl to the first match and |
+ break out of the - for - loop: |
+ */</span> |
+ tempEl = el[c]; |
+ break; |
+ } |
+ } |
+ <span class="commentJS">/* el will be set to null if the loop did not |
+ find an element with the corresponding ID |
+ because the default null value of tempEl |
+ will not have changed: |
+ */</span> |
+ el = tempEl; |
+ }else{ <span class="commentJS">//only a named element is available for id.</span> |
+ <span class="commentJS">/* getElementById should not return named elements |
+ only an IDed element so set el to null: |
+ */</span> |
+ el = null; |
+ } |
+ } <span class="commentJS">//else we have our element (the ID matches).</span> |
+ }else{ <span class="commentJS">//el is undefined so make it null;</span> |
+ el = null; |
+ } |
+ <span class="commentJS">/* The returned value will be the first element confirmed as |
+ having the corresponding ID or it will be null: |
+ */</span> |
+ return el; |
+ }; |
+} |
+</pre> |
+ |
+<p id="getEl_8"> |
+One of the consequences of creating a function to emulate |
+<code>getElementById</code> is that other scripts that use the |
+existence of <code>document.getElementById</code> to infer the |
+existence of features of the browser beyond the getElementById method |
+may wrongly infer that a browser that is provided with the emulation |
+may have features that it does not have (unless they have also been |
+emulated). This should not be a problem as using a test on one feature |
+to infer the existence of other features is a <strong>fatally flawed |
+technique</strong>, the use of which <strong>is discouraged</strong>. |
+</p> |
+ |
+<p id="getEl_9"> |
+I will be using the third approach, emulating the |
+<code>document.getElementById</code> method, in the modified |
+<code>DynWrite</code> function (with notes on what would differ |
+with either of the first two). |
+</p> |
+ |
+<h2><a name="innHTest" id="innHTest">innerHTML Testing Strategy.</a></h2> |
+ |
+<p id="innHTest_1"> |
+Initially testing an element to see if <code>innerHTML</code> is supported simply |
+involves using the <code>typeof</code> operator to see if it returns |
+<code>"string"</code>. That test will identify browsers such as Opera 6, |
+where the <code>innerHTML</code> property is undefined. |
+</p> |
+ |
+<p id="innHTest_2"> |
+The second test is based on the fact that when the <code>innerHTML</code> property |
+of an element is read on a supporting browser the value returned is |
+normalised <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> and not the literal <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> source code. However, all |
+browsers seem to take a different attitude when generating that |
+normalised source. So given the original <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> source:-<br><code><td |
+CLASS="obj"><U>firstChild</U></td></code><br> |
+the corresponding <code>innerHTML</code> of the parent element reads <br><code><TD |
+CLASS='obj'><U>firstChild</U></TD></code><br> on |
+Opera 7.11, <br><code><TD class=obj><U>firstChild</U></TD> |
+</code><br> on IE 5.0 and <br><code><td |
+class="obj"><u>firstChild</u></td> |
+</code><br> on Mozilla 1.2. |
+</p> |
+ |
+<p id="innHTest_3"> |
+None of these correspond with the original <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> but they are also |
+different from each other. What is needed for the test is <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> |
+source that all supporting browsers will return as different text |
+from the source assigned. For that task a mixed case <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> string with additional |
+unnecessary whitespace characters is used. That test <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> is appended |
+to the original <code>innerHTML</code> value to ensure that the test string will |
+never be equivalent to either the original <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> or the normalised |
+result of reading the innnerHTML property after the assignment, even |
+by accident. The fact that the browser has normalised the source is |
+taken as indicating that the browser supports the <code>innerHTML</code> extension. |
+</p> |
+ |
+<p id="innHTest_4"> |
+After writing the test <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> to the <code>innerHTML</code> property it is possible |
+to determine whether the property is read only by comparing a stored |
+copy of the original value against the retrieved value. This is also |
+necessary because otherwise the fact that the returned <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> does not |
+correspond with the testHTML would be taken as indicating that |
+it had been normalised. |
+</p> |
+ |
+<p id="innHTest_5"> |
+Finally, it is necessary to determine whether inserting the test |
+<span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> has added the element that it defines to the DOM for the page. |
+</p> |
+ |
+<p id="innHTest_6"> |
+When those tests are passed correctly the <code>DynWrite</code> function can be |
+replaced with a new function that does not bother repeating the tests |
+for subsequent assignments to <code>innerHTML</code>. If the tests are failed |
+then the <code>DynWrite</code> function replaces itself with one that does no |
+more than return false to indicate its failure. |
+</p> |
+ |
+<h2><a name="AltDynWr" id="AltDynWr">Alternative DynWrite function.</a></h2> |
+ |
+<p id="AltDynWr_1"> |
+The modified, and commented, alternative <code>DynWrite</code> function |
+incorporating these tests is as follows:- |
+</p> |
+ |
+<pre id="AltDynWr_ex1"> |
+<span class="commentJS">/* As written here, to support older browsers like IE 4, the emulation |
+ of getElementById MUST HAVE BEEN EXECUTED _PRIOR_ TO THE FIRST CALL |
+ TO THIS FUNCTION. If either of the alternative element retrieval |
+ methods are to be used the noted changes also need to be made to |
+ this function and the alternative method MUST have been set-up |
+ prior to the first use of this function. |
+*/</span> |
+function DynWrite(id, S){<span class="commentJS"> //Generates a successor when first called!</span> |
+ <span class="commentJS">/* Define local variables:- |
+ */</span> |
+ var testH, newH, inH, testID; |
+ <span class="commentJS">/* Set the default value for the body text of the function that |
+ will be created to replace this function as the DynWrite |
+ function:- |
+ */</span> |
+ var funcBody = "return false;" |
+ <span class="commentJS">/* This ensures that getElementById is available (or emulated) |
+ on this browser prior to calling it:- |
+ */</span> |
+ var el = (document.getElementById)?document.getElementById(id):null; |
+ <span class="commentJS">/* If one of the other element retrieval strategies was used, |
+ creating a getElementWithId function, then because that function |
+ will return null when an element cannot be found, it is |
+ practical to just call that function as - |
+ var el = getElementWithId(id); |
+ - as subsequent tests result in an appropriate response. |
+ */</span> |
+ <span class="commentJS">/* This ensures that the referenced element has been successfully |
+ retrieved and tests to verify that its innerHTML property is |
+ a string (as opposed to being undefined):- |
+ */</span> |
+ if((el)&&(typeof el.innerHTML == 'string')){ |
+ <span class="commentJS">/* Arbitrary string to use as an ID for an element that |
+ should be created as a result of writing to the innerHTML |
+ value (The string itself and the result of concatenating it |
+ to itself (repeatedly) should follow the rules for valid |
+ <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> ID attributes):- |
+ */</span> |
+ testID = "tSt"; |
+ <span class="commentJS">/* This ensures that the test ID is not in use on the page by |
+ modifying it until an element cannot be retrieved using it:- |
+ */</span> |
+ while(document.getElementById(testID)){ |
+ <span class="commentJS">/* If the getElementWithId function is being used instead |
+ of the getElementById emulation then the preceding test |
+ must also use that function. |
+ */</span> |
+ testID += testID; |
+ } |
+ inH = el.innerHTML; <span class="commentJS">//Read the original innerHTML value.</span> |
+ <span class="commentJS">/* The following mixed case <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> string is _not_ an error. |
+ */ |
+ /* Note also that the STRONG element inserted in the page |
+ contains the text "test", which may momentarily be |
+ visible to the user. It would probably not be a good |
+ idea to have no contents in the STRONG at all but &nbsp; |
+ could be used to reduce the potential visual impact:- |
+ */</span> |
+ newH = inH+"<sTrOnG Id='"+testID+"' >test<\/StRoNg >"; |
+ el.innerHTML = newH; <span class="commentJS">//Assumes synchronous update of DOM.</span> |
+ testH = el.innerHTML; <span class="commentJS">//Read innerHTML back for examination.</span> |
+ if((testH != newH)&& <span class="commentJS">//Apparently normalised or unchanged.</span> |
+ (testH != inH)&& <span class="commentJS">//Not unchanged (Not read-only).</span> |
+ (document.getElementById(testID))){ <span class="commentJS">//Element found in DOM.</span> |
+ <span class="commentJS">/* If the getElementWithId function is being used instead |
+ of the getElementById emulation then the preceding test |
+ must also use that function. |
+ */</span> |
+ <span class="commentJS">/* TESTS PASSED! Replace the default function body string |
+ with code that will set the innerHTML property of the |
+ element and return true, based on the assumption that |
+ the assignment will be successful because this test was |
+ sucessful:- |
+ */</span> |
+ funcBody = |
+ "document.getElementById(id).innerHTML=S; return true"; |
+ <span class="commentJS">/* See additional notes[1] on the function body to use at |
+ this point. |
+ */</span> |
+ } |
+ } |
+ <span class="commentJS">/* Replace the DynWrite function with one determined by the results |
+ of the tests:- |
+ */</span> |
+ DynWrite = new Function("id", "S", funcBody); |
+ <span class="commentJS">/* Call the newly created DynWrite function and return its return |
+ value as the return value for this function call:- |
+ */</span> |
+ return DynWrite(id, S); |
+} |
+<span class="commentJS">/* [1] Notes on the body string to use if the tests are passed:- |
+ The existing function body string relies on the use of |
+ the getElementById emulation approach to retrieving DOM element |
+ with an ID. If the getElementWithId function was used the |
+ appropriate equivalent body string would be:- |
+ |
+"getElementWithId(id).innerHTML = S;return true;" |
+ |
+ However, if the ID passed as a parameter to DynWrite does not |
+ correspond with an existing IDed element then either of these two |
+ options would result in a function that would generate run-time |
+ errors. For development that is probably a good thing as the |
+ resulting error should be corrected in either the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> or the |
+ script code by ensuring that the ID string provided does refer to a |
+ uniquely identified DOM element. On the other hand, having fully |
+ tested the code, the body string might be best swapped in deployed |
+ code to a more cautious version that checked the result of the |
+ element retrieval call to ensure that it is a non-null object:- |
+ |
+"var el=document.getElementById(id);if(el){el.innerHTML=S;}return true;" |
+ |
+ - with the getElementById emulation or:- |
+ |
+"var el=getElementWithId(id);if(el){el.innerHTML=S;}return true;" |
+ |
+ - with the getElementWithId function. |
+ |
+ These function body strings are still returning true. How |
+ suited that is to the situation would depend on how the code |
+ intended to respond to the return value. The inability to resolve |
+ one ID does not indicate that innerHTML would not available on |
+ others if they could be resolved so code that decides to stop |
+ attempting to write to innerHTML upon the first false return |
+ value might be better off using the previous strings. Code that |
+ wanted to fall-back based on each attempt to write to innerHTML |
+ would be better using a function body string that returned |
+ true/false based on the success of each individual attempt. For |
+ the body string that tests to ensure that the element reference |
+ is recovered a boolean return value based on the success of the |
+ element retrieval would be best suited. That is simplest achieved |
+ with a double NOT operator - return !!el; - . A null value of |
+ - el - would return boolean false and an element reference would |
+ return true due to type-converting forced by the NOT operator:- |
+ |
+"var el=document.getElementById(id);if(el){el.innerHTML=S;}return !!el;" |
+ |
+ - with the getElementById emulation or:- |
+ |
+"var el=getElementWithId(id);if(el){el.innerHTML=S;}return !!el;" |
+ |
+ - with the getElementWithId function. |
+ |
+*/</span> |
+</pre> |
+ |
+<p id="AltDynWr_2"> |
+This design of the function does not involve any configuration tests |
+as the page loads. It is one simple function definition. In principle |
+calling the function with appropriate parameters will always return |
+false if the content inserting is not possible and true otherwise. |
+With the tests being performed only on the first invocation of the |
+function. |
+</p> |
+ |
+<p id="AltDynWr_3"> |
+Given the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span>: <code><div ID="anID">old |
+<code>HTML</code></div></code> examples of usage might be:- |
+</p> |
+ |
+<pre id="AltDynWr_ex2"> |
+if(!DynWrite("anID", "new <code>HTML<\/code>")){ |
+ ... <span class="commentJS">// Handle the failure of the call to DynWrite.</span> |
+} |
+</pre> |
+ |
+<p id="AltDynWr_4"> |
+- or - |
+</p> |
+ |
+<pre id="AltDynWr_ex3"> |
+if(DynWrite("anID", "new <code>HTML<\/code>")){ |
+ ... <span class="commentJS">// Action following the success of the DynWrite call.</span> |
+}else{ |
+ ... <span class="commentJS">// Handle the failure of the call to DynWrite.</span> |
+} |
+</pre> |
+ |
+<p id="AltDynWr_5"> |
+It has been observed that IE 4 errors if DynWrite is called before the |
+onload event is triggered by the browser. So to maximise cross-browser |
+support for this function it would be better not to use it prior to that |
+point. |
+</p> |
+ |
+<p id="rToc"> |
+<a href="faq_notes.html#toc">comp.lang.javascript FAQ notes T.O.C.</a> |
+</p> |
+ |
+ |
+</body> |
+</html> |
\ No newline at end of file |
/cljs/faq_notes/alt_dynwrite.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/faq_notes/misc.html |
=================================================================== |
--- cljs/faq_notes/misc.html (nonexistent) |
+++ cljs/faq_notes/misc.html (revision 2) |
@@ -0,0 +1,287 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd"> |
+<html lang="en"><head><title>Miscellaneous Tricks and Tips</title> |
+<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> |
+<link href="../faq.css" rel="stylesheet" type="text/css"> |
+<link href="faq_notes.css" rel="stylesheet" type="text/css"> |
+</head> |
+<body> |
+ |
+<h1><a name="mtHead" id="mtHead">Miscellaneous Tricks and Tips.</a></h1> |
+ |
+<ol> |
+ <!-- <li><a href="#mtSort">Sorting Arrays of objects by one of properties of those objects.</a></li> --> |
+ <li><a href="#mtCSSUn">Setting the top and left values of positioned elements with <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> units, when needed</a></li> |
+ <li><a href="#mtSetTI">Using function references with setTimeout and setInterval</a></li> |
+</ol> |
+<!-- |
+<h2><a name="mtSort" id="mtSort">Sorting Arrays of objects by one of properties of those objects.</a></h2> |
+ |
+<p id="mtSort_1"> |
+Given an <code>Array</code> of like objects it may be necessary to sort |
+that <code>Array</code> based on the value of one of the properties of |
+those objects. The following functions are based on the results of a |
+discussion between Evertjan and Lasse Reichstein Nielsen and are |
+probably the shortest possible formulations of <code>"comparefn"</code> |
+functions (as per ECMA 262 page 94) for use with the |
+<code>Array.prototype.sort</code> method when sorting Arrays of objects |
+by values held in one of their properties. |
+</p> |
+ |
+<pre id="mtSort_ex1"> |
+<span class="commentJS">/* These example function use the value of a property of the objects |
+ called "x". That property name would have to be changed if the |
+ sorting was to be done by the value held under any other named. If |
+ the object to be sorted are other Arrays then the dot notation |
+ accessors - a.x - and - b.x - would have to be exchanged for Array |
+ accessors - a[n] - and - b[n] - where - n - is the integer index of |
+ the element being accessed. |
+*/</span> |
+<span class="commentJS">/* The object who's property holds the smallest value is placed first |
+ in the Array returned by the Array.prototype.sort method: |
+ a.x < b.x returns +1 |
+ b.x < a.x retains -1 |
+ a.x == b.x returns 0 |
+*/</span> |
+function sortSmallFirst(a, b){ |
+ <span class="commentJS">/* If a.x == b.x then (a.x < b.x) is false and (a.x > b.x) is |
+ false, the subtraction type converts false to zero and the |
+ return value is (0 - 0) which is zero. If a.x < b.x then |
+ (a.x < b.x) is true, and (a.x > b.x) is false, the |
+ subtraction type-converts them into the numbers one and zero |
+ respectively and the return value is (1 - 0) which is plus |
+ one. Finally, if a.x > b.x then (a.x < b.x) is false, and |
+ (a.x > b.x) is true, the subtraction type converts them to |
+ the numbers zero and one respectively and the return value |
+ is (0 - 1) which is minus one. |
+ */</span> |
+ return (a.x < b.x) - (a.x > b.x); |
+} |
+ |
+<span class="commentJS">/* The object who's property holds the largest value is placed first |
+ in the Array returned by the Array.prototype.sort method: |
+ a.x < b.x returns -1 |
+ b.x < a.x retains +1 |
+ a.x == b.x returns 0 |
+*/</span> |
+function sortLargeFirst(a, b){ |
+ return (a.x > b.x) - (a.x < b.x); |
+} |
+ |
+<span class="commentJS">/* usage:- |
+ var unsortedObjectArray = [ |
+ {x:2, y:'apple', z:5}, |
+ {x:3, y:'orange', z:7}, |
+ {x:89, y:'strawberry', z:9}, |
+ {x:45, y:'peach', z:3}, |
+ {x:8, y:'banana', z:9}, |
+ {x:1, y:'lemon', z:34} |
+ ]; |
+ |
+ var sortedObjectArray = unsortedObjectArray.sort(sortLargeFirst); |
+*/</span> |
+</pre> |
+ --> |
+ |
+ |
+<h2><a name="mtCSSUn" id="mtCSSUn">Setting the top and left values of positioned |
+ elements with <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> units, when needed</a></h2> |
+ |
+<p id="mtCSSUn_1"> |
+When setting the position of a positioned element by assigning values |
+to the <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> <code>top</code> and <code>left</code> properties of the |
+element's <code>style</code> object it is necessary to provide the |
+value as a string with the units of the length (usually "px") |
+following the value. Modern standards compliant browsers require this, |
+older and more tolerant browsers may assume that values without units |
+represent "px" units but they can handle string values which |
+include the <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> units. Unfortunately some browsers want the |
+<code>top</code> and <code>left</code> values provided as numbers and |
+complain (or don't react) if they are provided as strings with units. |
+</p> |
+ |
+<p id="mtCSSUn_2"> |
+A technique for handling this requirement is based on the observation |
+that when a browser expects the <code>top</code> and <code>left</code> |
+values to be set as a number of pixels a <code>typeof</code> test of |
+either the <code>top</code> or <code>left</code> properties will return |
+"number" while if that same test returns "string" |
+the browser either will require the <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> units to be appended to the |
+values set as a string or it will successfully handle a value in that |
+format. |
+</p> |
+ |
+<p id="mtCSSUn_3"> |
+Once the object on which the <code>top</code> and <code>left</code> |
+values are to be set is available one of its <code>top</code> or |
+<code>left</code> properties can be tested with <code>tyoeof</code> |
+and an appropriately scoped variable set to either the string |
+<code>"px"</code> or the number zero. |
+</p> |
+ |
+<pre id="mtCSSUn_ex1"> |
+var cssUnitsOrZero = (typeof styleObjectRef.top == 'string')?'px':0; |
+</pre> |
+ |
+<p id="mtCSSUn_4"> |
+Then when the position has been calculated (as a number) it can be |
+assigned to the appropriate property with the value derived as the |
+result of the test applied to it using the <code>+</code> operator. |
+Because the <code>+</code> operator is a duel role addition and |
+string concatenation operator, and decides which action it will take |
+based on its operands, the application of the <code>+</code> operator |
+to a position value as a number will depend on the type of the value |
+derived from the preceding <code>typeof</code> test on the |
+<code>top</code> or <code>left</code> properties. |
+</p> |
+ |
+<pre id="mtCSSUn_ex2"> |
+styleObjectRef.top = numericPosition + cssUnitsOrZero; |
+ |
+<span class="commentJS">/* If the - numericPosition - value was 125, for example, and - |
+ cssUnitsOrZero - was zero, the value assigned would be:- |
+ |
+ styleObjectRef.top = (125 + 0); |
+ |
+ - which is the number 125. If - cssUnitsOrZero - was "px" then |
+ the assignment would be:- |
+ |
+ styleObjectRef.top = (125 + "px"); |
+ |
+ - which is the string "125px". |
+*/</span> |
+</pre> |
+ |
+<p id="mtCSSUn_5"> |
+If the tested top property was not a string <code>cssUnitsOrZero</code> |
+will be the number zero and the <code>+</code> operator will have two |
+numeric operands and will perform numeric addition, assigning a numeric |
+value to the property, unmodified by the addition of zero. But if the |
+tested property was a string, so <code>cssUnitsOrZero</code> was |
+assigned the string value <code>"px"</code>, the |
+<code>+</code> operator will recognise that one of its operands is a |
+string and type-convert the other (the calculated position value) into |
+a string and perform concatenation, appending the |
+<code>"px"</code> <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> units string to the string |
+representation of the calculated position and then assign that value to |
+the property. |
+</p> |
+ |
+<p id="mtCSSUn_6"> |
+This fulfils the requirement to provide <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> units where needed while |
+providing the vlaues in numeric form whenever that is the type of value |
+expected. It is inefficient to perform the <code>typeof</code> test on |
+a relevant property whenever a value is to be assigned, it is better to |
+perform the test once and then re-use the same |
+<code>cssUnitsOrZero</code> variable for all subsequent assignments. |
+</p> |
+ |
+ |
+ |
+<h2><a name="mtSetTI" id="mtSetTI">Using function references with setTimeout and setInterval</a></h2> |
+ |
+<p id="mtSetTI_1"> |
+The <code>setTimeout</code> and <code>setInterval</code> functions |
+provided by web browsers are commonly used with a string of javascript |
+source code as their first argument, frequently a string that does no |
+more than call a separately defined function:- |
+</p> |
+ |
+<pre id="mtSetTI_ex1"> |
+function invokedWithSetTimeout(){ |
+ ... <span class="commentJS">// do something.</span> |
+} |
+... |
+var timer = setTimeout("invokedWithSetTimeout()", 100); |
+</pre> |
+ |
+<p id="mtSetTI_2"> |
+The string argument is interpreted and executed after the interval |
+specified as the second argument (in milliseconds). In the preceding |
+code the <code>invokeWithSetTimout</code> function would be called. |
+</p> |
+ |
+<p id="mtSetTI_3"> |
+On more recent browsers (easily the majority these days) the first |
+argument to the<code> setTimeout</code> and <code>setInterval</code> |
+functions can be a reference to a function. Instead of having to |
+interpret and execute a string of javascript source code the function |
+referred to is just executed after the interval. That will be more |
+efficient as considerably smaller overhead would be involved in the |
+execution of the function. |
+</p> |
+ |
+<pre id="mtSetTI_ex2"> |
+var timer = setTimeout(invokedWithSetTimeout, 100); |
+</pre> |
+ |
+<p id="mtSetTI_4"> |
+Unfortunately a number of older browsers such as IE 4 and Opera 5 do |
+not understand the function reference versions of |
+<code>setTimeout</code> and <code>setInterval</code>, leaving the use |
+of string arguments as apparently the best method for cross-browser |
+support. However, it is in the nature of loosely typed javascript that |
+when a native code function such as <code>setTimeout/Interval</code> is |
+expecting a string argument but is instead passed a value of another |
+type that value will be type-converted into a string. That doesn't help |
+much when the process of type-converting a function into a string |
+results in an implementation dependent representation of the function, |
+as is normally the case. |
+</p> |
+ |
+<p id="mtSetTI_5"> |
+Type-converting of a function to a string is done with the |
+function's <code>toString</code> method, usually |
+<code>Function.prototype.toString</code>. Methods of a |
+<code>prototype</code> can be overridden by methods of the function |
+object itself and an overriding <code>toString</code> method can return |
+any value its creator desires. That fact provides a means of using the |
+more efficient function reference arguments with |
+<code>setTimeout/Interval</code> and still supporting browsers that can |
+only handle string arguments, by assigning a custom |
+<code>toString</code> method to the function that is referred to in the |
+argument to <code>setTimeout/Interval</code>. That custom method would |
+return the string that would have been used in the |
+<code>setTimeout/Interval</code> function call. If the function |
+reference is type-converted to a string that string represents the |
+javascript source code that would be needed to invoke the function. If |
+it is not type-converted then <code>setTimeout/Interval</code> can |
+invoke the function directly (and without the overhead involved in |
+interpreting and executing the string of source code). |
+</p> |
+ |
+<pre id="mtSetTI_ex3"> |
+function invokedWithSetTimeout(){ |
+ ... <span class="commentJS">// do something.</span> |
+} |
+<span class="commentJS">/* Assign a function expression to a toString property of the function |
+ object referred to by the identifier - invokeWithSetTimeout -, |
+ overriding - Funciton.prototype.toString -. The new toString |
+ function returns the javascript source code needed to invoke a call |
+ to the function. |
+*/</span> |
+invokedWithSetTimeout.toString = function(){ |
+ return "invokedWithSetTimeout();"; |
+} |
+... |
+var timer = setTimeout(invokedWithSetTimeout, 100); |
+<span class="commentJS">/* If the browser will only recognise string values as the first |
+ argument to - setTimeout - then the function referred to by the |
+ identifier - invokeWithSetTimeout - will be type-converted to a |
+ string by calling its - toString - method, which will return the |
+ string " invokedWithSetTimeout();" and that string will |
+ be employed by the setTimeout function. Efectivly the same as |
+ calling the setTimeout function as:- |
+ |
+var timer = setTimeout("invokedWithSetTimeout()", 100); |
+*/</span> |
+</pre> |
+ |
+ |
+ |
+ |
+<p id="rToc"> |
+<a href="faq_notes.html#toc">comp.lang.javascript FAQ notes T.O.C.</a> |
+</p> |
+ |
+</body> |
+</html> |
\ No newline at end of file |
/cljs/faq_notes/misc.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/faq_notes/not_browser_detect.html |
=================================================================== |
--- cljs/faq_notes/not_browser_detect.html (nonexistent) |
+++ cljs/faq_notes/not_browser_detect.html (revision 2) |
@@ -0,0 +1,1413 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" |
+ "http://www.w3.org/TR/html4/strict.dtd"> |
+<html lang="en"> |
+<head> |
+<title>Browser Detection (and What to Do Instead)</title> |
+<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> |
+<link href="../../faq.css" rel="stylesheet" type="text/css"> |
+<link href="../notes.css" rel="stylesheet" type="text/css"> |
+<style type="text/css"> |
+.tip { |
+ border: 1px solid #ccc; |
+ padding: 1ex; |
+ background: #fcfcfc; |
+ font-size: 90%; |
+} |
+</style> |
+</head> |
+<body> |
+<h1 id="bdTop">Browser Detection (and What to Do Instead)</h1> |
+<div id="faqNav"> |
+ <a href="../../">FAQ</a> > <a href="../">FAQ Notes</a> |
+</div> |
+<p> |
+By Richard Cornford, edited by Garrett Smith |
+</p> |
+<ul> |
+ <li><a href="#bdIntro">Introduction</a></li> |
+ <li><a href="#bdValid">Avoiding Structural Differences in the Browser DOMs</a></li> |
+ <li><a href="#bdDif">Browsers Differences</a></li> |
+ <li><a href="#bdFailS">Failed Strategies: Browser Detecting</a> |
+ <ul> |
+ <li><a href="#bdUAS">Assumptions Based on navigator.userAgent</a></li> |
+ <li><a href="#bdOI">Assumptions Based on DOM Objects: Object inference</a></li> |
+ </ul> |
+ </li> |
+ <li><a href="#bdFD">A Strategy That Works: Object/Feature Detecting.</a> |
+ <ul> |
+ <li><a href="#bdGEID">Example 1: IDed Element Retrieval</a></li> |
+ <li><a href="#bdScroll">Example 2: Scroll Values</a></li> |
+ <li><a href="#bdReplace">Example 3: String.prototype.replace</a></li> |
+ </ul> |
+ </li> |
+ <li><a href="#bdDesPb">The Javascript Design Problem</a></li> |
+ |
+</ul> |
+ |
+<h2 id="bdIntro">Introduction</h2> |
+ |
+<p id="bdIntro_1"> |
+Under normal circumstances computer programs are written for a known |
+environment. The programmer knows what to expect; which APIs will be |
+available, how they will behave and so on. Java is an ideal example |
+of this, providing a theoretically consistent set of APIs and language |
+features across all Java Virtual Machine (JVM) implementations. But |
+this is also true in most other circumstances. The programmer of C++ |
+for the Windows operating system will know what MFC classes are |
+available and how to program them. Their expectations will be |
+rewarded, if they posses the required knowledge. |
+</p> |
+ |
+<p id="bdIntro_2"> |
+Client side javascript for the Internet, on the other hand, has the |
+possibly unique problem of having to be authored with no specific |
+knowledge of the environment in which it will be executed. The |
+client side environment will usually be a web browser and web |
+browsers do tend to have many common features (and increasingly |
+standardised features) but the author cannot know which version of |
+which browser will be making any HTTP request (or |
+whether it is a browser at all). It is not even possible to tell in |
+advance whether the User Agent will be capable of executing |
+javascript; all of those that can include a user configurable option |
+to disable it anyway. |
+</p> |
+ |
+<p id="bdIntro_3"> |
+Javascript authors for the Internet must realise that they are dealing |
+with the unknown and that any, and all, scripts will fail to execute |
+somewhere. The challenge is to get the most from your javascript when |
+it is available but to cope with their failure in a meaningful way. |
+</p> |
+ |
+<p id="bdIntro_4"> |
+I once read a description of a variant on the game of chess, played |
+at military academies. Two players sit at separate boards set up with |
+only their own pieces, out of sight of each other, and a referee |
+supervises the game. Each player makes their move in turn and the |
+referee is responsible for informing them how the other's move impacts |
+on their own pieces and how the other's disposition of pieces impact |
+on their intended move. The player is informed only when one of their |
+own pieces is taken, when one of their moves is affected by |
+interacting with one of their opponents pieces (i.e. a player may want |
+to move a bishop across the board but the referee may inform them that |
+their move was stopped four squares early when the bishop took a pawn |
+from the other side) and when one of their opponents pieces is |
+sitting on a square adjacent to one of their own. |
+</p> |
+ |
+<p id="bdIntro_5"> |
+The game is used to teach battlefield strategy. To win a player must |
+probe and test to deduce his opponent's disposition, while planing and |
+executing a response that will achieve the desired checkmate. It is |
+this sort of strategy that needs to be added to the normal programming |
+problems in order that javascript may cope with its unknown execution |
+environment, with the significant difference that the strategy, its |
+tests and all of the paths of execution must be fully planed out before |
+the code can even starts executing. |
+</p> |
+ |
+<h2 id="bdValid">Avoiding Structural Differences in the Browser DOMs</h2> |
+ |
+<p id="bdValid_1"> |
+While the point of this article is to introduce techniques for handling |
+the differences between web browsers and their DOM implementations it |
+is also possible to avoid some types of differences especially related |
+to the structure of the DOM that is being scripted. |
+</p> |
+ |
+<p id="bdValid_2"> |
+If I was asked to recommend one action most likely to promote the |
+authoring of cross-browser scripts it would be: <strong><em>Start |
+from a basis of valid <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language" |
+>HTML</abbr></span></em></strong>.</p> |
+ |
+<p id="bdValid_3"> |
+Browsers presented with invalid <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> will usually attempt to error |
+correct it in order to do the best possible job of displaying it. |
+Some browsers, particularly IE, are tolerant of all sorts of strange |
+formulations of mark-up. Valid <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> has a tree-like structure, elements |
+may completely contain others but they cannot overlap, and there are |
+rules about which elements may appear in which contexts. The DOM that |
+is to be scripted also has a tree-like structure and there is a very |
+simple relationship between the tree-like structure of valid <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> and |
+the DOM constructed from it. So any browser presented with valid <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> |
+will be able to directly translate that <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> into a corresponding DOM |
+using well specified rules, resulting in a DOM that is of predictable |
+and consistent structure on all of the browsers that can build a DOM. |
+</p> |
+ |
+<p id="bdValid_4"> |
+Invalid <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> will not translate as naturally into a DOM, or even a |
+tree-like structure. If the browser is going to build a DOM with the |
+source provided it is going to have to apply error correcting rules |
+and attempt to build the best DOM it can. But the error correcting |
+rules are not standardised, not even published. So different browsers |
+have no choice but apply different rules and that directly results in |
+the building of DOMs with different (and in extremes, radically |
+different) structures. |
+</p> |
+ |
+<p id="bdValid_5"> |
+As a result, using invalid <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> directly produces differences in the |
+DOMs produced by different browsers. No matter how good the application |
+of techniques for dealing with the differences between browsers, it |
+does not make sense to do anything that will provoke more differences |
+than are unavoidable. |
+</p> |
+ |
+<p id="bdValid_6"> |
+The authoring of invalid <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span>, justified because "It works in |
+browser XYZ", gives the authors of accompanying scripts the |
+impression that cross-browser scripting is harder than it is. If they |
+had started with valid <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> they would never have encountered any of |
+the structural inconsistencies that invalid <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> can provoke. |
+</p> |
+ |
+<h2 id="bdDif">Browsers Differences</h2> |
+ |
+<p id="bdDif_1"> |
+As browsers have evolved they have offered more features to javascript. |
+Different manufactures have adopted the features of other browsers, |
+while adding new features, that may in turn have been adopted by (or |
+will be adopted by) their competitors. Various sets of common features |
+have emerged and some have been formalised by the W3C into a sequence |
+of standard DOM specifications. Along the way an increasing number of |
+javascript capable browsers have emerged. In addition to desktop PC |
+browsers, javascript capable browsers exist for a whole range of |
+devices; PDAs, mobile telephones (Microwave ovens, refrigerators). |
+</p> |
+ |
+<p id="bdDif_2"> |
+Unfortunately it is the case that the browsers on the smaller devices |
+cannot offer the range of features available to a desktop PC and even |
+as the technology improves and features are added to the smaller |
+browsers the problem will not improve as browsers will become available |
+on a wider range of devices while the desktop PC browsers will continue |
+to march ahead of them. |
+</p> |
+ |
+<p id="bdDif_3"> |
+Over the years various strategies have been attempted to tackle this |
+problem and some have failed miserably. |
+</p> |
+ |
+<h2 id="bdFailS">Failed Strategies: Browser Detecting</h2> |
+ |
+<h3 id="bdUAS">Assumptions Based on navigator.userAgent</h3> |
+ |
+<p id="bdUAS_1"> |
+One of the most popular strategies for handling the differences between |
+web browsers was browser detecting based on the User Agent string. |
+Browsers possessing a <code>navigator</code> object also provide a |
+property of that object: <code>navigator.userAgent</code> containing a |
+string that (in theory) identifies the browser. Its application went |
+something like:- |
+</p> |
+ |
+<pre id="bdUAS_ex1"> |
+<span class="commentJS">/* Warning: never use this script, or any script based on, or resembling, it. |
+*/</span> |
+var userAgent = self.navigator.userAgent; |
+var appName = self.navigator.appName; |
+var isOpera = false; |
+var isOpera5 = false; |
+var isOpera6p = false; |
+var isIE = false; |
+var isIE4 = false; |
+var isIE5p = false; |
+var isMozilla1p = false; |
+var isNet4 = false; |
+var isNet5p = false; |
+var operaVersion = 0; |
+var ieVersion = 0; |
+var appVersion = self.navigator.appVersion; |
+var brSet = false; |
+ |
+function brSetup(){ |
+ for(var c = 3;c < appVersion.length;c++){ |
+ var chr = appVersion.charAt(c); |
+ if(isNaN(chr)){ |
+ appVersion = appVersion.substring(0, c); |
+ break; |
+ } |
+ } |
+ if((userAgent.indexOf('webtv') < 0) && |
+ (userAgent.indexOf('hotjava') < 0)){ |
+ if(userAgent.indexOf('Opera') >= 0){ |
+ var ind = (userAgent.indexOf('Opera')+6); |
+ if(((ind+1) < userAgent.length)&&(ind >= 6)){ |
+ isOpera = true; |
+ var bsVersion = parseInt(userAgent.substring(ind, ind+1)); |
+ if(!isNaN(bsVersion)){ |
+ operaVersion = bsVersion; |
+ if(operaVersion >= 6){ |
+ isOpera6p = true; |
+ }else if(operaVersion >= 5){ |
+ isOpera5 = true; |
+ } |
+ } |
+ } |
+ }else if(appName.indexOf('Microsoft Internet Explorer') >= 0){ |
+ var ind = (userAgent.indexOf('MSIE')+5); |
+ if(((ind+1) < userAgent.length)&&(ind >= 5)){ |
+ isIE = true; |
+ var bsVersion = parseInt(userAgent.substring(ind, ind+1)); |
+ if(!isNaN(bsVersion)){ |
+ ieVersion = bsVersion; |
+ if(ieVersion >= 5){ |
+ isIE5p = true; |
+ }else if(ieVersion >= 4){ |
+ isIE4 = true; |
+ } |
+ } |
+ } |
+ }else if(appName.indexOf('Netscape') >= 0){ |
+ if((self.navigator.vendor)&& |
+ (self.navigator.vendor.indexOf('Netscape') >= 0)&& |
+ (userAgent.indexOf('Gecko') >= 0)){ |
+ isNet5p = true; |
+ }else if((userAgent.indexOf('Netscape') < 0)&& |
+ (userAgent.indexOf('Gecko') >= 0)&& |
+ (appVersion >= 5)){ |
+ isMozilla1p = true; |
+ }else if((appVersion < 5)&& |
+ (userAgent.indexOf('compatible') < 0)){ |
+ isNet4 = true; |
+ } |
+ } |
+ } |
+ brSet = true; |
+} |
+</pre> |
+ |
+<p id="bdUAS_2"> |
+This version also uses some other properties of the |
+<code>navigator</code> object; <code>appName</code> and |
+<code>appVersion</code>. |
+</p> |
+ |
+<p id="bdUAS_3"> |
+Superficially this type of script seems to be saying quite a lot about |
+what browser is executing the script. Knowing that the |
+<code>isIE5p</code> variable is boolean <code>true</code> seems to be |
+a reasonable indicator that the browser in question is Internet |
+Explorer Version 5 or above and from that all of the available features |
+on the IE 5+ DOM could be assumed to exist. |
+</p> |
+ |
+<p id="bdUAS_4"> |
+Unfortunately, if this type of script ever was an effective determiner |
+of the browser type, it is not now. The first problem is that you cannot |
+write this type of script to take into account all web browsers. The |
+script above is only interested in Internet Explorer, Netscape and |
+(some) Mozilla derived browsers and Opera. Any other browser will not |
+be identified, and that will include a number of W3C DOM conforming |
+fully dynamic visual browsers quite capable of delivering on even quite |
+demanding code. |
+</p> |
+ |
+<p id="bdUAS_5"> |
+The second problem is that scripts like this one, and server-side |
+counter-parts (reading the HTTP User Agent header) were used to |
+<em>exclude</em> browsers that did not fall into a set of browsers |
+known to the author, regardless of whether those browsers were |
+capable of displaying the offending site or not. |
+</p> |
+ |
+<p id="bdUAS_6"> |
+As more browsers were written, their authors discovered that if they |
+honestly reported their type and version in their User Agent string |
+they would likely be excluded from sites that they would |
+otherwise be quite capable of displaying. To get around this problem |
+browsers began spoofing the more popular versions, sending HTTP User |
+Agent headers, and reporting <code>navigator.userAgent</code> strings, |
+that were indistinguishable from, say, IE. |
+</p> |
+ |
+<p id="bdUAS_7"> |
+As a result, when the above script reports <code>isIE5p</code> as true, it is |
+possible that the browser that is executing the script is one of |
+numerous current browsers. Many of those browsers support sufficient |
+features found on IE5+ to allow most scripts to execute but the |
+trueness of <code>isIE5p</code> is not a valid indicator that the |
+browser will support <em>all</em> of the IE 5+ DOM. |
+</p> |
+ |
+<p id="bdUAS_8"> |
+Now you might decide that a browser that lies about its identity |
+deserves what it gets (though they started lying in order to make |
+themselves usable in the face of near-sighted <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> and script authors) |
+but is worth bearing in mind that the IE 5 |
+<code>navigator.userAgent</code> string is: |
+<code>"Mozilla/4.0 (compatible; MSIE 5.01; Windows NT)"</code>. |
+IE 5 is in fact spoofing Netscape 4, and Microsoft started to do that |
+for precisely the same reasons that motivate many current browsers to |
+send User Agent headers, and report <code>navigator.userAgent</code> |
+strings that are indistinguishable form those of Microsoft browsers. |
+</p> |
+ |
+<p id="bdUAS_9"> |
+No browser manufacture wants (or ever has wanted) their browser to be |
+needlessly excluded from displaying a web site that it is perfectly |
+capable of handling just because the author of that site does not |
+know it by name. And to prevent that they have followed Microsoft and |
+taken action that has rendered the <code>userAgent</code> string (and |
+the HTTP User Agent header) meaningless. |
+</p> |
+ |
+<p id="bdUAS_10"> |
+We are now at a point where the contents of the User Agent strings |
+bear no relationship at all to the capabilities and features of the |
+browser that is reporting it. The situation has gone so far that a |
+number of javascript experts have stated that a standard quality test |
+for an unknown script would include searching the source code of the |
+script for the string <code>"userAgent"</code> and dismissing |
+the script out of hand if that string is found. |
+</p> |
+ |
+<h3 id="bdOI">Assumptions Based on DOM Objects: Object inference</h3> |
+ |
+<p id="bdOI_1"> |
+A second browser detecting strategy uses the objects present in various |
+browser DOMs and make the assumption that the presence (or absence) of |
+one or more objects indicates that a browser is a particular type or |
+version. I quickly found this example of typical code of this type:- |
+</p> |
+ |
+<pre id="bdOI_ex1"> |
+<span class="commentJS">/* Warning: never use this script, or any script based on, or resembling, it. |
+*/</span> |
+var isDOM=(document.getElementById)?true:false; |
+var isIE4=(document.all&&!isDOM)?true:false; |
+var isIE5p=(document.all&&isDOM)?true:false; |
+var isIE=(document.all)?true:false; |
+var isOP=(window.opera)?true:false; |
+var isNS4=(document.layers)?true:false; |
+</pre> |
+ |
+<p id="bdOI_2"> |
+Javascript performs automatic type conversion so when a boolean result |
+is expected from an expression that evaluates to a non-boolean value |
+that non-boolean value is (internally) converted to a boolean value |
+(using the rules defined in the ECMAScript specification) and that |
+boolean is used as the result. |
+</p> |
+ |
+<p id="bdOI_3"> |
+Take the first line:- |
+</p> |
+ |
+<pre id="bdOI_ex2"> |
+var isDOM=(document.getElementById)?true:false; |
+</pre> |
+ |
+<p id="bdOI_4"> |
+The conditional expression requires that the expression preceding the <code>?</code> |
+have a boolean result. The <code>document.getElementById</code> |
+property accessor can resolve as one of two values depending on whether |
+the <code>getElementById</code> function is supported in the browser in |
+question. If it is supported then the accessor resolves as a function |
+object, and is type converted to boolean <code>true</code>. If |
+<code>getElementById</code> is not supported the accessor resolves as |
+undefined, and undefined type converts to boolean |
+<code>false</code>. Thus the expression preceding the question mark |
+resolves as <code>true</code> or <code>false</code> and based on that |
+result <code>true</code> or <code>false</code> are assigned to the |
+variable <code>isDOM</code>. |
+</p> |
+ |
+<div class="tip"> |
+ <h4>Boolean Conversion Tip: !!</h4> |
+ <p id="bdOI_5"> |
+ Incidentally, this code is not the optimum method of assigning a boolean |
+ value based on the type converted to boolean result of a property accessor. |
+ It is better to use the javascript NOT operator ( <code>!</code> ) twice |
+ or to pass the object reference as the argument to the <code>Boolean</code> |
+ constructor called as a function. The not operator will type convert its |
+ operand to boolean and then invert it so <code>false</code> becomes |
+ <code>true</code> and <code>true</code> becomes <code>false</code>. |
+ Passing that result as the operand for a second not operator inverts |
+ the boolean again so a reference to a function object results in boolean |
+ <code>true</code> and an undefined reference results in boolean |
+ <code>false</code>. The <code>Boolean</code> constructor called as a |
+ function converts its argument to boolean and returns that value. The |
+ statement would become:- |
+ </p> |
+ |
+ <pre id="bdOI_ex3"> |
+ var isDOM = !!document.getElementById; |
+ |
+ <span class="commentJS">/* - or - */</span> |
+ |
+ var isDOM = Boolean(document.getElementById); |
+ </pre> |
+ |
+ <p id="bdOI_6"> |
+ Which is shorter and faster than the original version and certainly |
+ more direct. |
+ </p> |
+</div> |
+ |
+<h4>Inductive Generalization Fallacy</h4> |
+<p id="bdOI_7"> |
+The problem with this type of browser detecting script is that it is |
+used to make assumptions about the browser's capabilities that are |
+rarely valid. For example, this <code>isDOM</code> result, based on |
+the browser's support for <code>document.getElementById</code>, is |
+often used as the basis for the assumption that the browser has a |
+fully dynamic DOM with methods such as |
+<code>document.createElement</code>, <code>replaceChild</code> and |
+<code>appendChild</code>. Browsers do not live up to that expectation, |
+some are not that dynamic and while they may implement some of the Core |
+DOM level 1 methods such as <code>getElementById</code> They do not |
+necessarily implement large parts of the various DOM standards, |
+including all of the dynamic <code>Node</code> manipulation methods. |
+</p> |
+ |
+<p id="bdOI_8"> |
+The result of the <code>isIE5p</code> test is intended to indicate that |
+the browser is Internet Explorer 5.0 or above. However, Opera 7, |
+IceBrowser 5.4, Web Browser 2.0 (palm OS), Konquerer, Safari, NetFront, |
+iCab and others will all produce a <code>true</code> value in |
+<code>isIE5p</code> because they implement <code>getElementById</code> |
+and the <code>document.all</code> collection. As a result, code that |
+assumes that it will have <em>all</em> of the capabilities of IE 5.0+ |
+available to it when <code>isIE5p</code> is <code>true</code> will as |
+often as not be mistaken. |
+</p> |
+ |
+<p id="bdOI_9"> |
+This problem applies to all of the tests above with the possible |
+exception of the <code>window.opera</code> test. I am unaware of a |
+second browser type that has implemented an <code>opera</code> object |
+on the window object. But then Opera 7 is a radically different, and |
+much more dynamic browser that its preceding versions, though they all |
+possess a <code>window.opera</code> object. |
+</p> |
+ |
+<p id="bdOI_10"> |
+To get around the problem that multiple browsers implement the same |
+features (even if they start off unique to one browser) script authors |
+have attempted to find more discriminating features to test. For |
+example, the following script extract is intended to work only on IE |
+5.0+ browsers:- |
+</p> |
+ |
+<pre id="bdOI_ex4"> |
+var isIE5p = !!window.ActiveXObject; |
+... |
+function copyToClip(myString){ |
+ if(!isIE5p) return; |
+ window.clipboardData.setData("text",myString); |
+} |
+</pre> |
+ |
+<p id="bdOI_11"> |
+The <code>ActiveXObject</code> constructor is intended to be |
+discriminating of an IE browser. However, this type if script still |
+does not work. It has placed the competing browser manufacturers in |
+exactly the same position as they were in when scripts tested the |
+<code>navigator.userAgent</code> string and excluded them from |
+accessing a site because they honestly reported that they where not |
+IE. As a result I already know of one browser that has implemented |
+a <code>window.ActiveXObject</code> function, it probably is a dummy |
+and exists in the browsers DOM specifically to defeat the exclusion |
+of that browser based on tests like the one above. |
+</p> |
+ |
+<p id="bdOI_12"> |
+The assumptions that the existence of one (or two) feature(s) in a |
+javascript environment infers the existence of any feature beyond |
+the ones tested is invalid. It is only used by those ignorant of the |
+potential for diversity, imitation and the patterns of evolution in |
+browser DOMs. |
+</p> |
+ |
+<p id="bdOI_13"> |
+No matter how specifically the objects from which the inferences are |
+derived are chosen, the technique itself sows the seeds of its own |
+invalidity, an object that may actually validly be used to infer that |
+a browser is of a particular type/version today probably will not still |
+be valid next year. Adding a maintenance burden to a task that already |
+presupposes an omniscient knowledge of <em>all</em> browser DOMs just |
+in order to be effectively implemented at present. |
+</p> |
+ |
+ |
+<h2 id="bdFD">A Strategy That Works: Object/Feature Detecting</h2> |
+ |
+<p id="bdFD_1"> |
+The main point of the previous discussion is to convey the idea that it |
+is impossible to detect exactly which type of browser (or version of |
+that browser) a script is being executed on. The use that such scripts |
+have been put to in the past (to exclude browsers from sites that |
+they probably could have successfully handled) has motivated the |
+manufactures of browsers to render browser detecting nonviable |
+as a strategy for dealing with the variations in browser DOMs. |
+</p> |
+ |
+<p id="bdFD_2"> |
+Fortunately, not being able to identify a web browser type or version |
+with more accuracy than could be achieved by generating a random number |
+and then biasing the result by your favourite (meaningless, because |
+they too are based on browser detecting and suffer exactly the same |
+unreliability) browser usage statistics, does not need to impact upon |
+your ability to script web browsers at all. A viable alternative |
+strategy has been identified and developed to the point where it is |
+possible to author javascript to be used on web pages without any |
+interest in the type or version of the browser at all. |
+</p> |
+ |
+<p id="bdFD_3"> |
+That alternative strategy is known as object or feature detecting. I |
+prefer to use the term "feature detecting", partly because the |
+resulting code often needs to test and probe a wider range of |
+features than just those that could be described as objects, but |
+mostly because "object detecting" is occasionally |
+erroneously applied to the object inference style of script described |
+above. |
+</p> |
+ |
+<p id="bdFD_4"> |
+Feature detecting seeks to match an attempt to execute as script (or a |
+part of a script) with the execution environment by seeking to test |
+features of that environment where the results of the test have a |
+direct one-to-one relationship with the features that need to be |
+supported in the environment for the code to successfully execute. It |
+is the direct one-to-one relationship in the implemented tests that |
+avoids the need to identify the specific browser because whatever |
+browser it is it either will support all of the required features or |
+it will not. That would mean testing the feature itself (to ensure |
+that it exists on the browser) and possibly aspects of the behaviour |
+of that feature. |
+</p> |
+ |
+<p id="bdFD_5"> |
+Taking the previous example that illustrated how the |
+<code>ActiveXObject</code> constructor might be used as the basis for |
+a script that inferred the existence of, and ability to use, the |
+<code>clipboardData</code> feature implemented on window IE. Rather |
+than inferring the browser's support for the <code>clipboardData</code> |
+feature from some other unrelated feature it should be fairly obvious |
+that the feature that should be tested for prior to attempting to write |
+to the clipboard <em>is</em> the <code>clipboardData</code> object, and |
+further, that calling the <code>setData</code> method of that object |
+should necessitate checking that it too is implemented:- |
+</p> |
+ |
+<pre id="bdFD_ex1"> |
+function copyToClip(myString){ |
+ if((typeof clipboardData != 'undefined')&& |
+ (clipboardData.setData)){ |
+ clipboardData.setData("text",myString); |
+ } |
+} |
+</pre> |
+ |
+<p id="bdFD_6"> |
+In this way the tests that determine whether the |
+<code>clipboardData.setData</code> method is called have a direct |
+one-to-one relationship with the browser's support for the feature. It |
+is not necessary to be interested in whether the browser is the |
+expected windows IE that is known to implement the feature, or whether |
+it is some other browser that has decided to copy IE's implementation |
+and provide the feature itself. If the feature is there (at least to |
+the required extent) it is used and if it is not there no attempt is |
+made to use it. |
+</p> |
+ |
+<p id="bdFD_7"> |
+The above feature detecting tests are done using two operations. The |
+first employs the <code>typeof</code> operator, which returns a string |
+depending on the type of its operand. That string is one of |
+<code>"undefined"</code>, <code>"object"</code>, |
+<code>"function"</code>, <code>"boolean"</code> |
+<code>"string"</code> and <code>"number"</code> |
+and the test compares the returned string with the string |
+<code>"undefined"</code>. The <code>clipboardData</code> |
+object is not used unless typeof does not return |
+<code>"undefined"</code>. |
+</p> |
+ |
+ |
+<p id="bdFD_8"> |
+The second test is a type-converting test. The logical AND |
+(<code>&&</code>) operator internally converts its operands to |
+boolean in order to make its decision about what value it will return. |
+If <code>clipboardData.setData</code> is undefined it will type-convert |
+to boolean <code>false</code>, while if it is an object or a function |
+the result of the conversion will be boolean <code>true</code>. |
+</p> |
+ |
+<p id="bdFD_9"> |
+However, that function is not a particularly clever application of |
+feature detecting because, while it avoids the function throwing errors |
+in an attempt to execute <code>clipboardData.setData</code> on a browser |
+thatdoes not support it, it will do nothing on a browser that does not |
+support it. That is a problem when the user has been presented with a |
+GUI component that gives them the impression that their interaction |
+will result in something being written to the clipboard but when they |
+use it nothing happens. And of course nothing was going to happen if |
+the browser in use did not support javascript or it had been disabled. |
+</p> |
+ |
+<p id="bdFD_10"> |
+Ensuring that a script will not attempt to use a feature that is not |
+supported is not sufficient to address the design challenge of crating |
+scripts for the Internet. Testing the browser for the features that it |
+does support makes it practical to handle a spectrum of browser DOMs |
+but the script design task also involves planning how to handle the |
+range of possibilities. A range that goes from guaranteed failure to |
+execute at all on browser that do not support javascript, to full |
+support for all of the required features. |
+</p> |
+ |
+<p id="bdFD_11"> |
+You can tell when the browser does not support the |
+<code>clipboardData</code> feature from the script prior to using it |
+but the user has no way of knowing why a button that promised them |
+some action has failed to do anything. So in addition to matching the |
+script to the browser's ability to execute it, it is also necessary to |
+match the GUI, and the user's resulting expectations, to what the |
+script is going to be able to deliver. |
+</p> |
+ |
+<p id="bdFD_12"> |
+Suppose the <code>copyToClip</code> function was called from an |
+<code>INPUT</code> element of <code>type="button"</code> |
+and was intended to copy a company e-mail address into the clipboard, |
+the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> code for the button might look like:- |
+</p> |
+ |
+<pre id="bdFD_ex2"> |
+<input type="button" |
+ value="copy our contact e-mail address to your clipboard" |
+ onclick="copyToClip('info@example.com')"> |
+</pre> |
+ |
+<p id="bdFD_13"> |
+We know that that <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> will do nothing if javascript is |
+disabled/unavailable and we know that it will do nothing if the browser |
+does not support the required features, so one option would be to use a |
+script to write the button <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> into the document in the position in |
+which the button was wanted when the browser provided the facility:- |
+</p> |
+ |
+<pre id="bdFD_ex3"> |
+<script type="text/javascript"> |
+ if((typeof clipboardData != 'undefined')&& |
+ (clipboardData.setData)&& |
+ (document.write)){ |
+ document.write('<input type="button"', |
+ 'value="copy our contact e-mail address', |
+ ' to your clipboard" onclick="', |
+ 'copyToClip(\'info@example.com\')">'); |
+ } |
+</script> |
+</pre> |
+ |
+<p id="bdFD_14"> |
+Now the user will never see the button unless the browser supports the |
+required features <em>and</em> javascript is enabled. The user never |
+gets an expectation that the script will not be able to deliver (at |
+least that is the theory, it is still possible for the user's browser |
+configuration to prevent scripts from writing to the clipboard, but |
+the user might be expected to know how their browser is configured and |
+understand that the button is not in a position to override it). |
+</p> |
+ |
+<p id="bdFD_15"> |
+If the <code>copyToClip</code> function is only ever called from |
+buttons that are written only following the required feature detection |
+then it can be simplified by the removal of the test from its body as |
+it would be shielded from generating errors on nonsupporting browsers by |
+the fact that there would be no way for it to be executed. |
+</p> |
+ |
+<p id="bdFD_16"> |
+The <code>document.write</code> method is not the only way of adding |
+GUI components to a web page in a way that can be subject to the |
+verification of the features that render those components meaningful. |
+Alternatives include writing to a parent element's |
+<code>innerHTML</code> property (where supported, see |
+<a href="/faq/#updateContent">FAQ: How do I modify the content of the current page?</a>), or using the W3C DOM |
+<code>document.crateElement</code> (or <code>createElementNS</code>) |
+methods and appending the created element at a suitable location within |
+the DOM. Either of these two approaches are suited to adding the |
+components after the page has finished loading, but that can be useful |
+as some feature testing is not practical before that point. The |
+approach used can be chosen based on the requirements of the script. |
+If the script is going to be using the |
+<code>document.createElement</code> method itself then it is a good |
+candidate as a method for inserting any required GUI components, |
+similarly with <code>innerHTML</code>. The <code>document.write</code> |
+method is universally supported in <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> DOMs but is not necessarily |
+available at all in XHTML DOMs. |
+</p> |
+ |
+<p id="bdFD_17"> |
+Other ways of handling the possibility that the browser will not |
+support either javascript or the features required by the script used |
+is to design the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span>/<span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> parts of the page so that the script, upon |
+verifying support for the features it requires, can modify, manipulate |
+and transform the resulting elements in the DOM. But in the absence of |
+sufficient script support the unmodified <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> presents all of the |
+required content, navigation, etc. |
+</p> |
+ |
+<p id="bdFD_18"> |
+This can be particularly significant with things like navigation menus. |
+One style of design would place the content of the navigation menus, |
+the URLs and text, in javascript structures such as Arrays. But either |
+of javascript being disabled/unavailable on the client or the absence |
+of the features required to support a functional javascript menu would |
+leave the page without any navigation at all. Generally that would not |
+be a viable web page, and not that good for search engine placement as |
+search engine robots do not tend to execute javascript either so they |
+would be left unable to navigate a site featuring such a menu and so |
+unable to rank its content for listing. |
+</p> |
+ |
+<p id="bdFD_19"> |
+A better approach to menu design would have the navigation menu content |
+defined in the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span>, possibly as nested list elements of some sort, and |
+once the script has ascertained that the browser is capable of executing |
+it and providing the menu in an interactive form it can modify the <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> |
+<code>position</code>, <code>display</code> and <code>visibility</code> |
+properties, move the elements to their desired location, attach event |
+handlers and generally get on with the task of providing a javascript |
+menu. And the worst that happens when the browser does not support |
+scripting or the required features is that the user (and any search |
+engine robots) finds the navigation in the page as a series of nested |
+lists containing links. Fully functional, if not quite as impressive as |
+it could have been had the script been supported. This is termed |
+"clean degradation" and goes hand in hand with feature |
+detecting during the process of planing and implementing a browser |
+script for the Internet. |
+</p> |
+ |
+<h3 id="bdGEID">Example 1: IDed Element Retrieval</h3> |
+ |
+<p id="bdGEID_1"> |
+An important aspect of feature detecting is that it allows a script to |
+take advantage of possible fall-back options. Having deduced that a |
+browser lacks the preferred feature it still may be possible to |
+achieve the desired goal by using an alternative feature that is know |
+to exist on some browsers. A common example of this is retrieving an |
+element reference from the DOM given a string representing the |
+<code>ID</code> attribute of that element. The preferred method would |
+be the W3C Core DOM standard <code>document.getElementById</code> |
+method which is supported on the widest number of browsers. If that |
+method was not available but the browser happened to support the |
+<code>document.all</code> collection then it could be used for the |
+element retrieval as a fall-back option. And for some types of |
+elements, such as <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> positioned elements on Netscape 4 (where the |
+<code>document.layers</code> collection may be used to retrieve such |
+a reference), additional options may be available. |
+</p> |
+ |
+<pre id="bdGEID_ex1"> |
+function getElementWithId(id){ |
+ var obj; |
+ if(document.getElementById){ |
+ <span class="commentJS">/* Prefer the widely supported W3C DOM method, if |
+ available:- |
+ */</span> |
+ obj = document.getElementById(id); |
+ }else if(document.all){ |
+ <span class="commentJS">/* Branch to use document.all on document.all only |
+ browsers. Requires that IDs are unique to the page |
+ and do not coincide with NAME attributes on other |
+ elements:- |
+ */</span> |
+ obj = document.all[id]; |
+ }else if(document.layers){ |
+ <span class="commentJS">/* Branch to use document.layers, but that will only work for |
+ <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> positioned elements and LAYERs that are not nested. A |
+ recursive method might be used instead to find positioned |
+ elements within positioned elements but most DOM nodes on |
+ document.layers browsers cannot be referenced at all. |
+ */</span> |
+ obj = document.layers[id]; |
+ } |
+ <span class="commentJS">/* If no appropriate/functional element retrieval mechanism |
+ exists on this browser this function returns null:- |
+ */</span> |
+ return obj||null; |
+} |
+</pre> |
+ |
+<p id="bdGEID_2"> |
+Although that function is not very long or complex (without its |
+comments) it does demonstrate a consequence of one style of |
+implementation of feature detecting, it repeats the test each time |
+it is necessary to retrieve an element using its ID. If not too many |
+elements need retrieving that may not be significant, but if many |
+elements needed retrieving in rapid succession and performance was |
+significant then the overhead of performing the feature detection on |
+each retrieval may add up and impact on the resulting |
+script. |
+</p> |
+ |
+<p id="bdGEID_3"> |
+An alternative is to assign one of many functions to a global |
+<code>getElementWithId</code> variable based on the results of the |
+feature detecting tests, as the script loads. |
+</p> |
+ |
+<pre id="bdGEID_ex2"> |
+var getElementWithId; |
+if(document.getElementById){ |
+ <span class="commentJS">/* Prefer the widely supported W3C DOM method, if |
+ available:- |
+ */</span> |
+ getElementWithId = function(id){ |
+ return document.getElementById(id); |
+ } |
+}else if(document.all){ |
+ <span class="commentJS">/* Branch to use document.all on document.all only |
+ browsers. Requires that IDs are unique to the page |
+ and do not coincide with NAME attributes on other |
+ elements:- |
+ */</span> |
+ getElementWithId = function(id){ |
+ return document.all[id]; |
+ } |
+}else if(document.layers){ |
+ <span class="commentJS">/* Branch to use document.layers, but that will only work for <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> |
+ positioned elements. This function uses a recursive method |
+ to find positioned elements within positioned elements but most |
+ DOM nodes on document.layers browsers cannot be referenced at |
+ all. This function is expected to be called with only one |
+ argument, exactly like the over versions. |
+ */</span> |
+ getElementWithId = function(id, baseLayers){ |
+ <span class="commentJS">/* If the - baseLayers - parameter is not provided default |
+ its value to the document.layers collection of the main |
+ document: |
+ */</span> |
+ baseLayers = baseLayers||document.layers; |
+ <span class="commentJS">/* Assign the value of the property of the - baseLayers - |
+ object (possibly defaulted to the document.layers |
+ collection) with the property name corresponding to the |
+ - id - parameter to the local variable - obj: |
+ */</span> |
+ var obj = baseLayers[id]; |
+ <span class="commentJS">/* If - obj - remains undefined (no element existed with the |
+ given - id -) try searching the indexed members of |
+ - baseLayers - to see if any of their layers collections |
+ contain the element with the corresponding - id: |
+ */</span> |
+ if(!obj){ <span class="commentJS">//Element not found</span> |
+ <span class="commentJS">/* Loop through the indexed members of - baseLayers: */</span> |
+ for(var c = 0;c < baseLayers.length;c++){ |
+ if((baseLayers[c])&& <span class="commentJS">//Object at index - c.</span> |
+ (baseLayers[c].document)&& <span class="commentJS">//It has a - document.</span> |
+ <span class="commentJS">/* And a layers collection on that document: */</span> |
+ (baseLayers[c].document.layers)){ |
+ <span class="commentJS">/* Recursively call this function passing the - id - as |
+ the first parameter and the layers collection from |
+ within the document found on the layer at index - c |
+ - in - baseLayers - as the second parameter and |
+ assign the result to the local variable - obj: |
+ */</span> |
+ obj=getElementWithId(id,baseLayers[c].document.layers); |
+ <span class="commentJS">/* If - obj - is now not null then we have found the |
+ required element and can break out of the - for - |
+ loop: |
+ */</span> |
+ if(obj)break; |
+ } |
+ } |
+ } |
+ <span class="commentJS">/* If - obj - will type-convert to boolean true (it is not null |
+ or undefined) return it, else return null: |
+ */</span> |
+ return obj||null; |
+ } |
+}else{ |
+ <span class="commentJS">/* No appropriate element retrieval mechanism exists on |
+ this browser. So assign this function as a safe dummy. |
+ Values returned form calls to getElementWithId probably |
+ should be tested to ensure that they are non-null prior |
+ to use anyway so this branch always returns null:- |
+ */</span> |
+ getElementWithId = function(id){ |
+ return null; |
+ } |
+} |
+ |
+<span class="commentJS">/* |
+Usage:- |
+ |
+var elRef = getElementWithId("ID_string"); |
+if(elRef){ |
+ ... //element was found |
+}else{ |
+ ... //element could not be found. |
+} |
+*/</span> |
+</pre> |
+ |
+<p id="bdGEID_4"> |
+The feature detecting tests are performed once as the page loads and |
+one of many function expressions assigned to the |
+<code>getElementWithId</code> global variable as a result. The |
+assigned function is the one most capable of retrieving the required |
+element on the browser in use but it is still necessary to check that |
+the returned value in not <code>null</code> and plan for the |
+possibility of failure in the element retrieval process. It is |
+guaranteed to fail on any browser that does not implement at least one |
+of the element retrieval mechanisms used as the default function just |
+returns <code>null</code>. |
+</p> |
+ |
+<p id="bdGEID_5"> |
+It may not be sufficient to provide a function that does the best job |
+of element retrieval that can be done on the browser in use. Other |
+scripts, or parts of the script, may need to know how successful their |
+attempts to retrieve elements are likely to be. The |
+<code>getElementWithId</code> version that uses |
+<code>document.layers</code> cannot retrieve elements that are not <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> |
+positioned and that may not be good enough for some scripts, while it |
+may not matter to others. The <code>document.getElementById</code> and |
+<code>document.all</code> versions should be able to retrieve any |
+element given its <code>ID</code>. An opting would be to set a couple |
+of boolean flags to indicate how successful element retrieval can be |
+expected to be. Defaulting the flags to <code>false</code> and setting |
+them to <code>true</code> in the branches that assign the various |
+function expressions. Then if other code is interested in what can be |
+expected from the <code>getElementWithId</code> function, say in order |
+to decide how to configure, or default itself, it can check the |
+pertinent flag. |
+</p> |
+ |
+<pre id="bdGEID_ex3"> |
+var getElementWithId; |
+var canGetAnyElement = false; <span class="commentJS">//default any element flag</span> |
+var canGetCSSPositionedElements = false; <span class="commentJS">//default <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> positioned flag</span> |
+if(document.getElementById){ |
+ canGetAnyElement = true; <span class="commentJS">//set any element flag to true</span> |
+ canGetCSSPositionedElements = true; <span class="commentJS">//set <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> positioned flag true</span> |
+ getElementWithId = ... |
+}else if(document.all){ |
+ canGetAnyElement = true; <span class="commentJS">//set any element flag to true</span> |
+ canGetCSSPositionedElements = true; <span class="commentJS">//set <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> positioned flag true</span> |
+ getElementWithId = ... |
+}else if(document.layers){ |
+ canGetCSSPositionedElements = true; <span class="commentJS">//set <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> positioned flag true</span> |
+ <span class="commentJS">/* The - canGetAnyElement - flag is not set in this branch because |
+ the document.layers collection does not make *all* elements |
+ available. |
+ */</span> |
+ getElementWithId = ... |
+}else{ |
+ <span class="commentJS">/* Neither flag is set when the dummy function is assigned because |
+ it is guaranteed not to be able to retrieve any elements: |
+ */</span> |
+ getElementWithId = function(id){ |
+ return null; |
+ } |
+} |
+... |
+if(canGetCSSPositionedElements){ |
+ <span class="commentJS">/* Expect to be able to retrieve <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> positioned elements. |
+ */</span> |
+ ... |
+ if(canGetAnyElement){ |
+ <span class="commentJS">/* Expect to also be able to retrieve any other elements that |
+ have an ID attribute. |
+ */</span> |
+ ... |
+ } |
+} |
+</pre> |
+ |
+<p id="bdGEID_6"> |
+The flags do not directly reflect which feature is going to be used |
+for element retrieval, instead they reflect what can be expected from |
+the <code>getElementWithId</code> function on the current browser. |
+Allowing a script that requires a particular level of performance |
+(say the retrieval of any element) to determine whether it will have |
+that facility but without denying the facility from a script with a |
+less demanding requirement. |
+</p> |
+ |
+<h3 id="bdScroll">Example 2: Scroll Values</h3> |
+ |
+<p id="bdScroll_1"> |
+Another common task that needs to be approached differently on |
+different browsers is the retrieval of the extent to which the user |
+has scrolled a web page. The majority of browsers provide properties |
+of the global object called <code>pageXOffset</code> and |
+<code>pageYOffset</code>, which hold the relevant values. Some make the |
+equivalent browsers available as scrollLeft and scrollTop properties on |
+the "root" element (either in addition to the |
+<code>pageX/YOffset</code> properties or instead of them). The task is |
+complicated further by the fact that which element is the |
+"root" element depends on various factors, it was always the |
+<code>document.body</code> element in the past but newer (<span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span>) |
+standards compliant browsers (and browsers that can operate in various |
+modes, including standards compliant mode) make the |
+<code>document.documentElement</code> the root element. Then there may |
+be browsers that do not make the scrolling values available at all. |
+</p> |
+ |
+<p id="bdScroll_2"> |
+Because the <code>pageXOffset</code> and <code>pageYOffset</code> |
+properties are implemented on the largest number of browsers, and their |
+use avoids the need to worry about the "root" element, they |
+are the preferred values to use. In there absence the problem moves on |
+to identifying the "root" element, which is made easier by |
+the browsers that understand standards compliant mode and provide a |
+<code>document.compatMode</code> string property to announce which mode |
+they are in. If the string property is missing or the value of that |
+string is other than <code>"CSS1Compat"</code> then it is the |
+<code>document.body</code> object that needs to be read for the |
+scrolling values, else the <code>document.documentElement</code> should |
+be read. Testing for the presence of any of the scroll values |
+themselves needs to done with a <code>typeof</code> test because they |
+are numeric values and if implemented but set to zero a type-converting |
+test would return <code>false</code> but that would not be an indicator |
+of their absence. |
+</p> |
+ |
+<p id="bdScroll_3"> |
+The following is an example that employs feature detection to decide |
+which scroll values to read:- |
+</p> |
+ |
+<pre id="bdScroll_ex1"> |
+<span class="commentJS">/* The - getPageScroll - global variable is assigned a reference to a |
+ function and when that function is called initially it configures |
+ the script to read the correct values, if available, and then |
+ returns a reference to the object - interface - which provides |
+ methods that retrieve the scroll values. Subsequent invocations of |
+ the getPageScroll function do not repeat the configuration, they |
+ just return a reference to the same interface object. Because the |
+ configuration stage may need to check whether the document.body |
+ element exists the function cannot be called until the browser has |
+ parsed the opening body tag as prior to that point there is no |
+ document.body element. |
+ |
+ Usage:- |
+ var scrollInterface = getPageScroll(); |
+ var scrollX = scrollInterface.getScrollX(); |
+ var scrollY = scrollInterface.getScrollY(); |
+ |
+ The interface methods return NaN if the browser provides no method |
+ of reading the scroll values. A returned NaN value can be tested for |
+ with the - isNaN - global function, but it should not be necessary |
+ to perform the isNaN test on more than the first retrieval because |
+ if the returned value is NaN it will always be NaN and if it is not |
+ it should never be. |
+ |
+ if(isNaN(scrollX)){ |
+ //No scroll value retrieval mechanism was available on this browser |
+ } |
+ |
+ (* The script performs an inline execution of a function expression |
+ which returns the function object that is assigned to the - |
+ getPageScroll - global variable. This produces a closure that |
+ preserves the local variables of the executed function expression, |
+ allowing the execution context of the function expression to provide |
+ a repository for the configuration results, keeping them out of the |
+ global namespace. The format is:- |
+ |
+ v--- Anonymous function expression --v |
+ var variable = (function(){ ...; return returnValue; })(); |
+ Inline execution of the function expression ----^^ |
+ |
+ The value returned by the inline execution of the anonymous function |
+ expression is assigned to the variable. If that returned value is a |
+ reference to an inner function object then the assignment will form |
+ a closure.) |
+*/</span> |
+var getPageScroll = (function(){ |
+ <span class="commentJS">/* The local variable "global" is assigned the value - this - |
+ because the function expression is executing in the global |
+ context and - this - refers to the global object in that |
+ context. The global object is usually the - window - object on |
+ web browsers but this local variable is going to be used in the |
+ configuration tests for convenience: |
+ */</span> |
+ var global = this; |
+ <span class="commentJS">/* notSetUp - Is a flag to indicate when the script has done the |
+ setup configuration: |
+ */</span> |
+ var notSetUp = true; |
+ <span class="commentJS">/* readScroll - Is initially a dummy object that is used to return |
+ the NaN values whenever no functional scroll value retrieval |
+ mechanism is available on the browser. It is assigned a |
+ reference to the object from which the scroll values can be read |
+ if the feature detection determines that to be possible: |
+ */</span> |
+ var readScroll = {scrollLeft:NaN,scrollTop:NaN}; |
+ <span class="commentJS">/* Using the local variables - readScrollX - and readScrollY - to |
+ hold the property names allows the same functions to read both |
+ the pageX/YOffset properties of the global object and the |
+ scrollTop/Left properties of the "root" element by assigning |
+ different values to the variables. These are the defaults: |
+ */</span> |
+ var readScrollX = 'scrollLeft'; |
+ var readScrollY = 'scrollTop'; |
+ <span class="commentJS">/* The - itrface - local variable is assigned a reference to an |
+ object and it is this object that is returned whenever |
+ getPageScroll() is called. The object has two properties, |
+ getScrollX and getScrollY, which are assigned the values of two |
+ anonymous function expressions. These functions are inner |
+ functions and as a result have access to the local variables of |
+ the function that contains them (the anonymous function |
+ expression that is executed inline in order to assign value to |
+ the getPageScroll global variable). The use a square bracket |
+ property accessor to read a value of whatever object has been |
+ assigned to the variable - readScroll - with a property name |
+ that corresponds to the value assigned to whichever of the |
+ variables - readScrollX - or - readScrollY - are employed, |
+ allows the functions to use the simplest code poible to provide |
+ values for all of the possible permutations resting from the |
+ feature detection derived configuration: |
+ */</span> |
+ var itrface = { |
+ getScrollX:function(){ |
+ return readScroll[readScrollX]; |
+ }, |
+ getScrollY:function(){ |
+ return readScroll[readScrollY]; |
+ } |
+ }; |
+ <span class="commentJS">/* The - setUp - inner function is called to perform the feature |
+ detection and configure the variables that will be employed in |
+ reading the correct scroll values. It sets the - notSetUp - flag |
+ to false once it has been executed so that configuration only |
+ happens the first time that a request for the interface object |
+ is made: |
+ */</span> |
+ function setUp(){ |
+ <span class="commentJS">/* As the paeX/YOffset properties are the preferred values to |
+ use they are tested for first. They are not both tested |
+ because if one exists the other can be assumed to exist for |
+ symmetry. The testing method is a - typeof - test to see if |
+ the value is a number. A type-converting test cannot be used |
+ because the number zero would result in boolean false and a |
+ pageXOffset value will be zero if the page has not been |
+ scrolled: |
+ */</span> |
+ if(typeof global.pageXOffset == 'number'){ |
+ <span class="commentJS">/* If pageXOffset is a number then the value of the - |
+ global - variable (assigned a reference to the global |
+ object earlier) is assigned to the - readScroll - |
+ variable and the strings "pageXOffset" and "pageYOffset" |
+ are assigned to the - readScrollX - and - readScrollY - |
+ variables so they will be the property names used to |
+ access the - readScroll- (now the global) object. |
+ */</span> |
+ readScroll = global; |
+ readScrollY = 'pageYOffset'; |
+ readScrollX = 'pageXOffset'; |
+ }else{ |
+ <span class="commentJS">/* If pageXOffset is undefined it is time to find out which |
+ object is the "root" element. First, does the browser |
+ have a - document.compatMode - string, if it does then |
+ is its value "BackCompat", "QuirksMode" or "CSS1Compat". |
+ Instead of comparing the string directly it is searched |
+ for the substring "<span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span>" which might make the script more |
+ robust in the face of possible future "CSSnCompat" |
+ modes, which are unlikely to demand that the "root" |
+ element is moved again. |
+ |
+ The tests also verifies that there is a - |
+ document.documentElement - to read and that its |
+ - scrollLeft - property is a number: |
+ */</span> |
+ if((typeof document.compatMode == 'string')&& |
+ (document.compatMode.indexOf('CSS') >= 0)&& |
+ (document.documentElement)&& |
+ (typeof document.documentElement.scrollLeft=='number')){ |
+ <span class="commentJS">/* The - readScrollX - and - readScrollY - variables |
+ are already defaulted to the required strings so it |
+ is only necessary to assign a reference to the - |
+ document.documentElement - to the - readScroll - |
+ variable: |
+ */</span> |
+ readScroll = document.documentElement; |
+ <span class="commentJS">/* If the browser is not in the appropriate mode the scroll |
+ values should be read from the document.body - element, |
+ assuming it exists on this browser and that the |
+ - scrollLeft - property is a number: |
+ */</span> |
+ }else if((document.body)&& |
+ (typeof document.body.scrollLeft == 'number')){ |
+ <span class="commentJS">/* The - readScrollX - and - readScrollY - variables |
+ are already defaulted to the required strings so it |
+ is only necessary to assign a reference to the - |
+ document.body - to the - readScroll - variable: |
+ */</span> |
+ readScroll = document.body; |
+ } |
+ <span class="commentJS">/* No other scroll value reading options exist so if - |
+ readScroll - has not been assigned a new value by this |
+ point it will remain a reference to the object with the |
+ NaN value properties. |
+ */</span> |
+ } |
+ notSetUp = false; <span class="commentJS">//No need to repeat configuration.</span> |
+ } |
+ <span class="commentJS">/* The inline execution of the anonymous function expression |
+ returns with the following statement. It returns an inner |
+ function expression and it is that function that will be called |
+ when getPageScroll() is executed. Doing this forms a closure, |
+ preserving all of the local variables and functions defined |
+ within the executed anonymous function expression. Calling that |
+ returned function as - getPageScroll() - executes the setUp |
+ function, but only if it has not already been called, and |
+ returns a reference to the - itrface - object. |
+ */</span> |
+ return (function(){ |
+ if(notSetUp){ <span class="commentJS">//If the - notSetUp - variable is still true.</span> |
+ setUp(); <span class="commentJS">//Execute the - setUp - function.</span> |
+ } |
+ return itrface; <span class="commentJS">//returns a reference to - itrface</span> |
+ }); |
+})(); <span class="commentJS">//inline-execution of anonymous function expression, one-off!</span> |
+</pre> |
+ |
+<p id="bdScroll_4"> |
+The effect of this code is to match the browser's ability to provide |
+the scrolling information with a script's desire to read it through a |
+simple and efficient interface that acts based on the results of |
+featured detecting tests that it applies only once, and if the browser |
+does not support any methods of reading the scroll values the return |
+values form the interface method indicate that fact by being NaN. It |
+does not matter that Netscape 4 will be reading the global |
+<code>pageX/YOffset</code> properties, that IE 4 will read the |
+<code>scrollTop/Left</code> properties from <code>document.body</code> |
+or that IE 6 will read those values from one of two possible objects |
+based on the <code>document.compatMode</code> value. What is important |
+is that if unknown browser XYZ provides any of those mechanisms for |
+reporting the scroll values the script is going to be able to use them, |
+without ever knowing (or caring) that it is browser XYZ that it is |
+executing on. |
+</p> |
+ |
+<h3 id="bdReplace">Example 3: String.prototype.replace</h3> |
+ |
+<p id="bdReplace_1"> |
+Feature detecting is not restricted to features of the DOM, it can be |
+extended to include features of the javascript language implementation. |
+For example the <code>String.prototype.replace</code> function in later |
+language versions will accept a function reference as its second |
+argument, while earlier versions only accept a string in that context. |
+Code that wants to use the function argument facility of the |
+<code>replace</code> method will fail badly if it is not supported on |
+the browser. |
+</p> |
+ |
+<p id="bdReplace_2"> |
+As usual, a feature-detecting test for the implementation's ability to |
+support function arguments with the <code>replace</code> method has to |
+be a direct test on that feature. The following example test takes |
+advantage of the fact that a browser that only supports the string |
+argument version of <code>replace</code> will type-convert a function |
+reference used in that context into a string. The <code>replace</code> |
+method uses a Regular Expression (its first argument) to |
+identify parts of a string and then replaces them with a string that is |
+provided as its second argument. If the second argument is a function, |
+and the browser supports the function argument, that function is called |
+and its return value replaces the identified parts of the string. |
+</p> |
+ |
+<p id="bdReplace_3"> |
+By providing a function expression that returns an empty string as its |
+second argument and a Regular Expression that identifies the entire |
+original string as the first argument, the operation of the |
+<code>replace</code> method will result in an empty string if the |
+function argument is supported. But if only string arguments are |
+supported then the function will be type-converted into a string and |
+that string will not be an empty string so the result of the |
+evaluation of the <code>replace</code> method will not be an empty |
+string. Applying a NOT (<code>!</code>) operation to the resulting |
+string type-converts the empty string into a boolean value, inverts |
+it and returns <code>true</code>, the non-empty string would result |
+in <code>false</code>. |
+</p> |
+ |
+<pre id="bdReplace_ex1"> |
+<span class="commentJS">/* The original string is the one letter string literal "a". The |
+ Regular Expression /a/ identifies that entire string, so it is the |
+ entire original string that will be replaced. The second argument is |
+ the function expression - function(){return '';} -, so the entire |
+ original string will be replaced with an empty string if the |
+ function expression is executed. If it is instead type-converted |
+ into a string that string will not be an empty string. The NOT (!) |
+ operation type-converts its operand to boolean and then inverts it |
+ so the results of the test is boolean true if function references |
+ are supported in the second argument for the - replace - method, and |
+ false when not supported: |
+*/</span> |
+if(!('a'.replace(/a/, (function(){return '';})))){ |
+ ... <span class="commentJS">//function references OK.</span> |
+}else{ |
+ ... <span class="commentJS">//no function references with replace.</span> |
+} |
+</pre> |
+ |
+<p id="bdReplace_4"> |
+The common thread with feature detecting is that it is the code that is |
+going to use the features, and the nature of those features, that |
+defines how support for the required feature needs to be tested. Once |
+you get used to the idea it starts to become obvious which tests need |
+to be applied to verify a browser's support for a feature, and then it |
+is time to work on the efficient application of feature detection. |
+</p> |
+ |
+<h2 id="bdDesPb">The Javascript Design Problem</h2> |
+ |
+<p id="bdDesPb_1"> |
+Javascript as a language is not that complex, it may have its quirks |
+but it can be defined entirely in the 173 pages of the ECMA |
+specification (3rd edition). The challenge of authoring javascript |
+comes form the diversity of execution environments. When authoring for |
+the Internet nothing is known about the receiving software in advance, |
+and even when that software is a web browser that will execute |
+javascript, there is still a spectrum of possible DOM implementations |
+to contend with. |
+</p> |
+ |
+<p id="bdDesPb_2"> |
+The combination of the facts that it is impossible to determine which |
+browser is executing the script, and that it is impossible to be |
+familiar with all browser DOMs can be rendered insignificant by using |
+feature detection to match code execution with any browser's ability to |
+support it. But there is still going to be a diversity of |
+outcomes, ranging from total failure to execute any scripts (on |
+browsers that do not support javascript, or have it disabled) to full |
+successful execution on the most capable javascript enabled browsers. |
+</p> |
+ |
+<p id="bdDesPb_3"> |
+The challenge when designing scripts is to cope with all of the |
+possibilities in a way that makes sense for everyone. As those |
+possibilities will always include browsers incapable of executing |
+javascript at all, the starting point must be pages based on (valid) |
+<span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> that contain all of the required content, allow the necessary |
+navigation and are as functional as they purport to be (possibly with |
+the backing of server-side scripting, which does not have any of the |
+problems of client side scripting). On top of that reliable foundation |
+it is possible to layer the scripts. Feature detecting and adding |
+scripted enhancements when the browser is capable of supporting them, |
+cleanly degrading to the underlying and reliable <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> when it is not. |
+</p> |
+ |
+<p id="bdDesPb_4"> |
+A well designed script, implementing a suitable strategy, can enhance |
+the underlying <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> page, exploiting the browser's capabilities to the |
+maximum extent possible and still exhibit planed behaviour in the |
+absence of any (or all) desired features and degrade cleanly where |
+necessary. Nobody should either consider themselves a skilled Internet |
+javascript author, or deprecate javascript as a language and/or browser |
+scripting as a task, until they have demonstrated an ability to write |
+a non-trivial script that achieves that goal. |
+</p> |
+</body> |
+</html> |
/cljs/faq_notes/not_browser_detect.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/names/conclusion.html |
=================================================================== |
--- cljs/names/conclusion.html (nonexistent) |
+++ cljs/names/conclusion.html (revision 2) |
@@ -0,0 +1,120 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
+<html lang="en"> |
+<head> |
+ <title>Unsafe Names for HTML Form Controls - Conclusion</title> |
+ <meta http-equiv="content-type" content="text/html; charset=iso-8859-1"> |
+ <meta name="author" content="Garrett Smith"> |
+ <link rel="Start" href="./"> |
+ <link rel="stylesheet" href="../faq.css" type="text/css" media="all" charset="iso-8859-1"> |
+ <link rel="stylesheet" href="names.css" type="text/css" media="all" charset="iso-8859-1"> |
+</head> |
+<body> |
+ |
+ <h1>Unsafe Names for HTML Form Controls</h1> |
+ <h2>Conclusion</h2> |
+ |
+ <h3>Problem</h3> |
+ <p> |
+ Browser APIs and Web Standards are designed in such a way that |
+ element <code>id</code>s and <code>name</code>s, if not |
+ carefully chosen, may inadvertently pollute other objects |
+ with extra properties. This can cause problems. |
+ </p> |
+ |
+ <h3>Solution</h3> |
+ <p> |
+ There are several steps that you, as a page author, can take |
+ to avoid these problems. |
+ </p> |
+ |
+ <ul> |
+ <li> |
+ Be aware of the problem. |
+ </li> |
+ <li> |
+ Don't rely on the augmented scope chain to find properties of the <code>FORM</code>, |
+ <code>body</code>, or <code>document</code>. Instead, use fully qualified property lookups, |
+ e.g. <code>document.body</code>, <code>this.form.elements</code>. |
+ </li> |
+ <li> |
+ Avoid Event Handler Content Attributes. |
+ Events can be registered in the script (not in HTML). |
+ </li> |
+ <li> |
+ Use prefixed or "namespaced" names for |
+ <code>id</code> and <code>name</code> attribute values. |
+ </li> |
+ </ul> |
+ |
+ <h3>Do Web Standards Suck?</h3> |
+ <p> |
+ They are not without their problems. |
+ Most of the problems and <a href="extra_props.html#StandardWrong">misconceptions</a> |
+ would become self-evident if the standards bodies were to use a |
+ test-driven approach. The current approach is Big Up Front Design |
+ with the traditional analysis-documentation-implementation phases. |
+ The APIs are designed with a waterfall approach. |
+ </p> |
+ |
+ <p> |
+ Testing is informal and not part of the official process. This is something |
+ that needs to change in order to avoid unforseen pitfalls. Unfortunately, there has |
+ not been enough change in this direction and we can witness current problems |
+ with HTML 5 that build upon the mistakes of prior specifications and poor |
+ design of experimental implementations. |
+ </p> |
+ |
+ <p> |
+ A test-based process could have revealed the design problem |
+ with form-as-a-collection, as specified in HTML 5, or the issues |
+ with <code>body</code> event handler content attributes (e.g. |
+ <code>hashchange</code>). Multiple contributors |
+ to a test suite would make it hard for the author to ignore API design mistakes. |
+ </p> |
+ |
+ <h4>Normative References</h4> |
+ <ul id="controls-normref"> |
+ <li> [DOM1] |
+ <a href="http://www.w3.org/TR/REC-DOM-Level-1/level-one-html.html#ID-40002357" |
+ >Document Object Model (HTML) Level 1</a>, Mike Champion, others. |
+ </li> |
+ <li> [DOM2] |
+ <a href="http://www.w3.org/TR/DOM-Level-2-HTML/ecma-script-binding.html" |
+ >Document Object Model (HTML) Level 2</a>, Johnny Stenback, others. |
+ </li> |
+ <li> |
+ [DOMEvents] |
+ <a href="http://www.w3.org/TR/DOM-Level-3-Events/events.html" |
+ >Document Object Model Events</a>, Philippe Le Hégaret, Tom Pixley |
+ </li> |
+ <li> |
+ [HTML 5] |
+ <a href="http://www.whatwg.org/specs/">HTML 5</a>, |
+ Ian Hickson |
+ </li> |
+ <li>[WebIDL] |
+ <a href="http://www.w3.org/TR/WebIDL/">Web IDL</a>, |
+ Cameron McCormack |
+ </li> |
+ </ul> |
+ |
+ <div id="toc"> |
+ <h4>Table of Contents</h4> |
+ <ul class="pagination linkList"> |
+ <li><a href="./index.html">Introduction</a></li> |
+ <li><a href="extra_props.html">Extra Properties: <code>FORM</code> Elements</a></li> |
+ <li><a href="extra_props_document.html">Extra Properties: <code>document</code></a></li> |
+ <li><a href="extra_props_global.html">Extra Properties: <code>global</code></a></li> |
+ <li><a href="event_handler.html">Event Handler Scope</a></li> |
+ <li><a href="api_design.html">API Design?</a></li> |
+ <li><a href="unsafe_names.html">Unsafe Names</a></li> |
+ <li>Conclusion</li> |
+ </ul> |
+ </div> |
+ <ul id="nextLink" class="linkList"> |
+ <li> |
+ <span class="prev">Previous:</span> <a href="unsafe_names.html">Unsafe Names</a> |
+ </li> |
+ </ul> |
+</body> |
+</html> |
/cljs/names/conclusion.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/names/event_handler.html |
=================================================================== |
--- cljs/names/event_handler.html (nonexistent) |
+++ cljs/names/event_handler.html (revision 2) |
@@ -0,0 +1,305 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
+<html lang="en"> |
+<head> |
+ <meta http-equiv="content-type" content="text/html; charset=iso-8859-1"> |
+ <title>Unsafe Names for HTML Form Controls - Unsafe Names</title> |
+ <meta name="author" content="Garrett Smith"> |
+ <link rel="Start" href="./"> |
+ <link rel="stylesheet" href="../faq.css" type="text/css" media="all" charset="iso-8859-1"> |
+ <link rel="stylesheet" href="names.css" type="text/css" media="all" charset="iso-8859-1"> |
+</head> |
+<body> |
+ |
+ <h1>Unsafe Names for HTML Form Controls</h1> |
+ <h2>Event Handler Scope</h2> |
+ <h3>Event Handler Content Attributes and Augmented Scope Chain</h3> |
+ <p> |
+ Event Handler Content Attributes are event handler attributes that appear in the HTML source. |
+ </p> |
+ |
+ <p> |
+ When an element has an event handler content attribute, the value |
+ of that attribute becomes the <code>FunctionBody</code> of a function that the browser calls when it fires that event. |
+ </p> |
+ <p> |
+ Modern browsers augment the <code>FunctionBody</code>'s scope chain with the element, the element's <code>FORM</code> |
+ (if it is a form control), and <code>document</code>. There is no official standard for this augmented scope chain. |
+ </p> |
+ <p> |
+ Older browsers, such as Safari 2, Mozilla 1.x, Opera 7, differ. Scope augmentation occurs for all |
+ event handler content attributes with the notable exception of the <code>body</code> element, for |
+ which event handler scope is not consistently augmented across event types and implementations. |
+ </p> |
+ |
+ <p> |
+ The context (<code>thisArg</code>) is (with the exception of <code>body</code>), the element |
+ itself. In the browsers that implement DOM Events [<a href="conclusion.html#controls-normref">DOMEvents</a>], |
+ the event handler function has a single parameter named <code>event</code>. |
+ </p> |
+ |
+ <p> |
+ Given the following markup: |
+ </p> |
+<pre><p onclick="self.alert(event);"></p></pre> |
+ <p> |
+ The augmented scope chain, if written in ECMAScript, would look like: |
+ </p> |
+ |
+ <pre> |
+<span class='keyword'>function</span> onclick(<var>event</var>) { |
+ <span class='keyword'>with</span>(document) { |
+ <span class='keyword'>with</span>(<span class='keyword'>this</span>.form) { |
+ <span class='keyword'>with</span>(<span class='keyword'>this</span>) { |
+ self.alert(<var>event</var>); |
+ } |
+ } |
+ } |
+}</pre> |
+ <p> |
+ Note that some browsers will not supply an <code><var>event</var></code> parameter. |
+ </p> |
+ |
+ <h4>Example 3: Augmented Scope Chain</h4> |
+ <p> |
+ This example shows how <code>window</code> and <code>document</code> |
+ are shadowed: |
+ </p> |
+ <form action=""> |
+ <input type="hidden" name="document"> |
+ <button type="button" name="window" |
+ onclick="self.alert([window.tagName, document.tagName])" |
+ >self.alert([window.tagName, document.tagName])</button> |
+ </form> |
+ <strong>Source:</strong> |
+ <pre> |
+<form action=""> |
+ <input type="hidden" name="document"> |
+ <button type="button" name="window" |
+ onclick="self.alert([window.tagName, document.tagName])">self.alert([window.tagName, document.tagName])</button> |
+</form> |
+</pre> |
+ <p> |
+ The augmented scope chain, if written in ECMAScript, would look like: |
+ </p> |
+ |
+ <pre> |
+<span class='keyword'>function</span> onclick(<var>event</var>) { |
+ <span class='keyword'>with</span>(document) { |
+ <span class='keyword'>with</span>(<span class='keyword'>this</span>.form) { |
+ <span class='keyword'>with</span>(<span class='keyword'>this</span>) { |
+ self.alert([title, files, focus == window.focus]); |
+ <span class='keyword'>var</span> e = <var>event</var>||window.event; |
+ <span class='keyword'>if</span>(e && e.preventDefault) e.preventDefault(); |
+ e.returnValue = <span class='keyword'>false</span>; |
+ } |
+ } |
+ } |
+}</pre> |
+ |
+ <p> |
+ For all intents and purposes, the browser's |
+ <code>window</code> property of the <code>global</code> object is |
+ an alias to the the <code>global</code> object itself. |
+ </p> |
+ |
+ <p> |
+ Relying on an augmented scope chain to resolve properties may |
+ have unexpected results in different environments (i.e. browsers). The following example |
+ shows how in at least two browsers, <code>files</code> is resolved as a property |
+ of an <code>input</code> element. |
+ </p> |
+ |
+ <script type="text/javascript"> |
+ var files = [1,2,3]; |
+ </script> |
+ |
+ <form action=""> |
+ <input onclick="self.alert([title, files, focus == window.focus]); |
+ var e = event||window.event; |
+ if(e && e.preventDefault) e.preventDefault();e.returnValue = false;" type="file"> |
+ </form> |
+ <pre> |
+<script type="text/javascript"> |
+<span class='keyword'>var</span> files = [1,2,3]; |
+</script> |
+ |
+<form action=""> |
+ <input onclick="self.alert([title, files, focus == window.focus]); |
+ var e = event||window.event; |
+ if(e && e.preventDefault) e.preventDefault(); |
+ e.returnValue = false;" type="file"> |
+</form> |
+</pre> |
+ <h3>Result</h3> |
+ Firefox 3, Safari 3: |
+ <pre>",[object FileList],false"</pre> |
+ Opera 9.5, IE7, IE8: |
+ <pre>",1,2,3,false"</pre> |
+ |
+ <p> |
+ The identifier <code>files</code> is resolved on the input element |
+ in Firefox 3 and Safari 3. In IE8 or Opera 9.5, <code>files</code> is |
+ resolved on the window object. |
+ </p> |
+ <p> |
+ A <a href="scope_aug_example.html">modified example</a> from c.l.js thread <a |
+ href="http://groups.google.com/group/comp.lang.javascript/browse_frm/thread/2d1bd03a4bc47add" |
+ >"Works in ie and opera not mozilla"</a>, by Richard Cornford. |
+ </p> |
+ <h4>Browsers Tested:</h4> |
+<ul> |
+ <li>Opera 9.27, 9.63, 10a;</li> |
+ <li>Safari 3.2.1;</li> |
+ <li>Chrome 1.0.154.46;</li> |
+ <li>Firefox 2.0.0.18, 3.0.5;</li> |
+ <li>IE 7, 8.0RC1;</li> |
+ <li>IE 5.2 (Mac)</li> |
+ <li>Konqueror 4.1;</li> |
+ <li>Blackberry 4.7 (9500 model)</li> |
+ <li>MSIEMobile 6.0 (WinCE)</li> |
+</ul> |
+ <h4>Results:</h4> |
+<pre> |
+ex0 = global |
+ex1 = document #document |
+ex2 = document #document |
+ex3 = document #document |
+ex4 = 4 FORM |
+ex5 = 4 FORM |
+ex6 = 4 FORM |
+ex7 = 7 INPUT |
+ex8 = 7 INPUT |
+ex9 = 7 INPUT |
+ |
+// First link |
+ |
+ex0 = global |
+ex1 = document #document |
+ex2 = document #document |
+ex3 = document #document |
+ex4 = document #document |
+ex5 = document #document |
+ex6 = document #document |
+ex7 = document #document |
+ex8 = 8 A |
+ex9 = 8 A |
+ |
+// Second link |
+ |
+ex0 = global |
+ex1 = document #document |
+ex2 = document #document |
+ex3 = document #document |
+ex4 = document #document |
+ex5 = document #document |
+ex6 = document #document |
+ex7 = document #document |
+ex8 = document #document |
+ex9 = 9 A |
+</pre> |
+ <p>Most of the above results were provided by Juriy Zaytsev on thread |
+ <a |
+ href="http://groups.google.com/group/comp.lang.javascript/browse_frm/thread/8e48b8520d359395/61b45f35fb76694f" |
+ >Cross-Browser Mouse Event Handling</a>. |
+ </p> |
+<h4>Older Browsers</h4> |
+ <p> |
+ Less recent browsers, including Safari 2.0.4, Mozilla 1.x, |
+ and Opera 7, featured different scope chains. |
+ </p> |
+ |
+ <h4>Exception: The <code>BODY</code> Tag.</h4> |
+ <p> |
+ The <code>body</code> tag's event handler attributes are either mapped to |
+ <code>window</code> (which has no tag) or to the <code>BODY</code> element. |
+ Results vary based on the event and the browser. Do not use event handler |
+ attributes for the <code>body</code> element. |
+ </p> |
+ |
+ <h3>Problem</h3> |
+ |
+ <p> |
+ An augmented scope chain, combined with event handler content attributes, means that |
+ properties of the element itself, the element's form (if it is a form control), |
+ and document, may shadow properties of the window object. |
+ As explained in: <a href="http://groups.google.com/group/comp.lang.javascript/msg/3f5495216b3e9b67" |
+ >select?</a>, and |
+ <a href="http://lists.whatwg.org/htdig.cgi/whatwg-whatwg.org/2008-September/016184.html" |
+ >hashchange only dispatched in history traversal</a>, comments by Garrett Smith. Shortened code excerpt: |
+ </p> |
+ <pre> |
+<img name='alert' alt="Alert!" src="alert.jpg"> |
+<button onclick="self.alert(alert);">self.alert(alert);</button> |
+</pre> |
+ |
+<img name='alert' alt="Alert!" src="" style="z-index:-1;position:absolute"> |
+<button onclick="self.alert(alert);">self.alert(alert);</button> |
+ |
+ <h4>Result</h4> |
+ <p> |
+ Alerts <samp>[object HTMLImageElement]</samp> (or similar implementation-dependent string). |
+ </p> |
+ |
+ <p> |
+ By using an unsafe name of <samp>"alert"</samp> for an <code>IMG</code>, |
+ The <code>window</code>'s <code>alert</code> property |
+ identifier is shadowed by <code>document</code>'s <code>alert</code> |
+ property identifier because |
+ <code>document</code> is in the event handler's augmented scope |
+ before <code>window</code>. |
+ </p> |
+ |
+ <p> |
+ By using event handler content attributes and unsafe names, |
+ <code>document</code> and <code>window</code>, the respective identifiers |
+ are resolved on the augmented scope chain. |
+ </p> |
+ |
+ <p> |
+ The augmented scope chain |
+ creates more ambiguity and increases the number of unsafe names. |
+ </p> |
+ <h3>Solution</h3> |
+ <ul> |
+ <li> |
+ Don't rely on the augmented scope chain to find properties of the <code>FORM</code>, |
+ <code>body</code>, or <code>document</code>. Instead, use fully qualified property lookups, |
+ e.g. <code>document.body</code>, <code>this.form.elements</code>. |
+ </li> |
+ <li> |
+ Avoid Event Handler Content Attributes. |
+ Registering event callbacks in the script (not in HTML) avoids |
+ the possibility of a property such as unqualified <code>alert</code> |
+ being resolved on an object other than <code>window</code>. |
+ </li> |
+ <li> |
+ Do not use Event Handler Content Attributes for <code>body</code>. |
+ </li> |
+ <li> |
+ Use prefixed names for all <code>id</code> or <code>name</code> attribute values. |
+ </li> |
+ </ul> |
+ |
+ <div id="toc"> |
+ <h4>Table of Contents</h4> |
+ <ul class="pagination linkList"> |
+ <li><a href="./index.html">Introduction</a></li> |
+ <li><a href="extra_props.html">Extra Properties: <code>FORM</code> Elements</a></li> |
+ <li><a href="extra_props_document.html">Extra Properties: <code>document</code></a></li> |
+ <li><a href="extra_props_global.html">Extra Properties: <code>global</code></a></li> |
+ <li>Event Handler Scope</li> |
+ <li><a href="api_design.html">API Design?</a></li> |
+ <li><a href="unsafe_names.html">Unsafe Names</a></li> |
+ <li><a href="conclusion.html">Conclusion</a></li> |
+ </ul> |
+ </div> |
+ <ul id="nextLink" class="linkList"> |
+ <li> |
+ <span class="prev">Previous:</span> <a href="extra_props_global.html">Extra Properties: global</a> |
+ </li> |
+ <li> |
+ <span class="next">Next:</span> <a href="api_design.html">API Design?</a> |
+ </li> |
+ </ul> |
+</body> |
+</html> |
/cljs/names/event_handler.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/names/map-like-nodelist.html |
=================================================================== |
--- cljs/names/map-like-nodelist.html (nonexistent) |
+++ cljs/names/map-like-nodelist.html (revision 2) |
@@ -0,0 +1,34 @@ |
+<!doctype html> |
+<html> |
+<head> |
+<title>Map-like NodeList Example</title> |
+</head> |
+<body> |
+<h1>Map-like NodeList Example</h1> |
+<div id="item"></div> |
+<div id="length"></div> |
+<pre> |
+<script type="text/javascript"> |
+var divs = document.getElementsByTagName('div'); |
+document.writeln("divs.item.tagName = " + divs.item.tagName); |
+document.writeln("divs.length.tagName = " + divs.length.tagName); |
+</script> |
+</pre> |
+<hr> |
+<h2>Opera, IE</h2> |
+<pre> |
+DIV DIV |
+</pre> |
+ |
+<h2>Safari 3</h2> |
+<pre> |
+DIV undefined |
+</pre> |
+ |
+<h2>Firefox</h2> |
+<pre> |
+undefined undefined |
+</pre> |
+ |
+</body> |
+</html> |
/cljs/names/map-like-nodelist.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/names/scope_aug_example.html |
=================================================================== |
--- cljs/names/scope_aug_example.html (nonexistent) |
+++ cljs/names/scope_aug_example.html (revision 2) |
@@ -0,0 +1,83 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
+ "http://www.w3.org/TR/html4/loose.dtd"> |
+<html lang="en"> |
+ <head> |
+ <title>Augmented Scope Chain in Event Handlers</title> |
+<script type="text/javascript"> |
+ |
+function setExpandos(){ |
+ setExs(window,0, 'global'); |
+ setExs(document,1, 'document'); |
+ setExOn(document.body,2, 'body'); |
+} |
+ |
+function setExOn(obj, depth, data){ |
+ if(obj.nodeType == 1){ |
+ setExs(obj,depth, data); |
+ var o = obj.children||obj.childNodes; |
+ for(var c = 0;c < o.length;c++){ |
+ setExOn(o[c], (depth+1), (depth+1)); |
+ } |
+ } |
+} |
+ |
+function setExs(obj,start, data){ |
+ for(var c = start;c < 10;c++){ |
+ obj['ex'+c] = data+((obj.nodeName)?(' '+obj.nodeName):''); |
+ } |
+} |
+ |
+var res = [ |
+'chain results > ', |
+'\nex0 = ','', //2 |
+'\nex1 = ','', //4 |
+'\nex2 = ','', //6 |
+'\nex3 = ','', //8 |
+'\nex4 = ','', //10 |
+'\nex5 = ','', //12 |
+'\nex6 = ','', //14 |
+'\nex7 = ','', //16 |
+'\nex8 = ','', //18 |
+'\nex9 = ','' //20 |
+]; |
+ |
+</script> |
+</head> |
+<body onload="setExpandos();"> |
+<div> |
+<form action=""> |
+ <div> |
+ <p> |
+ <input type="button" value="Form Button" |
+ onclick="var a = res;a[2] = ex0;a[4] = ex1; |
+ a[6] = ex2;a[8] = ex3;a[10] = ex4; |
+ a[12] = ex5;a[14] = ex6;a[16] = ex7; |
+ a[18] = ex8;a[20] = ex9; |
+ alert(a.join(''));return false;"> |
+ </p> |
+ </div> |
+</form> |
+<table> |
+ <thead> |
+ <tr><th><a href="#" |
+ onclick="var a = res;a[2] = ex0;a[4] = ex1; |
+ a[6] = ex2;a[8] = ex3;a[10] = ex4; |
+ a[12] = ex5;a[14] = ex6;a[16] = ex7; |
+ a[18] = ex8;a[20] = ex9; |
+ alert(a.join(''));return false;"> |
+ thead</a></th></tr> |
+ </thead> |
+ <tbody> |
+ <tr><td><span> |
+ <a href="#" |
+ onclick="var a = res;a[2] = ex0;a[4] = ex1; |
+ a[6] = ex2;a[8] = ex3;a[10] = ex4; |
+ a[12] = ex5;a[14] = ex6;a[16] = ex7; |
+ a[18] = ex8;a[20] = ex9; |
+ alert(a.join(''));return false;"> |
+ tbody</a></span></td></tr> |
+ </tbody> |
+</table> |
+</div> |
+</body> |
+</html> |
\ No newline at end of file |
/cljs/names/scope_aug_example.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/names/extra_props_global.html |
=================================================================== |
--- cljs/names/extra_props_global.html (nonexistent) |
+++ cljs/names/extra_props_global.html (revision 2) |
@@ -0,0 +1,200 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
+<html lang="en"> |
+<head> |
+ <title>Unsafe Names for HTML Form Controls - Extra Properties: Global</title> |
+ <meta http-equiv="content-type" content="text/html; charset=iso-8859-1"> |
+ <meta name="author" content="Garrett Smith"> |
+ <link rel="Start" href="./"> |
+ <link rel="stylesheet" href="../faq.css" type="text/css" media="all" charset="iso-8859-1"> |
+ <link rel="stylesheet" href="names.css" type="text/css" media="all" charset="iso-8859-1"> |
+</head> |
+<body> |
+ |
+ <h1>Unsafe Names for HTML Form Controls</h1> |
+ <h2>Extra Properties: <code>global</code></h2> |
+ |
+ <h3>Extra Properties: The Element Id Resolver Object</h3> |
+ <p> |
+ IE, Opera, Firefox, and Webkit |
+ seem to implement a non-standard <dfn>element id resolver</dfn> |
+ object. This object is used to retrieve the element. |
+ See comp.lang.javscript thread: |
+ <a href="http://groups.google.com/group/comp.lang.javascript/msg/aed8ecf1660e1dd1" |
+ >Why "window.alert()" over "alert()"?</a>, comment by Lasse Reichstein Nielsen. |
+ </p> |
+ |
+ <p> |
+ In some browsers, this behavior depends on the DOCTYPE used. |
+ </p> |
+ |
+ <p> |
+ This is a non-standard behavior of browsers that applies to <em>any</em> element with |
+ an <code>id</code>, not only form controls. |
+ </p> |
+ |
+ <p> |
+ Assigning to an undeclared identifier should result in a new global |
+ property being created, or, if the global/window object has a property with |
+ that name, its value should be replaced. However in some |
+ browsers, the assigment can result in an error. |
+ </p> |
+ |
+ <p> |
+ The properties of the "element resolver" may appear to be shadowed by |
+ properties of the global object, or vice-versa. |
+ </p> |
+ |
+<h4>Property Assignment to Element</h4> |
+ <script type="text/javascript"> |
+var globalVal; |
+function addScript(id) { |
+ var script = document.createElement('script'), |
+ src = document.getElementById(id); |
+ script.text = src.firstChild.data; |
+ |
+ document.body.appendChild(script); |
+ document.getElementById(id+"Result").firstChild.data = globalVal; |
+} |
+ </script> |
+ <p> |
+ The following example should result: <samp>undefined, 11</samp>. |
+ </p> |
+ |
+ <button id='b1' onclick="addScript('g1')">addScript('g1')</button> |
+ <code id='g1Result'> </code> |
+ <pre id="g1"> |
+try { |
+ var b1; |
+ globalVal = [String(b1)]; // Should be "undefined". |
+ b1 = 11; |
+ globalVal = globalVal.concat(b1); // Should be ["undefined", 11] |
+} catch(ex) { |
+ globalVal = ex.message; |
+} |
+</pre> |
+ <p> |
+ The following example does not declare a variable. The browser may optionally |
+ resolve the identifier <code>b2</code> on the <dfn>element id resolver</dfn> object. |
+ </p> |
+ <button id='b2' onclick="addScript('g2')">addScript('g2')</button> |
+<code id='g2Result'> </code> |
+<pre id="g2"> |
+try { |
+ globalVal = [typeof b2]; |
+ b2 = 11; // undeclared assignment. |
+ globalVal = globalVal.concat(b2); |
+} catch(ex) { |
+ globalVal = ex.message; |
+} |
+</pre> |
+ <p> |
+ The following example should result: <samp>undefined, 11</samp>. |
+ </p> |
+ <button id='b3' onclick="addScript('g3')">addScript('g3')</button> |
+<code id='g3Result'> </code> |
+<pre id="g3"> |
+// remove element id. |
+document.getElementById('b3').id = ''; |
+ |
+try { |
+ globalVal = [typeof b3]; // should be "undefined". |
+ b3 = 11; // undeclared assignment. |
+ globalVal = globalVal.concat(b3); |
+} catch(ex) { |
+ globalVal = ex.message; |
+} |
+</pre> |
+ <p> |
+ Declared variables that have not yet been assigned a value create a property |
+ on the Variable object with the value <code>undefined</code>. |
+ </p> |
+ <p> |
+ If the <dfn>element id resolver</dfn> object exists above the scope of |
+ the global object, the identifier will be shadowed by the global variable object. |
+ </p> |
+<h3>Results</h3> |
+<p>Firefox:</p> |
+<ul> |
+ <li> |
+ <samp class="expected">undefined, 11</samp> |
+ </li> |
+ <li> |
+ <samp>object, 11</samp> |
+ </li> |
+ <li> |
+ <samp class="expected">undefined, 11</samp> |
+ </li> |
+</ul> |
+<p>Opera 9.5:</p> |
+<ul> |
+ <li> |
+ <samp class="error">undefined, 11</samp> |
+ </li> |
+ <li> |
+ <samp>object, 11</samp> |
+ </li> |
+ <li> |
+ <samp class="expected">undefined, 11</samp> |
+ </li> |
+</ul> |
+<p>Safari 2.0.2, 3.1:</p> |
+<ul> |
+ <li> |
+ <samp class="error">[object HTMLButtonElement], 11</samp> |
+ </li> |
+ <li> |
+ <samp>object, 11</samp> |
+ </li> |
+ <li> |
+ <samp class="expected">undefined, 11</samp> |
+ </li> |
+</ul> |
+<p>MSIE 7</p> |
+<ul> |
+ <li> |
+ <samp>undefined, 11</samp> |
+ </li> |
+ <li> |
+ <samp>Object doesn't support this property or method</samp> |
+ </li> |
+ <li> |
+ <samp>undefined, 11</samp> |
+ </li> |
+</ul> |
+<p>MSIE 6</p> |
+<ul> |
+ <li> |
+ <samp>undefined, 11</samp> |
+ </li> |
+ <li> |
+ <samp>Object doesn't support this property or method</samp> |
+ </li> |
+ <li> |
+ <samp>undefined, 11</samp> |
+ </li> |
+</ul> |
+ |
+<div id="toc"> |
+ <h4>Table of Contents</h4> |
+ <ul class="pagination linkList"> |
+ <li><a href="./index.html">Introduction</a></li> |
+ <li><a href="extra_props.html">Extra Properties: <code>FORM</code> Elements</a></li> |
+ <li><a href="extra_props_document.html">Extra Properties: <code>document</code></a></li> |
+ <li>Extra Properties: <code>global</code></li> |
+ <li><a href="event_handler.html">Event Handler Scope</a></li> |
+ <li><a href="api_design.html">API Design?</a></li> |
+ <li><a href="unsafe_names.html">Unsafe Names</a></li> |
+ <li><a href="conclusion.html">Conclusion</a></li> |
+ </ul> |
+</div> |
+<ul id="nextLink" class="linkList"> |
+ <li> |
+ <span class="prev">Previous:</span> <a href="extra_props_document.html">Extra Properties: <code>document</code></a> |
+ </li> |
+ <li> |
+ <span class="next">Next:</span> <a href="event_handler.html">Event Handler Scope</a> |
+ </li> |
+</ul> |
+ |
+</body> |
+</html> |
\ No newline at end of file |
/cljs/names/extra_props_global.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/names/form_dom_removal.html |
=================================================================== |
--- cljs/names/form_dom_removal.html (nonexistent) |
+++ cljs/names/form_dom_removal.html (revision 2) |
@@ -0,0 +1,53 @@ |
+<!DOCTYPE HTML> |
+<html> |
+<head> |
+<title>Test element Removal</title> |
+<style type='text/css'> |
+ .fail { background: #F33; } |
+ .pass { background: #0f0; } |
+ b { display: none; padding: 1px 3px; |
+ font-family: monospace; white-space: pre;} |
+</style> |
+</head> |
+<body> |
+<form action=""> |
+<input type="text" name="test"> |
+</form> |
+ |
+<b id="failElements" class="fail">FAIL</b> |
+<b id="passElements" class="pass">PASS</b> |
+<strong>form.elements.test is null?</strong> |
+ |
+<div> |
+<b id="passForm" class="pass">PASS</b> |
+<b id="failForm" class="fail">FAIL</b> |
+<strong>form.test is null?</strong> |
+</div> |
+ |
+<script type="text/javascript"> |
+var d = document, |
+ form = d.forms[0], |
+ display = "inline-block", |
+ failElements = d.getElementById('failElements'), |
+ passElements = d.getElementById('passElements'), |
+ failForm = d.getElementById('failForm'), |
+ passForm = d.getElementById('passForm'); |
+ |
+// comment the following line to hide bug: |
+form.test; |
+ |
+while(form.lastChild){ |
+ form.removeChild(form.lastChild); |
+} |
+if(document.forms[0].elements.test ) |
+ failElements.style.display = display; |
+else |
+ passElements.style.display = display; |
+ |
+if(document.forms[0].test ) |
+ failForm.style.display = display; |
+else |
+ passForm.style.display = display; |
+</script> |
+</body> |
+</html> |
\ No newline at end of file |
/cljs/names/form_dom_removal.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/names/names.css |
=================================================================== |
--- cljs/names/names.css (nonexistent) |
+++ cljs/names/names.css (revision 2) |
@@ -0,0 +1,104 @@ |
+#toc ul.linkList { |
+ /* 160% * 62.5% = 100% */ |
+ font-size : 62.5%; |
+ margin: 0; |
+} |
+ |
+body { |
+ position: relative; |
+} |
+ |
+ul { |
+ margin : 1em 2.0em 1.5em 2.5em; |
+} |
+ul.linkList li { |
+ line-height: 120%; |
+ padding-top: 5px; |
+ padding-bottom: 5px; |
+} |
+ |
+#toc{ |
+ background: transparent; |
+ border: 0; |
+} |
+ |
+ul.linkList li { |
+ display: inline; |
+ margin: .4em; |
+ color: #334; |
+ white-space: nowrap; |
+} |
+ |
+ul.linkList li a code { |
+ color: inherit; |
+ padding: 0; |
+ font-size: 105%; |
+ font-weight: normal; |
+} |
+ |
+#toc { |
+ position: absolute; |
+ top: 2em; |
+ *top: 3em; |
+ font-size : 160%; |
+ padding: 0; |
+ width: 97.5%; |
+} |
+ |
+#toc h4 { |
+ font-size : 62.5%; |
+ margin-bottom: 0; |
+ display: none; |
+ } |
+ |
+h1 { |
+ /* space for toc */ |
+ margin-bottom: 3em; |
+} |
+ |
+ul.linkList { |
+ margin-left: 0; |
+ margin-top: 0; |
+ font-weight: 800; |
+} |
+ |
+.next, .prev { |
+ font-style: italic; |
+ color: #334; |
+ margin-right: .1em; |
+ font-weight: 400; |
+} |
+ |
+div { |
+ padding: 0; |
+ margin: 0; |
+} |
+ |
+button.evaluator { |
+ margin-right: .4em; |
+} |
+ |
+ins { |
+ background: #ffc; |
+ border-bottom: 1px dotted #ec9; |
+ margin: 1px; |
+ text-decoration: none; |
+ padding: 1px; |
+} |
+ |
+ins[title]:before, del[title]:before { |
+ content: attr(title); |
+ display: block; |
+ background: #666; |
+ color: #fff; |
+ padding: 2px; |
+ font-style: italic; |
+} |
+ |
+body > ins, body > del { |
+ display: block; |
+} |
+del { |
+ background: #fdc; |
+ color: #333; |
+} |
/cljs/names/names.css |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/names/simple-leak-form-input.html |
=================================================================== |
--- cljs/names/simple-leak-form-input.html (nonexistent) |
+++ cljs/names/simple-leak-form-input.html (revision 2) |
@@ -0,0 +1,20 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
+ "http://www.w3.org/TR/html4/loose.dtd"> |
+<html lang="en"> |
+<head><title></title></head> |
+<body> |
+<form action=""><input name="foo"><input name="bar"></form> |
+<pre> |
+<script type="text/javascript"> |
+document.forms[0].foo; |
+document.forms[0].elements.foo; |
+ |
+// Clear out form's HTML. |
+document.forms[0].innerHTML = ""; |
+document.write('foo: ' + document.forms[0].foo+'<br>'); |
+document.write('bar: '+document.forms[0].bar+'<br>'); |
+document.write('elements.foo: '+document.forms[0].elements.foo); |
+</script> |
+</pre> |
+</body> |
+</html> |
\ No newline at end of file |
/cljs/names/simple-leak-form-input.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/names/form_override_dom.html |
=================================================================== |
--- cljs/names/form_override_dom.html (nonexistent) |
+++ cljs/names/form_override_dom.html (revision 2) |
@@ -0,0 +1,87 @@ |
+<!DOCTYPE HTML> |
+<html lang="en"> |
+<head> |
+ <title>FormElementCollection.html</title> |
+ <style type="text/css"> |
+ input { font-size: 8px; font-family: courier new, monospace; padding: 0 } |
+ #pass { display: none; background : #0f0; } |
+ #fail { display: none; background : #F33; } |
+ </style> |
+</head> |
+<body> |
+<h1>Test: 290 Names not to give a FORM Control</h1> |
+<form name="length" action="fail" title="fail"> |
+<input type="submit" /> |
+</form> |
+<form name="title"></form> |
+ |
+<pre id="pass">PASS - All Form Properties Replaced by an Element</pre> |
+<pre id="fail">FAIL</pre> |
+<pre> |
+<script type='text/javascript' src="names.js"></script> |
+<script type="text/javascript"> |
+ |
+(function(){ |
+var form = document.forms[0]; |
+var input = document.createElement('input'), |
+ clone; |
+var bugs = []; |
+ |
+input.type = "text"; |
+ |
+for(var i = names.length -1; i >= 0; i--) { |
+ try { |
+ if(names[i] == names[i-1]) { |
+ alert("found duplicate: " + names[i]); |
+ break; |
+ } |
+ else { |
+ clone = input.cloneNode(false); |
+ clone.name = clone.id = names[i]; |
+ clone.value = names[i]; |
+ form.appendChild(clone); |
+ } |
+ } catch(ex) { |
+ //("could not create input named: " + names[i]); |
+ } |
+} |
+// can't use form.elements, form.getElementsByTagName, et c |
+// because they were replaced by an input. |
+ |
+var actual, expected, msg, actualString; |
+for(i = 0; i < names.length; i++) { |
+ |
+ actual = form[names[i]]; |
+ expected = document.getElementById(names[i]); |
+ if(actual != expected) { |
+ msg = names[i]; |
+ if(actual.toString && actual.toString.tagName) |
+ actualString = actual.toString.tagName; |
+ else |
+ actualString = String(actual); |
+ msg += " found: " + (((actualString + " ("+typeof actual+")")) || "(missing)"); |
+ bugs[bugs.length] = msg; |
+ } |
+} |
+ |
+if(bugs.length > 0) |
+ fail(bugs); |
+else pass(); |
+ |
+function fail(bugs) { |
+ var fail = document.getElementById('fail'); |
+ fail.firstChild.data += ': The following ' + bugs.length + |
+ ' form properties should have been an INPUT element:\n * ' + bugs.join('\n * '); |
+ fail.style.display = "inline-block"; |
+} |
+ |
+function pass() { |
+ var pass = document.getElementById('pass'); |
+ pass.style.display = "inline-block"; |
+} |
+ |
+//document.write(names.join("\n </li>\n <li>\n ")); |
+})(); |
+</script> |
+</body> |
+</html> |
/cljs/names/form_override_dom.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/names/api_design.html |
=================================================================== |
--- cljs/names/api_design.html (nonexistent) |
+++ cljs/names/api_design.html (revision 2) |
@@ -0,0 +1,169 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
+<html lang="en"> |
+<head> |
+ <title>Unsafe Names for HTML Form Controls - API Design?</title> |
+ <meta http-equiv="content-type" content="text/html; charset=iso-8859-1"> |
+ <meta name="author" content="Garrett Smith"> |
+ <link rel="Start" href="./"> |
+ <link rel="stylesheet" href="../faq.css" type="text/css" media="all" charset="iso-8859-1"> |
+ <link rel="stylesheet" href="names.css" type="text/css" media="all" charset="iso-8859-1"> |
+</head> |
+<body> |
+ |
+ <h1>Unsafe Names for HTML Form Controls</h1> |
+ <h2>API Design?</h2> |
+ <h3>Form-as-a-collection Design Decision</h3> |
+ |
+ <p> |
+ Form-as-a-collection is problematic for implementors and should be a |
+ concern for developers (because bugs can occur when unsafe names are used). |
+ </p> |
+ |
+ <p> |
+ The idea of creating properties on a form creates |
+ a conflict. In Opera, the same key may appear twice in a for in loop. |
+ <a href="http://groups.google.com/group/comp.lang.javascript/browse_frm/thread/a27c626bd71f1f0/" |
+ >Opera, For In Loop, Same Key Appears Twice</a>. |
+ </p> |
+ |
+ <p> |
+ The elements collection is a safe alternative. |
+ By deprecating the non-standard mystery <code>"similar to a collection"</code> |
+ behavior of a form, authors would be discouraged from using it. |
+ </p> |
+ |
+ <p> |
+ Developers can still safely access the properties directly from the <code>elements</code> collection. |
+ There is no need to standardize this. |
+ </p> |
+ <h4>HTML 5</h4> |
+ <p> |
+ The HTML 5 draft has merged in much of the Web Forms 2.0 specification, |
+ which attempted to standardize some of the browser inconsistencies, strange behavior, |
+ and bugs. |
+ </p> |
+ |
+ <h4 id="controls-example-2">toString Example</h4> |
+ <p> |
+ This example contains a <code>FORM</code> element with two form controls, |
+ one named "length", the other "toString". A click callback is added to the |
+ <code>FORM</code>'s <code>length</code> property. The body of the function calls |
+ the <code>alert</code> function with the <code>FORM</code>. |
+ </p> |
+ <form action=";" id="form1" style="display:inline"> |
+ <input name="toString" type="hidden"> |
+ <input name="length" value="submit" type="submit"> |
+ </form> |
+ (Click the submit button to see what happens.) |
+ |
+ <script type="text/javascript"> |
+ (function (){ |
+ var form = document.getElementById('form1'); |
+ form.length.onclick = function(e) { |
+ try{ |
+ alert(form); |
+ } catch(ex) { |
+ alert("Error:\n" +ex.message); |
+ } finally { |
+ return false; |
+ } |
+ }; |
+ })(); |
+ </script> |
+ |
+ <p> |
+ <a onclick="toggleDisplay('controls-example-2-source', 'block', 'none'); return false;" |
+ href="">source...</a> |
+ </p> |
+ |
+ <pre id='controls-example-2-source' style="display:none"> |
+<form action="" id="form1"> |
+<input name="toString" type="hidden"/> |
+<input name="length" value="submit" type="submit"/> |
+</form> |
+<script type="text/javascript"> |
+(<span class='keyword'>function</span> (){ |
+ <span class='keyword'>var</span> form = document.getElementById(<span class='q'>'form1'</span>); |
+ form.length.onclick = <span class='keyword'>function</span>(e) { |
+ <span class='keyword'>try</span>{ |
+ alert(form); |
+ } <span class='keyword'>catch</span>(ex) { |
+ alert(<span class='q'>"Error:\n"</span> +ex.message); |
+ } <span class='keyword'>finally</span> { |
+ <span class='keyword'>return</span> <span class='keyword'>false</span>; |
+ } |
+ }; |
+})();</script> |
+ </pre> |
+ |
+ <strong>Result</strong> |
+ <p> |
+ The callback tries to <code>alert</code> |
+ the <code>FORM</code> but throws an error when the <code>alert</code> function |
+ attempts to call the form's <code>toString</code> |
+ property, which was shadowed by a form control. |
+ </p> |
+ |
+ <h3>Callable Collections</h3> |
+ <p> |
+ Many browsers make <code>HTMLCollection</code> collection a callable object. |
+ When called, <code>document.forms(<var>x</var>)</code> returns a form element whose <code>name</code>, |
+ <code>id</code>, or <code>index</code> matches the supplied argument <code><var>x</var></code>. |
+ </p> |
+ <p> |
+ <a href="callable_example.html">Callable HTMLCollection Example</a> |
+ </p> |
+ <p> |
+ The DOM does not standardize collections to be callable. There isn't a good reason to call |
+ a collection. The property access operators provide a standard, cross-browser alternative. |
+ Callable collections are not implented in Mozilla. This feature does not appear to be considered for |
+ inclusion in HTML 5 or Web IDL. |
+ </p> |
+ |
+ <h3>Map-like NodeList Collections</h3> |
+ <p> |
+ Many browsers implement Map-like quality on <code>NodeList</code>. |
+ In these browsers, elements are accessible off the <code>NodeList</code> by their ID. |
+ </p> |
+ <p> |
+ <a href="map-like-nodelist.html">Map-like NodeList Example</a> |
+ </p> |
+ <p> |
+ This behavior is nonstandard and may be present, but should not be used. |
+ It is one innovation of Internet Explorer, |
+ copied in Safari, Opera, and perhaps elsewhere. |
+ </p> |
+ |
+ <p> |
+ Implementation developers and specifications authors must be aware of the permanence of |
+ API Design. We should all be cognizant of the impact that an API has on the future. |
+ </p> |
+ <div id="toc"> |
+ <h4>Table of Contents</h4> |
+ <ul class="pagination linkList"> |
+ <li><a href="./index.html">Introduction</a></li> |
+ <li><a href="extra_props.html">Extra Properties: <code>FORM</code> Elements</a></li> |
+ <li><a href="extra_props_document.html">Extra Properties: <code>document</code></a></li> |
+ <li><a href="extra_props_global.html">Extra Properties: <code>global</code></a></li> |
+ <li><a href="event_handler.html">Event Handler Scope</a></li> |
+ <li>API Design?</li> |
+ <li><a href="unsafe_names.html">Unsafe Names</a></li> |
+ <li><a href="conclusion.html">Conclusion</a></li> |
+ </ul> |
+ </div> |
+ <ul id="nextLink" class="linkList"> |
+ <li> |
+ <span class="prev">Previous:</span> <a href="event_handler.html">Event Handler Scope</a> |
+ </li> |
+ <li> |
+ <span class="next">Next:</span> <a href="unsafe_names.html">Unsafe Names</a> |
+ </li> |
+ </ul> |
+ <script type="text/javascript"> |
+ function toggleDisplay(id, d1, d2) { |
+ var s = document.getElementById(id).style; |
+ s.display = s.display === d2 ? d1 : d2; |
+ } |
+ </script> |
+</body> |
+</html> |
/cljs/names/api_design.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/names/unsafe_names.html |
=================================================================== |
--- cljs/names/unsafe_names.html (nonexistent) |
+++ cljs/names/unsafe_names.html (revision 2) |
@@ -0,0 +1,997 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
+<html lang="en"> |
+<head> |
+ <meta http-equiv="content-type" content="text/html; charset=iso-8859-1"> |
+ <title>Unsafe Names for HTML Form Controls - Unsafe Names</title> |
+ <meta name="author" content="Garrett Smith"> |
+ <link rel="Start" href="./"> |
+ <link rel="stylesheet" href="../faq.css" type="text/css" media="all" charset="iso-8859-1"> |
+ <link rel="stylesheet" href="names.css" type="text/css" media="all" charset="iso-8859-1"> |
+</head> |
+<body> |
+ |
+ <h1>Unsafe Names for HTML Form Controls</h1> |
+ <h2>Unsafe Names</h2> |
+ <p> |
+ There are roughly three-hundred (300) names which a form control |
+ must not have. |
+ </p> |
+ |
+ <p> |
+ Unsafely named elements can be added to a <code>FORM</code> object after |
+ the form has been created, or can be included in the HTML source |
+ code. |
+ </p> |
+ |
+<h3> |
+Examples of Unsafe Form Control Names |
+</h3> |
+ <p> |
+ Unsafe <code>FORM</code> |
+ control names can appear in three ways: |
+ </p> |
+ <ol> |
+ <li>In the <a href="form_override_html_source.html">HTML Source</a></li> |
+ <li><a href="form_override_dom.html">Added via the DOM</a></li> |
+ <li>From <a href="form_override_change_name.html">changing the <code>name</code> property</a></li> |
+ </ol> |
+ |
+ <p> |
+ Not all browsers behave the same when using unsafe |
+ <code>FORM</code> control names and a changing DOM. |
+ </p> |
+ |
+ <h3>Solution: Namespaced Form Controls</h3> |
+ <p> |
+ A naming system can help avoid unsafe names. |
+ </p> |
+ <p> |
+ Name the form controls starting with a special prefix. The prefix should be |
+ unique and represent the application. |
+ </p> |
+ |
+ <p> |
+ For example, an application named "VortexMail" could use the prefix <code>vtxmail_</code>. |
+ </p> |
+ |
+ <pre> |
+<input name="vtxmail_fname" type="text"> |
+<input name="vtxmail_data" type="file"> |
+<input name="vtxmail_submit" type="submit"> |
+</pre> |
+ <p> |
+ A prefix can also act as an identifying characteristic of your program or company, |
+ like a namespace. |
+ </p> |
+ |
+ <h4>Unsafe Names - Partial List</h4> |
+ <p> |
+ This list contains all the names that a form control should never have. It assumes |
+ that event handler attributes are never used and excludes some |
+ proposed properties from HTML 5 |
+ [<a href="conclusion.html#controls-normref">References</a>]. (e.g. |
+ <code>autofocus</code>, <code>min</code>, <code>max</code>, |
+ <code>height</code>, <code>labels</code>, <code>required</code>, <code>valid</code>, etc.). |
+ </p> |
+ |
+ <p> |
+ If event handler attributes are used, the list of unsafe names also includes |
+ every possible property name that exists on <code>document</code>, <code>window</code>, |
+ and the object of the tag that the event handler is declared on (could be any tag). |
+ This would bring the list to well over five-hundred (500) unsafe names, including |
+ <code>atob</code>, <code>bgColor</code>, <code>clear</code>, <code>close</code>, <code>opener</code>, |
+ <code>status</code>, <code>write</code>, etc. |
+ </p> |
+ |
+ <ol style="-moz-column-count: 2; |
+ -webkit-column-count: 2; |
+ column-count: 2; |
+ -moz-column-gap: 20px; |
+ -webkit-column-gap: 20px; |
+ column-gap: 20px; |
+ list-style-position:inside;"> |
+ <li> |
+ ATTRIBUTE_NODE |
+ </li> |
+ <li> |
+ CDATA_SECTION_NODE |
+ </li> |
+ <li> |
+ COMMENT_NODE |
+ </li> |
+ <li> |
+ DOCUMENT_FRAGMENT_NODE |
+ </li> |
+ <li> |
+ DOCUMENT_NODE |
+ </li> |
+ <li> |
+ DOCUMENT_POSITION_CONTAINED_BY |
+ </li> |
+ <li> |
+ DOCUMENT_POSITION_CONTAINS |
+ </li> |
+ <li> |
+ DOCUMENT_POSITION_DISCONNECTED |
+ </li> |
+ <li> |
+ DOCUMENT_POSITION_FOLLOWING |
+ </li> |
+ <li> |
+ DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC |
+ </li> |
+ <li> |
+ DOCUMENT_POSITION_PRECEDING |
+ </li> |
+ <li> |
+ DOCUMENT_TYPE_NODE |
+ </li> |
+ <li> |
+ ELEMENT_NODE |
+ </li> |
+ <li> |
+ ENTITY_NODE |
+ </li> |
+ <li> |
+ ENTITY_REFERENCE_NODE |
+ </li> |
+ <li> |
+ NOTATION_NODE |
+ </li> |
+ <li> |
+ PROCESSING_INSTRUCTION_NODE |
+ </li> |
+ <li> |
+ TEXT_NODE |
+ </li> |
+ <li> |
+ accept |
+ </li> |
+ <li> |
+ acceptCharset |
+ </li> |
+ <li> |
+ action |
+ </li> |
+ <li> |
+ addBehavior |
+ </li> |
+ <li> |
+ addEventListener |
+ </li> |
+ <li> |
+ addEventSource |
+ </li> |
+ <li> |
+ addRepetitionBlock |
+ </li> |
+ <li> |
+ addRepetitionBlockByIndex |
+ </li> |
+ <li> |
+ all |
+ </li> |
+ <li> |
+ appendChild |
+ </li> |
+ <li> |
+ applyElement |
+ </li> |
+ <li> |
+ ariaBusy |
+ </li> |
+ <li> |
+ ariaChecked |
+ </li> |
+ <li> |
+ ariaControls |
+ </li> |
+ <li> |
+ ariaDescribability |
+ </li> |
+ <li> |
+ ariaDisabled |
+ </li> |
+ <li> |
+ ariaExpanded |
+ </li> |
+ <li> |
+ ariaFlowto |
+ </li> |
+ <li> |
+ ariaHaspopup |
+ </li> |
+ <li> |
+ ariaHidden |
+ </li> |
+ <li> |
+ ariaInvalid |
+ </li> |
+ <li> |
+ ariaLabelledby |
+ </li> |
+ <li> |
+ ariaLevel |
+ </li> |
+ <li> |
+ ariaMultiselect |
+ </li> |
+ <li> |
+ ariaOwns |
+ </li> |
+ <li> |
+ ariaPosinset |
+ </li> |
+ <li> |
+ ariaPressed |
+ </li> |
+ <li> |
+ ariaReadonly |
+ </li> |
+ <li> |
+ ariaRequired |
+ </li> |
+ <li> |
+ ariaSecret |
+ </li> |
+ <li> |
+ ariaSelected |
+ </li> |
+ <li> |
+ ariaSetsize |
+ </li> |
+ <li> |
+ ariaValuemax |
+ </li> |
+ <li> |
+ ariaValuemin |
+ </li> |
+ <li> |
+ ariaValuenow |
+ </li> |
+ <li> |
+ attachEvent |
+ </li> |
+ <li> |
+ attributes |
+ </li> |
+ <li> |
+ autocomplete |
+ </li> |
+ <li> |
+ baseURI |
+ </li> |
+ <li> |
+ behaviorUrns |
+ </li> |
+ <li> |
+ blockDiraction |
+ </li> |
+ <li> |
+ blur |
+ </li> |
+ <li> |
+ canHaveChildren |
+ </li> |
+ <li> |
+ canHaveHTML |
+ </li> |
+ <li> |
+ checkValidity |
+ </li> |
+ <li> |
+ childElementCount |
+ </li> |
+ <li> |
+ childNodes |
+ </li> |
+ <li> |
+ children |
+ </li> |
+ <li> |
+ className |
+ </li> |
+ <li> |
+ clearAttributes |
+ </li> |
+ <li> |
+ click |
+ </li> |
+ <li> |
+ clientHeight |
+ </li> |
+ <li> |
+ clientLeft |
+ </li> |
+ <li> |
+ clientTop |
+ </li> |
+ <li> |
+ clientWidth |
+ </li> |
+ <li> |
+ cloneNode |
+ </li> |
+ <li> |
+ compareDocumentPosition |
+ </li> |
+ <li> |
+ componentFromPoint |
+ </li> |
+ <li> |
+ constructor |
+ </li> |
+ <li> |
+ contains |
+ </li> |
+ <li> |
+ contentEditable |
+ </li> |
+ <li> |
+ currentStyle |
+ </li> |
+ <li> |
+ data |
+ </li> |
+ <li> |
+ detachEvent |
+ </li> |
+ <li> |
+ dir |
+ </li> |
+ <li> |
+ dispatchEvent |
+ </li> |
+ <li> |
+ dispatchFormChange |
+ </li> |
+ <li> |
+ dispatchFormInput |
+ </li> |
+ <li> |
+ document |
+ </li> |
+ <li> |
+ dragDrop |
+ </li> |
+ <li> |
+ elements |
+ </li> |
+ <li> |
+ encoding |
+ </li> |
+ <li> |
+ enctype |
+ </li> |
+ <li> |
+ fireEvent |
+ </li> |
+ <li> |
+ firstChild |
+ </li> |
+ <li> |
+ firstElementChild |
+ </li> |
+ <li> |
+ focus |
+ </li> |
+ <li> |
+ getAdjacentText |
+ </li> |
+ <li> |
+ getAttribute |
+ </li> |
+ <li> |
+ getAttributeNS |
+ </li> |
+ <li> |
+ getAttributeNode |
+ </li> |
+ <li> |
+ getAttributeNodeNS |
+ </li> |
+ <li> |
+ getBoundingClientRect |
+ </li> |
+ <li> |
+ getClientRects |
+ </li> |
+ <li> |
+ getElementsByClassName |
+ </li> |
+ <li> |
+ getElementsByTagName |
+ </li> |
+ <li> |
+ getElementsByTagNameNS |
+ </li> |
+ <li> |
+ getExpression |
+ </li> |
+ <li> |
+ getFeature |
+ </li> |
+ <li> |
+ getUserData |
+ </li> |
+ <li> |
+ hasAttribute |
+ </li> |
+ <li> |
+ hasAttributeNS |
+ </li> |
+ <li> |
+ hasAttributes |
+ </li> |
+ <li> |
+ hasChildNodes |
+ </li> |
+ <li> |
+ hasOwnProperty |
+ </li> |
+ <li> |
+ hideFocus |
+ </li> |
+ <li> |
+ id |
+ </li> |
+ <li> |
+ innerHTML |
+ </li> |
+ <li> |
+ innerText |
+ </li> |
+ <li> |
+ insertAdjacentElement |
+ </li> |
+ <li> |
+ insertAdjacentHTML |
+ </li> |
+ <li> |
+ insertAdjacentText |
+ </li> |
+ <li> |
+ insertBefore |
+ </li> |
+ <li> |
+ isContentEditable |
+ </li> |
+ <li> |
+ isDefaultNamespace |
+ </li> |
+ <li> |
+ isDefaultNamespaceURI |
+ </li> |
+ <li> |
+ isDisabled |
+ </li> |
+ <li> |
+ isEqualNode |
+ </li> |
+ <li> |
+ isMultiLine |
+ </li> |
+ <li> |
+ isPrototypeOf |
+ </li> |
+ <li> |
+ isSameNode |
+ </li> |
+ <li> |
+ isSupported |
+ </li> |
+ <li> |
+ isTextEdit |
+ </li> |
+ <li> |
+ item |
+ </li> |
+ <li> |
+ lang |
+ </li> |
+ <li> |
+ language |
+ </li> |
+ <li> |
+ lastChild |
+ </li> |
+ <li> |
+ lastElementChild |
+ </li> |
+ <li> |
+ length |
+ </li> |
+ <li> |
+ localName |
+ </li> |
+ <li> |
+ lookupPrefix |
+ </li> |
+ <li> |
+ mergeAttributes |
+ </li> |
+ <li> |
+ method |
+ </li> |
+ <li> |
+ moveRepetitionBlock |
+ </li> |
+ <li> |
+ msBlockProgression |
+ </li> |
+ <li> |
+ msBoxSizing |
+ </li> |
+ <li> |
+ name |
+ </li> |
+ <li> |
+ namedItem |
+ </li> |
+ <li> |
+ namespaceURI |
+ </li> |
+ <li> |
+ nextSibling |
+ </li> |
+ <li> |
+ nodeName |
+ </li> |
+ <li> |
+ nodeType |
+ </li> |
+ <li> |
+ nodeValue |
+ </li> |
+ <li> |
+ normalize |
+ </li> |
+ <li> |
+ offsetHeight |
+ </li> |
+ <li> |
+ offsetWidth |
+ </li> |
+ <li> |
+ onOffBehavior |
+ </li> |
+ <li> |
+ onabort |
+ </li> |
+ <li> |
+ onactivate |
+ </li> |
+ <li> |
+ onbeforeactivate |
+ </li> |
+ <li> |
+ onbeforecopy |
+ </li> |
+ <li> |
+ onbeforecut |
+ </li> |
+ <li> |
+ onbeforedeactivate |
+ </li> |
+ <li> |
+ onbeforeeditfocus |
+ </li> |
+ <li> |
+ onbeforepaste |
+ </li> |
+ <li> |
+ onblur |
+ </li> |
+ <li> |
+ onchage |
+ </li> |
+ <li> |
+ onclick |
+ </li> |
+ <li> |
+ onclosecapture |
+ </li> |
+ <li> |
+ oncontextmenu |
+ </li> |
+ <li> |
+ oncopy |
+ </li> |
+ <li> |
+ oncut |
+ </li> |
+ <li> |
+ ondblclick |
+ </li> |
+ <li> |
+ ondeactivate |
+ </li> |
+ <li> |
+ ondrag |
+ </li> |
+ <li> |
+ ondragend |
+ </li> |
+ <li> |
+ ondragenter |
+ </li> |
+ <li> |
+ ondragleave |
+ </li> |
+ <li> |
+ ondragover |
+ </li> |
+ <li> |
+ onerror |
+ </li> |
+ <li> |
+ onfocus |
+ </li> |
+ <li> |
+ onfocusin |
+ </li> |
+ <li> |
+ onfocusout |
+ </li> |
+ <li> |
+ onhelp |
+ </li> |
+ <li> |
+ oninput |
+ </li> |
+ <li> |
+ onkeydown |
+ </li> |
+ <li> |
+ onkeypress |
+ </li> |
+ <li> |
+ onkeyup |
+ </li> |
+ <li> |
+ onmousedown |
+ </li> |
+ <li> |
+ onmouseenter |
+ </li> |
+ <li> |
+ onmouseleave |
+ </li> |
+ <li> |
+ onmousemove |
+ </li> |
+ <li> |
+ onmousemultiwheel |
+ </li> |
+ <li> |
+ onmouseout |
+ </li> |
+ <li> |
+ onmouseover |
+ </li> |
+ <li> |
+ onmouseup |
+ </li> |
+ <li> |
+ onmousewheel |
+ </li> |
+ <li> |
+ onmove |
+ </li> |
+ <li> |
+ onmoveend |
+ </li> |
+ <li> |
+ onmovestart |
+ </li> |
+ <li> |
+ onpaste |
+ </li> |
+ <li> |
+ onpropertychange |
+ </li> |
+ <li> |
+ onreadystatechange |
+ </li> |
+ <li> |
+ onresize |
+ </li> |
+ <li> |
+ onresizeend |
+ </li> |
+ <li> |
+ onresizestart |
+ </li> |
+ <li> |
+ onscroll |
+ </li> |
+ <li> |
+ onsearch |
+ </li> |
+ <li> |
+ onselect |
+ </li> |
+ <li> |
+ onselectstart |
+ </li> |
+ <li> |
+ ontimeerror |
+ </li> |
+ <li> |
+ onunload |
+ </li> |
+ <li> |
+ outerHTML |
+ </li> |
+ <li> |
+ outerText |
+ </li> |
+ <li> |
+ ownerDocument |
+ </li> |
+ <li> |
+ parentNode |
+ </li> |
+ <li> |
+ parentTextEdit |
+ </li> |
+ <li> |
+ prefix |
+ </li> |
+ <li> |
+ previousElementSibling |
+ </li> |
+ <li> |
+ previousSibling |
+ </li> |
+ <li> |
+ propertyIsEnumerable |
+ </li> |
+ <li> |
+ querySelector |
+ </li> |
+ <li> |
+ querySelectorAll |
+ </li> |
+ <li> |
+ quotes |
+ </li> |
+ <li> |
+ releaseCapture |
+ </li> |
+ <li> |
+ removeAttribute |
+ </li> |
+ <li> |
+ removeAttributeNS |
+ </li> |
+ <li> |
+ removeAttributeNode |
+ </li> |
+ <li> |
+ removeBehavior |
+ </li> |
+ <li> |
+ removeChild |
+ </li> |
+ <li> |
+ removeEventListener |
+ </li> |
+ <li> |
+ removeEventSource |
+ </li> |
+ <li> |
+ removeExpression |
+ </li> |
+ <li> |
+ removeNode |
+ </li> |
+ <li> |
+ removeRepetitionBlock |
+ </li> |
+ <li> |
+ repeatMax |
+ </li> |
+ <li> |
+ repeatMin |
+ </li> |
+ <li> |
+ repeatStart |
+ </li> |
+ <li> |
+ repetitionBlocks |
+ </li> |
+ <li> |
+ repetitionIndex |
+ </li> |
+ <li> |
+ repetitionTemplate |
+ </li> |
+ <li> |
+ repetitionType |
+ </li> |
+ <li> |
+ replace |
+ </li> |
+ <li> |
+ replaceAdjacentText |
+ </li> |
+ <li> |
+ replaceChild |
+ </li> |
+ <li> |
+ replaceNode |
+ </li> |
+ <li> |
+ reset |
+ </li> |
+ <li> |
+ resetFromData |
+ </li> |
+ <li> |
+ role |
+ </li> |
+ <li> |
+ runtimeStyle |
+ </li> |
+ <li> |
+ schemaTypeInfo |
+ </li> |
+ <li> |
+ scopeName |
+ </li> |
+ <li> |
+ scrollByLines |
+ </li> |
+ <li> |
+ scrollByPages |
+ </li> |
+ <li> |
+ scrollHeight |
+ </li> |
+ <li> |
+ scrollIntoView |
+ </li> |
+ <li> |
+ scrollLeft |
+ </li> |
+ <li> |
+ scrollTop |
+ </li> |
+ <li> |
+ scrollWidth |
+ </li> |
+ <li> |
+ selectNodes |
+ </li> |
+ <li> |
+ selectSingleNode |
+ </li> |
+ <li> |
+ setActive |
+ </li> |
+ <li> |
+ setAttributeNS |
+ </li> |
+ <li> |
+ setAttributeNode |
+ </li> |
+ <li> |
+ setAttributeNodeNS |
+ </li> |
+ <li> |
+ setCapture |
+ </li> |
+ <li> |
+ setExpression |
+ </li> |
+ <li> |
+ setIdAttribute |
+ </li> |
+ <li> |
+ setIdAttributeNS |
+ </li> |
+ <li> |
+ setIdAttributeNode |
+ </li> |
+ <li> |
+ setUserData |
+ </li> |
+ <li> |
+ sourceIndex |
+ </li> |
+ <li> |
+ spellcheck |
+ </li> |
+ <li> |
+ style |
+ </li> |
+ <li> |
+ submit |
+ </li> |
+ <li> |
+ swapNode |
+ </li> |
+ <li> |
+ tabIndex |
+ </li> |
+ <li> |
+ tagName |
+ </li> |
+ <li> |
+ tagUrn |
+ </li> |
+ <li> |
+ target |
+ </li> |
+ <li> |
+ templateElements |
+ </li> |
+ <li> |
+ text |
+ </li> |
+ <li> |
+ textContent |
+ </li> |
+ <li> |
+ title |
+ </li> |
+ <li> |
+ toLocaleString |
+ </li> |
+ <li> |
+ toString |
+ </li> |
+ <li> |
+ uniqueID |
+ </li> |
+ <li> |
+ unselectable |
+ </li> |
+ <li> |
+ unwatch |
+ </li> |
+ <li> |
+ urns |
+ </li> |
+ <li> |
+ valueOf |
+ </li> |
+ <li> |
+ watch |
+ </li> |
+ <li> |
+ window |
+ </li> |
+ </ol> |
+ |
+ <h4 style="clear:both">Early Adopter</h4> |
+ <p> |
+ Safari 3 has implemented the behavior specified in more closely than |
+ Safari 2. Safari 3 replaces more pre-existing properties of a |
+ <code>FORM</code> when an element with the same name is added. |
+ </p> |
+ |
+ <div id="toc"> |
+ <h4>Table of Contents</h4> |
+ <ul class="pagination linkList"> |
+ <li><a href="./index.html">Introduction</a></li> |
+ <li><a href="extra_props.html">Extra Properties: <code>FORM</code> Elements</a></li> |
+ <li><a href="extra_props_document.html">Extra Properties: <code>document</code></a></li> |
+ <li><a href="extra_props_global.html">Extra Properties: <code>global</code></a></li> |
+ <li><a href="event_handler.html">Event Handler Scope</a></li> |
+ <li><a href="api_design.html">API Design?</a></li> |
+ <li>Unsafe Names</li> |
+ <li><a href="conclusion.html">Conclusion</a></li> |
+ </ul> |
+ </div> |
+ <ul id="nextLink" class="linkList"> |
+ <li> |
+ <span class="prev">Previous:</span> <a href="api_design.html">API Design?</a> |
+ </li> |
+ <li> |
+ <span class="next">Next:</span> <a href="conclusion.html">Conclusion</a> |
+ </li> |
+ </ul> |
+</body> |
+</html> |
/cljs/names/unsafe_names.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/names/extra_props_document.html |
=================================================================== |
--- cljs/names/extra_props_document.html (nonexistent) |
+++ cljs/names/extra_props_document.html (revision 2) |
@@ -0,0 +1,86 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
+<html lang="en"> |
+<head> |
+ <title>Unsafe Names for HTML Form Controls - Extra Properties: Document</title> |
+ <meta http-equiv="content-type" content="text/html; charset=iso-8859-1"> |
+ <meta name="author" content="Garrett Smith"> |
+ <link rel="Start" href="./"> |
+ <link rel="stylesheet" href="../faq.css" type="text/css" media="all" charset="iso-8859-1"> |
+ <link rel="stylesheet" href="names.css" type="text/css" media="all" charset="iso-8859-1"> |
+</head> |
+<body> |
+ |
+ <h1>Unsafe Names for HTML Form Controls</h1> |
+ <h2>Extra Properties: <code>document</code></h2> |
+ |
+ <h3>Non-Standard Named Properties</h3> |
+ <p> |
+ A browser may add a property to the <code>document</code> for each named |
+ (or <code>id</code>'d) FORM element, IMG, or possibly any other element. |
+ Alternatively, the same |
+ browser may implement a specialized <code>[[Get]]</code> method to find the property. |
+ </p> |
+ |
+ <form action="" id="testFormID" name="testFormName"> |
+ <pre> |
+<form action="" id="testFormID" name="testFormName"> |
+</form> |
+</pre> |
+ <button class="evaluator" onclick="this.nextSibling.firstChild.data = eval(this.firstChild.data);return false" |
+ >'testFormID' in document</button |
+ ><span> </span> |
+ <button class="evaluator" onclick="this.nextSibling.firstChild.data = eval(this.firstChild.data);return false" |
+ >'testFormName' in document</button |
+ ><span> </span> |
+ <img name="testImgNAME" src="" alt="404" style="z-index: -1;position:relative;"> |
+<pre> |
+<img name="testImgNAME" src=""> |
+</pre> |
+ |
+ <button class="evaluator" onclick="this.nextSibling.firstChild.data = eval(this.firstChild.data);return false" |
+ >'testImgNAME' in document</button |
+ ><span> </span> |
+ |
+ <a name='testLinkNAME' style="z-index: -1;position:relative;">link</a> |
+<pre> |
+<a name='testLinkNAME'>link</a> |
+</pre> |
+ <button class="evaluator" onclick="this.nextSibling.firstChild.data = eval(this.firstChild.data);return false" |
+ >'testLinkNAME' in document</button |
+ ><span> </span> |
+ </form> |
+ |
+ <h3>Non Standard</h3> |
+ |
+ <p> |
+ Accessing objects from the <code>document</code> collection is not standard and unsafe. |
+ </p> |
+ |
+ <p> |
+ The extra properties added to <code>document</code> |
+ can cause problems with Event Handler Content Attributes as we will see later on. |
+ </p> |
+ |
+ <div id="toc"> |
+ <h4>Table of Contents</h4> |
+ <ul class="pagination linkList"> |
+ <li><a href="./index.html">Introduction</a></li> |
+ <li><a href="extra_props.html">Extra Properties: <code>FORM</code> Elements</a></li> |
+ <li>Extra Properties: <code>document</code></li> |
+ <li><a href="extra_props_global.html">Extra Properties: <code>global</code></a></li> |
+ <li><a href="event_handler.html">Event Handler Scope</a></li> |
+ <li><a href="api_design.html">API Design?</a></li> |
+ <li><a href="unsafe_names.html">Unsafe Names</a></li> |
+ <li><a href="conclusion.html">Conclusion</a></li> |
+ </ul> |
+ </div> |
+ <ul id="nextLink" class="linkList"> |
+ <li> |
+ <span class="prev">Previous:</span> <a href="extra_props.html">Extra Properties: <code>FORM</code> Elements</a> |
+ </li> |
+ <li> |
+ <span class="next">Next:</span> <a href="extra_props_global.html">Extra Properties: <code>global</code></a> |
+ </li> |
+ </ul> |
+</body> |
+</html> |
/cljs/names/extra_props_document.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/names/extra_props.html |
=================================================================== |
--- cljs/names/extra_props.html (nonexistent) |
+++ cljs/names/extra_props.html (revision 2) |
@@ -0,0 +1,182 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
+<html lang="en"> |
+<head> |
+ <title>Unsafe Names for HTML Form Controls - Extra Properties: Form Elements</title> |
+ <meta http-equiv="content-type" content="text/html; charset=iso-8859-1"> |
+ <meta name="author" content="Garrett Smith"> |
+ <link rel="Start" href="./"> |
+ <link rel="stylesheet" href="../faq.css" type="text/css" media="all" charset="iso-8859-1"> |
+ <link rel="stylesheet" href="names.css" type="text/css" media="all" charset="iso-8859-1"> |
+</head> |
+<body> |
+ |
+ <h1>Unsafe Names for HTML Form Controls</h1> |
+ <h2>Extra Properties: <code>FORM</code> Elements</h2> |
+ |
+ <h3>Named Properties</h3> |
+ <p> |
+ A browser may add a property to the either the <code>FORM</code> or |
+ <code>elements</code> collection for each named (or <code>id</code>'d) element. |
+ Alternatively, the same |
+ browser may implement a specialized <code>[[Get]]</code> method to find the property. |
+ </p> |
+ <p>The way to tell if an object has a property is to use the <code>in</code> operator.</p> |
+ |
+ <form action=""> |
+ <button name='test' onclick="this.nextSibling.firstChild.data = eval(this.firstChild.data);return false" |
+ >'test' in this.form</button |
+ ><span> </span> |
+ <button name='test' onclick="this.nextSibling.firstChild.data = eval(this.firstChild.data);return false" |
+ >'test' in this.form.elements</button |
+ ><span> </span> |
+ </form> |
+ |
+ <p> |
+ Behavior varies between browsers, |
+ and between <code>FORM</code> and <code>elements</code>. When named properties |
+ exist, they usually appear to have the attributes <code>ReadOnly</code>, <code>DontDelete</code>. |
+ </p> |
+ |
+ <h3>Indexed Properties</h3> |
+ <p> |
+ Browsers also either add indexed properties to the collection or form or implement |
+ a specialized <code>[[Get]]</code> method to find the property. As with named properties, most browsers |
+ will actually add the property to the collection. |
+ </p> |
+ |
+ <form action=""> |
+ <button name='test' onclick="this.nextSibling.firstChild.data = eval(this.firstChild.data);return false" |
+ >'0' in this.form</button |
+ ><span> </span> |
+ <button name='test' onclick="this.nextSibling.firstChild.data = eval(this.firstChild.data);return false" |
+ >'0' in this.form.elements</button |
+ ><span> </span> |
+ </form> |
+ |
+ <p> |
+ Mozilla seems to be the only browser that implements a specialized [[Get]]. |
+ </p> |
+ |
+ <h3 id="StandardWrong">Standard</h3> |
+ <p> |
+ The <code>elements</code> collection is an <code>HTMLCollection</code> that provides a |
+ standard way to access form controls. |
+ </p> |
+ |
+ <p> |
+ Web IDL [<a href="conclusion.html#controls-normref">WebIDL</a>] lumps these behaviors into |
+ the terms: <code>[[NameGetter]]</code> and <code>[[IndexGetter]]</code>. |
+ Not all browsers have a specialized <code>[[Get]]</code> to retrieve named elements; |
+ the ones that do (Mozilla) don't always use it for every collection, so the term is a bit |
+ of a misnomer. |
+ </p> |
+ <p> |
+ We can see the influence Java programmers had in the DOM 2 ECMAScript bindings |
+ [<a href="conclusion.html#controls-normref">DOM2</a>], |
+ which falsely states: |
+ </p> |
+ |
+ <blockquote cite="http://www.w3.org/TR/DOM-Level-2-HTML/ECMA-script-binding.html"> |
+ <strong>Objects that implement the <code>HTMLCollection</code> interface:</strong> |
+ ... |
+ <p> |
+ <strong>Note:</strong> This object can also be dereferenced using square |
+ bracket notation (e.g. <code>obj[1]</code>). Dereferencing with an integer |
+ <strong>index</strong> is equivalent to invoking the <strong><code>item</code></strong> function |
+ with that index. |
+ </p> |
+ ... |
+ <p> |
+ <strong>Note:</strong> This object can also be dereferenced using square |
+ bracket notation (e.g. <code>obj["foo"]</code>). Dereferencing using a string |
+ index is equivalent to invoking the <strong><code>namedItem</code></strong> function with |
+ that index. |
+ </p> |
+ </blockquote> |
+ |
+ <h3>Property Access Operators</h3> |
+ <p> |
+ Contrary to what the [<a href="conclusion.html#controls-normref">DOM 1</a>] |
+ specification states, the <code>[ ]</code> property access operator does not perform |
+ a typecheck. In ECMAScript, property access |
+ is performed with <code>obj[ <var>Expression</var> ]</code> or |
+ <code>obj . <var>Identifier</var></code>. |
+ </p> |
+ |
+ <h4>Property Access on a Form</h4> |
+ <p> |
+ When the named or indexed property is added to the form, |
+ there is no call to <code>item</code> or <code>namedItem</code>. The specification |
+ is wrong. |
+ </p> |
+ |
+ <p> |
+ When the property access operator is used, the <code><var>Expression</var></code> is |
+ converted to a string with the internal <code>ToString</code>. |
+ The internal <code>ToString</code> method calls the object's <code>toString</code> |
+ property if it is an object or, if <code>toString</code> is not an object, the <code>valueOf</code> |
+ property is to be called (though results vary). |
+ </p> |
+ |
+ <h4>Property Access on a Form Example</h4> |
+ <p> |
+ The following example |
+ shows that with <code>form[ <var>Expression</var> ]</code>, |
+ the <code><var>Expression</var></code>, an <code>ObjectLiteral</code>, |
+ results in an Object. This object's <code>toString</code> method |
+ is called by the internal [[ToString]]. |
+ </p> |
+ |
+ <form action=""> |
+ <button name='test' onclick="this.nextSibling.data += eval(this.firstChild.data);return false" |
+ >this.form["0"] === this.form[ { toString : function(){ return 0; } } ]</button |
+ > |
+ </form> |
+ |
+ <p> |
+ The property access operator results in a call to the object's <code>toString</code> |
+ property and the resulting primitive value is converted to the string value <samp>"0"</samp>. |
+ </p> |
+ |
+ <p> |
+ Had the authors of the DOM specification ECMAScript bindings written some tests, |
+ they could have learned how this basic feature of property access works in ECMAScript. |
+ </p> |
+ |
+ <p> |
+ Accessing form controls from the <code>elements</code> collection reduces ambiguity |
+ in the code. Control names that may conflict with the collection's properties are limited to: |
+ <code>length</code>, <code>item</code>, <code>namedItem</code>, <code>tags</code>. |
+ The names <code>document</code>, and <code>window</code> are still unsafe. |
+ </p> |
+ |
+ <p> |
+ Accessing form controls from the <code>elements</code> collection is safe. There |
+ are fewer conflicting names and, unlike form-as-a-collection, <code>elements</code> |
+ is a live representation. |
+ </p> |
+ |
+ |
+ <div id="toc"> |
+ <h4>Table of Contents</h4> |
+ <ul class="pagination linkList"> |
+ <li><a href="./index.html">Introduction</a></li> |
+ <li>Extra Properties: <code>FORM</code> Elements</li> |
+ <li><a href="extra_props_document.html">Extra Properties: <code>document</code></a></li> |
+ <li><a href="extra_props_global.html">Extra Properties: <code>global</code></a></li> |
+ <li><a href="event_handler.html">Event Handler Scope</a></li> |
+ <li><a href="api_design.html">API Design?</a></li> |
+ <li><a href="unsafe_names.html">Unsafe Names</a></li> |
+ <li><a href="conclusion.html">Conclusion</a></li> |
+ </ul> |
+ </div> |
+ <ul id="nextLink" class="linkList"> |
+ <li> |
+ <span class="prev">Previous:</span> <a href="index.html">Introduction</a> |
+ </li> |
+ <li> |
+ <span class="next">Next:</span> <a href="extra_props_document.html">Extra Properties: <code>document</code></a> |
+ </li> |
+ </ul> |
+</body> |
+</html> |
/cljs/names/extra_props.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/names/form_override_html_source.html |
=================================================================== |
--- cljs/names/form_override_html_source.html (nonexistent) |
+++ cljs/names/form_override_html_source.html (revision 2) |
@@ -0,0 +1,65 @@ |
+<!DOCTYPE HTML> |
+<html lang="en"> |
+<head> |
+ <title>FormElementCollection.html</title> |
+ <style type="text/css"> |
+ #pass { display: none; background : #0f0; } |
+ #fail { display: none; background : #F33; } |
+ </style> |
+</head> |
+<body> |
+<h1>Test: 290 Names not to give a FORM Control</h1> |
+<form action=""> |
+<input name="window" id="window" type="text"><input name="watch" id="watch" type="text"><input name="valueOf" id="valueOf" type="text"><input name="urns" id="urns" type="text"><input name="unwatch" id="unwatch" type="text"><input name="unselectable" id="unselectable" type="text"><input name="uniqueID" id="uniqueID" type="text"><input name="toString" id="toString" type="text"><input name="toLocaleString" id="toLocaleString" type="text"><input name="title" id="title" type="text"><input name="textContent" id="textContent" type="text"><input name="text" id="text" type="text"><input name="templateElements" id="templateElements" type="text"><input name="target" id="target" type="text"><input name="tagUrn" id="tagUrn" type="text"><input name="tagName" id="tagName" type="text"><input name="tabIndex" id="tabIndex" type="text"><input name="swapNode" id="swapNode" type="text"><input name="submit" id="submit" type="text"><input name="style" id="style" type="text"><input name="spellcheck" id="spellcheck" type="text"><input name="sourceIndex" id="sourceIndex" type="text"><input name="setUserData" id="setUserData" type="text"><input name="setIdAttributeNode" id="setIdAttributeNode" type="text"><input name="setIdAttributeNS" id="setIdAttributeNS" type="text"><input name="setIdAttribute" id="setIdAttribute" type="text"><input name="setExpression" id="setExpression" type="text"><input name="setCapture" id="setCapture" type="text"><input name="setAttributeNodeNS" id="setAttributeNodeNS" type="text"><input name="setAttributeNode" id="setAttributeNode" type="text"><input name="setAttributeNS" id="setAttributeNS" type="text"><input name="setActive" id="setActive" type="text"><input name="selectSingleNode" id="selectSingleNode" type="text"><input name="selectNodes" id="selectNodes" type="text"><input name="scrollWidth" id="scrollWidth" type="text"><input name="scrollTop" id="scrollTop" type="text"><input name="scrollLeft" id="scrollLeft" type="text"><input name="scrollIntoView" id="scrollIntoView" type="text"><input name="scrollHeight" id="scrollHeight" type="text"><input name="scrollByPages" id="scrollByPages" type="text"><input name="scrollByLines" id="scrollByLines" type="text"><input name="scopeName" id="scopeName" type="text"><input name="schemaTypeInfo" id="schemaTypeInfo" type="text"><input name="runtimeStyle" id="runtimeStyle" type="text"><input name="role" id="role" type="text"><input name="resetFromData" id="resetFromData" type="text"><input name="reset" id="reset" type="text"><input name="replaceNode" id="replaceNode" type="text"><input name="replaceChild" id="replaceChild" type="text"><input name="replaceAdjacentText" id="replaceAdjacentText" type="text"><input name="replace" id="replace" type="text"><input name="repetitionType" id="repetitionType" type="text"><input name="repetitionTemplate" id="repetitionTemplate" type="text"><input name="repetitionIndex" id="repetitionIndex" type="text"><input name="repetitionBlocks" id="repetitionBlocks" type="text"><input name="repeatStart" id="repeatStart" type="text"><input name="repeatMin" id="repeatMin" type="text"><input name="repeatMax" id="repeatMax" type="text"><input name="removeRepetitionBlock" id="removeRepetitionBlock" type="text"><input name="removeNode" id="removeNode" type="text"><input name="removeExpression" id="removeExpression" type="text"><input name="removeEventSource" id="removeEventSource" type="text"><input name="removeEventListener" id="removeEventListener" type="text"><input name="removeChild" id="removeChild" type="text"><input name="removeBehavior" id="removeBehavior" type="text"><input name="removeAttributeNode" id="removeAttributeNode" type="text"><input name="removeAttributeNS" id="removeAttributeNS" type="text"><input name="removeAttribute" id="removeAttribute" type="text"><input name="releaseCapture" id="releaseCapture" type="text"><input name="quotes" id="quotes" type="text"><input name="querySelectorAll" id="querySelectorAll" type="text"><input name="querySelector" id="querySelector" type="text"><input name="propertyIsEnumerable" id="propertyIsEnumerable" type="text"><input name="previousSibling" id="previousSibling" type="text"><input name="previousElementSibling" id="previousElementSibling" type="text"><input name="prefix" id="prefix" type="text"><input name="parentTextEdit" id="parentTextEdit" type="text"><input name="parentNode" id="parentNode" type="text"><input name="ownerDocument" id="ownerDocument" type="text"><input name="outerText" id="outerText" type="text"><input name="outerHTML" id="outerHTML" type="text"><input name="onunload" id="onunload" type="text"><input name="ontimeerror" id="ontimeerror" type="text"><input name="onselectstart" id="onselectstart" type="text"><input name="onselect" id="onselect" type="text"><input name="onsearch" id="onsearch" type="text"><input name="onscroll" id="onscroll" type="text"><input name="onresizestart" id="onresizestart" type="text"><input name="onresizeend" id="onresizeend" type="text"><input name="onresize" id="onresize" type="text"><input name="onreadystatechange" id="onreadystatechange" type="text"><input name="onpropertychange" id="onpropertychange" type="text"><input name="onpaste" id="onpaste" type="text"><input name="onmovestart" id="onmovestart" type="text"><input name="onmoveend" id="onmoveend" type="text"><input name="onmove" id="onmove" type="text"><input name="onmousewheel" id="onmousewheel" type="text"><input name="onmouseup" id="onmouseup" type="text"><input name="onmouseover" id="onmouseover" type="text"><input name="onmouseout" id="onmouseout" type="text"><input name="onmousemultiwheel" id="onmousemultiwheel" type="text"><input name="onmousemove" id="onmousemove" type="text"><input name="onmouseleave" id="onmouseleave" type="text"><input name="onmouseenter" id="onmouseenter" type="text"><input name="onmousedown" id="onmousedown" type="text"><input name="onkeyup" id="onkeyup" type="text"><input name="onkeypress" id="onkeypress" type="text"><input name="onkeydown" id="onkeydown" type="text"><input name="oninput" id="oninput" type="text"><input name="onhelp" id="onhelp" type="text"><input name="onfocusout" id="onfocusout" type="text"><input name="onfocusin" id="onfocusin" type="text"><input name="onfocus" id="onfocus" type="text"><input name="onerror" id="onerror" type="text"><input name="ondragover" id="ondragover" type="text"><input name="ondragleave" id="ondragleave" type="text"><input name="ondragenter" id="ondragenter" type="text"><input name="ondragend" id="ondragend" type="text"><input name="ondrag" id="ondrag" type="text"><input name="ondeactivate" id="ondeactivate" type="text"><input name="ondblclick" id="ondblclick" type="text"><input name="oncut" id="oncut" type="text"><input name="oncopy" id="oncopy" type="text"><input name="oncontextmenu" id="oncontextmenu" type="text"><input name="onclosecapture" id="onclosecapture" type="text"><input name="onclick" id="onclick" type="text"><input name="onchage" id="onchage" type="text"><input name="onblur" id="onblur" type="text"><input name="onbeforepaste" id="onbeforepaste" type="text"><input name="onbeforeeditfocus" id="onbeforeeditfocus" type="text"><input name="onbeforedeactivate" id="onbeforedeactivate" type="text"><input name="onbeforecut" id="onbeforecut" type="text"><input name="onbeforecopy" id="onbeforecopy" type="text"><input name="onbeforeactivate" id="onbeforeactivate" type="text"><input name="onactivate" id="onactivate" type="text"><input name="onabort" id="onabort" type="text"><input name="onOffBehavior" id="onOffBehavior" type="text"><input name="offsetWidth" id="offsetWidth" type="text"><input name="offsetHeight" id="offsetHeight" type="text"><input name="normalize" id="normalize" type="text"><input name="nodeValue" id="nodeValue" type="text"><input name="nodeType" id="nodeType" type="text"><input name="nodeName" id="nodeName" type="text"><input name="nextSibling" id="nextSibling" type="text"><input name="namespaceURI" id="namespaceURI" type="text"><input name="namedItem" id="namedItem" type="text"><input name="name" id="name" type="text"><input name="msBoxSizing" id="msBoxSizing" type="text"><input name="msBlockProgression" id="msBlockProgression" type="text"><input name="moveRepetitionBlock" id="moveRepetitionBlock" type="text"><input name="method" id="method" type="text"><input name="mergeAttributes" id="mergeAttributes" type="text"><input name="lookupPrefix" id="lookupPrefix" type="text"><input name="localName" id="localName" type="text"><input name="length" id="length" type="text"><input name="lastElementChild" id="lastElementChild" type="text"><input name="lastChild" id="lastChild" type="text"><input name="language" id="language" type="text"><input name="lang" id="lang" type="text"><input name="item" id="item" type="text"><input name="isTextEdit" id="isTextEdit" type="text"><input name="isSupported" id="isSupported" type="text"><input name="isSameNode" id="isSameNode" type="text"><input name="isPrototypeOf" id="isPrototypeOf" type="text"><input name="isMultiLine" id="isMultiLine" type="text"><input name="isEqualNode" id="isEqualNode" type="text"><input name="isDisabled" id="isDisabled" type="text"><input name="isDefaultNamespaceURI" id="isDefaultNamespaceURI" type="text"><input name="isDefaultNamespace" id="isDefaultNamespace" type="text"><input name="isContentEditable" id="isContentEditable" type="text"><input name="insertBefore" id="insertBefore" type="text"><input name="insertAdjacentText" id="insertAdjacentText" type="text"><input name="insertAdjacentHTML" id="insertAdjacentHTML" type="text"><input name="insertAdjacentElement" id="insertAdjacentElement" type="text"><input name="innerText" id="innerText" type="text"><input name="innerHTML" id="innerHTML" type="text"><input name="id" id="id" type="text"><input name="hideFocus" id="hideFocus" type="text"><input name="hasOwnProperty" id="hasOwnProperty" type="text"><input name="hasChildNodes" id="hasChildNodes" type="text"><input name="hasAttributes" id="hasAttributes" type="text"><input name="hasAttributeNS" id="hasAttributeNS" type="text"><input name="hasAttribute" id="hasAttribute" type="text"><input name="getUserData" id="getUserData" type="text"><input name="getFeature" id="getFeature" type="text"><input name="getExpression" id="getExpression" type="text"><input name="getElementsByTagNameNS" id="getElementsByTagNameNS" type="text"><input name="getElementsByTagName" id="getElementsByTagName" type="text"><input name="getElementsByClassName" id="getElementsByClassName" type="text"><input name="getClientRects" id="getClientRects" type="text"><input name="getBoundingClientRect" id="getBoundingClientRect" type="text"><input name="getAttributeNodeNS" id="getAttributeNodeNS" type="text"><input name="getAttributeNode" id="getAttributeNode" type="text"><input name="getAttributeNS" id="getAttributeNS" type="text"><input name="getAttribute" id="getAttribute" type="text"><input name="getAdjacentText" id="getAdjacentText" type="text"><input name="focus" id="focus" type="text"><input name="firstElementChild" id="firstElementChild" type="text"><input name="firstChild" id="firstChild" type="text"><input name="fireEvent" id="fireEvent" type="text"><input name="enctype" id="enctype" type="text"><input name="encoding" id="encoding" type="text"><input name="elements" id="elements" type="text"><input name="dragDrop" id="dragDrop" type="text"><input name="document" id="document" type="text"><input name="dispatchFormInput" id="dispatchFormInput" type="text"><input name="dispatchFormChange" id="dispatchFormChange" type="text"><input name="dispatchEvent" id="dispatchEvent" type="text"><input name="dir" id="dir" type="text"><input name="detachEvent" id="detachEvent" type="text"><input name="data" id="data" type="text"><input name="currentStyle" id="currentStyle" type="text"><input name="contentEditable" id="contentEditable" type="text"><input name="contains" id="contains" type="text"><input name="constructor" id="constructor" type="text"><input name="componentFromPoint" id="componentFromPoint" type="text"><input name="compareDocumentPosition" id="compareDocumentPosition" type="text"><input name="cloneNode" id="cloneNode" type="text"><input name="clientWidth" id="clientWidth" type="text"><input name="clientTop" id="clientTop" type="text"><input name="clientLeft" id="clientLeft" type="text"><input name="clientHeight" id="clientHeight" type="text"><input name="click" id="click" type="text"><input name="clearAttributes" id="clearAttributes" type="text"><input name="className" id="className" type="text"><input name="children" id="children" type="text"><input name="childNodes" id="childNodes" type="text"><input name="childElementCount" id="childElementCount" type="text"><input name="checkValidity" id="checkValidity" type="text"><input name="canHaveHTML" id="canHaveHTML" type="text"><input name="canHaveChildren" id="canHaveChildren" type="text"><input name="blur" id="blur" type="text"><input name="blockDiraction" id="blockDiraction" type="text"><input name="behaviorUrns" id="behaviorUrns" type="text"><input name="baseURI" id="baseURI" type="text"><input name="autocomplete" id="autocomplete" type="text"><input name="attributes" id="attributes" type="text"><input name="attachEvent" id="attachEvent" type="text"><input name="ariaValuenow" id="ariaValuenow" type="text"><input name="ariaValuemin" id="ariaValuemin" type="text"><input name="ariaValuemax" id="ariaValuemax" type="text"><input name="ariaSetsize" id="ariaSetsize" type="text"><input name="ariaSelected" id="ariaSelected" type="text"><input name="ariaSecret" id="ariaSecret" type="text"><input name="ariaRequired" id="ariaRequired" type="text"><input name="ariaReadonly" id="ariaReadonly" type="text"><input name="ariaPressed" id="ariaPressed" type="text"><input name="ariaPosinset" id="ariaPosinset" type="text"><input name="ariaOwns" id="ariaOwns" type="text"><input name="ariaMultiselect" id="ariaMultiselect" type="text"><input name="ariaLevel" id="ariaLevel" type="text"><input name="ariaLabelledby" id="ariaLabelledby" type="text"><input name="ariaInvalid" id="ariaInvalid" type="text"><input name="ariaHidden" id="ariaHidden" type="text"><input name="ariaHaspopup" id="ariaHaspopup" type="text"><input name="ariaFlowto" id="ariaFlowto" type="text"><input name="ariaExpanded" id="ariaExpanded" type="text"><input name="ariaDisabled" id="ariaDisabled" type="text"><input name="ariaDescribability" id="ariaDescribability" type="text"><input name="ariaControls" id="ariaControls" type="text"><input name="ariaChecked" id="ariaChecked" type="text"><input name="ariaBusy" id="ariaBusy" type="text"><input name="applyElement" id="applyElement" type="text"><input name="appendChild" id="appendChild" type="text"><input name="all" id="all" type="text"><input name="addRepetitionBlockByIndex" id="addRepetitionBlockByIndex" type="text"><input name="addRepetitionBlock" id="addRepetitionBlock" type="text"><input name="addEventSource" id="addEventSource" type="text"><input name="addEventListener" id="addEventListener" type="text"><input name="addBehavior" id="addBehavior" type="text"><input name="action" id="action" type="text"><input name="acceptCharset" id="acceptCharset" type="text"><input name="accept" id="accept" type="text"><input name="TEXT_NODE" id="TEXT_NODE" type="text"><input name="PROCESSING_INSTRUCTION_NODE" id="PROCESSING_INSTRUCTION_NODE" type="text"><input name="NOTATION_NODE" id="NOTATION_NODE" type="text"><input name="ENTITY_REFERENCE_NODE" id="ENTITY_REFERENCE_NODE" type="text"><input name="ENTITY_NODE" id="ENTITY_NODE" type="text"><input name="ELEMENT_NODE" id="ELEMENT_NODE" type="text"><input name="DOCUMENT_TYPE_NODE" id="DOCUMENT_TYPE_NODE" type="text"><input name="DOCUMENT_POSITION_PRECEDING" id="DOCUMENT_POSITION_PRECEDING" type="text"><input name="DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" id="DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC" type="text"><input name="DOCUMENT_POSITION_FOLLOWING" id="DOCUMENT_POSITION_FOLLOWING" type="text"><input name="DOCUMENT_POSITION_DISCONNECTED" id="DOCUMENT_POSITION_DISCONNECTED" type="text"><input name="DOCUMENT_POSITION_CONTAINS" id="DOCUMENT_POSITION_CONTAINS" type="text"><input name="DOCUMENT_POSITION_CONTAINED_BY" id="DOCUMENT_POSITION_CONTAINED_BY" type="text"><input name="DOCUMENT_NODE" id="DOCUMENT_NODE" type="text"><input name="DOCUMENT_FRAGMENT_NODE" id="DOCUMENT_FRAGMENT_NODE" type="text"><input name="COMMENT_NODE" id="COMMENT_NODE" type="text"><input name="CDATA_SECTION_NODE" id="CDATA_SECTION_NODE" type="text"><input name="ATTRIBUTE_NODE" id="ATTRIBUTE_NODE" type="text"> |
+</form> |
+<form name="title"/> |
+ |
+<pre id="pass">PASS - All Form Properties Replaced by an Element</pre> |
+<pre id="fail">FAIL</pre> |
+<pre> |
+<script type='text/javascript' src="names.js"></script> |
+<script type="text/javascript"> |
+(function(){ |
+var form = document.forms[0]; |
+var actual, expected, msg, actualString; |
+var bugs = []; |
+ |
+for(var i = names.length -1; i > 0; i--) { |
+ try{ |
+ actual = form[names[i]]; |
+ if(actual != input) { |
+ msg = names[i]; |
+ if(actual.toString && actual.toString.tagName) |
+ actualString = actual.toString.tagName; |
+ else |
+ actualString = String(actual); |
+ msg += " found: " + (((actualString + " ("+typeof actual+")")) || "(missing)"); |
+ bugs[bugs.length] = msg; |
+ } |
+ } catch(x){ |
+ msg = "Error: " + x.message; |
+ } |
+} |
+// can't use form.elements, form.getElementsByTagName, et c |
+// because they were replaced by an input. |
+ |
+if(bugs.length > 0) |
+ fail(bugs); |
+else pass(); |
+ |
+function fail(bugs) { |
+ var fail = document.getElementById('fail'); |
+ fail.firstChild.data += ': The following ' + bugs.length + |
+ ' form properties should have been an INPUT element:\n * ' + bugs.join('\n * '); |
+ fail.style.display = "inline-block"; |
+} |
+ |
+function pass() { |
+ var pass = document.getElementById('pass'); |
+ pass.style.display = "inline-block"; |
+} |
+ |
+})(); |
+</script> |
+</body> |
+</html> |
/cljs/names/form_override_html_source.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/names/form_override_change_name.html |
=================================================================== |
--- cljs/names/form_override_change_name.html (nonexistent) |
+++ cljs/names/form_override_change_name.html (revision 2) |
@@ -0,0 +1,75 @@ |
+<!DOCTYPE HTML> |
+<html lang="en"> |
+<head> |
+ <title>Safe Form Controls</title> |
+ <style type="text/css"> |
+ input { font-size: 8px; font-family: courier new, monospace; padding: 0 } |
+ #pass { display: none; background : #0f0; } |
+ #fail { display: none; background : #F33; } |
+ </style> |
+</head> |
+<body> |
+<h1>Test: 290 Names not to give a FORM Control</h1> |
+<form name="length" action="fail" title="fail"> |
+<input type="submit" /> |
+</form> |
+<pre id="pass">PASS - All Form Properties Replaced by an Element</pre> |
+<pre id="fail">FAIL</pre> |
+<pre> |
+<script type='text/javascript' src="names.js"></script> |
+<script type="text/javascript"> |
+(function(){ |
+var form = document.forms[0]; |
+var input = form.elements[0]; |
+var bugs = []; |
+ |
+var actual, expected, msg, actualString; |
+ |
+for(var i = names.length -1; i > 0; i--) { |
+ if(names[i] == names[i-1]) { |
+ alert("found duplicate: " + names[i]); |
+ break; |
+ } |
+ else { |
+ try{ |
+ input.name = names[i]; |
+ actual = form[names[i]]; |
+ if(actual != input) { |
+ msg = names[i]; |
+ if(actual.toString && actual.toString.tagName) |
+ actualString = actual.toString.tagName; |
+ else |
+ actualString = String(actual); |
+ msg += " found: " + (((actualString + " ("+typeof actual+")")) || "(missing)"); |
+ bugs[bugs.length] = msg; |
+ } |
+ } catch(x){ |
+ msg = "Error: " + x.message; |
+ } |
+ } |
+} |
+// can't use form.elements, form.getElementsByTagName, et c |
+// because they were replaced by an input. |
+ |
+if(bugs.length > 0) |
+ fail(bugs); |
+else pass(); |
+ |
+function fail(bugs) { |
+ var fail = document.getElementById('fail'); |
+ fail.firstChild.data += ': The following ' + bugs.length + |
+ ' form properties should have been an INPUT element:\n * ' + bugs.join('\n * '); |
+ fail.style.display = "inline-block"; |
+} |
+ |
+function pass() { |
+ var pass = document.getElementById('pass'); |
+ pass.style.display = "inline-block"; |
+} |
+ |
+//document.write(names.join("\n </li>\n<li>\n")); |
+})(); |
+</script> |
+</pre> |
+</body> |
+</html> |
/cljs/names/form_override_change_name.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/names/index.html |
=================================================================== |
--- cljs/names/index.html (nonexistent) |
+++ cljs/names/index.html (revision 2) |
@@ -0,0 +1,235 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"> |
+<html lang="en"> |
+<head> |
+ <title>Unsafe Names for HTML Form Controls</title> |
+ <meta http-equiv="content-type" content="text/html; charset=iso-8859-1"> |
+ <meta name="author" content="Garrett Smith"> |
+ <meta name="author-email" content="dhtmkitchen@gmail.com"> |
+ <link rel="stylesheet" href="../faq.css" type="text/css" media="all" charset="iso-8859-1"> |
+ <link rel="stylesheet" href="names.css" type="text/css" media="all" charset="iso-8859-1"> |
+ <link rel="Start" href="./"> |
+</head> |
+<body> |
+ <h1>Unsafe Names for HTML Form Controls</h1> |
+ |
+ <p> |
+ by Garrett Smith (<a href="http://www.dhtmlkitchen.com/">dhtmlkitchen.com</a>), |
+ edited by Frank Manno (<a href="http://www.frankmanno.com/">frankmanno.com</a>) |
+ with comments from David Mark, Richard Cornford, RobG, and Juriy Zaytsev. |
+ </p> |
+ <h2>Rich, Featureful Forms</h2> |
+ |
+ <p> |
+ An HTML <code>FORM</code> element, in most modern browsers, |
+ implements many interfaces and has a rich set of features. |
+ These features are exposed as properties of the form, such as |
+ <code>addEventListener</code>, <code>parentNode</code>, and |
+ <code>submit</code>. Browsers also add their own non-standard features |
+ such as <code>all</code>, <code>contentEditable</code>, or <code>spellcheck</code>. |
+ </p> |
+ |
+ <h3>Problem</h3> |
+ <p> |
+ Browsers add <code>name</code>s and <code>id</code>s of form |
+ controls as properties to the <code>FORM</code>. This results in |
+ the properties of the form being replaced. |
+ </p> |
+ <p> |
+ Browsers also may add <code>name</code>s |
+ and <code>id</code>'s of other elements as properties to |
+ <code>document</code>, and sometimes to the <code>global</code> |
+ object (or an object above the <code>global</code> object in scope). |
+ This non-standard behavior can result in replacement of |
+ properties on other objects. The problems it causes are discussed in detail. |
+ </p> |
+ |
+ <p> |
+ A problem occurs when a form control's <code>name</code> conflicts |
+ with the a property name of the <code>FORM</code> object. For example: |
+ </p> |
+ |
+ <h4>Simple Unsafe Name Example</h4> |
+ <pre> |
+<form action=""> |
+ <input type="text" name="name"> |
+ <input type="submit" name="submit"> |
+</form> |
+</pre> |
+ |
+ <h5>Result</h5> |
+ <p> |
+ The element with <code>name="name"</code> replaces |
+ the value of the <code>FORM</code>'s <code>name</code> property. |
+ A similar type of conflict happens with the |
+ <code>FORM</code>'s <code>submit</code> method and the |
+ element with <code>name="submit'</code>. Which will win? |
+ </p> |
+ <p> |
+ In most cases, the form control wins and the <code>FORM</code>'s property is |
+ replaced to have the value of the form control, or, if more than |
+ one form control has that name, the <code>FORM</code>'s property is |
+ replaced with a <code>NodeList</code> containing those form controls. |
+ </p> |
+ <p> |
+ However, in some cases, the <code>FORM</code>'s property is <em>not</em> replaced |
+ to have the value of the form control with the same name. The examples in this page show that |
+ the result depends on the browser, the property, and how the control is added. |
+ </p> |
+ |
+ <h4>How is a Form Like a Collection?</h4> |
+ <p> |
+ The DOM 1 specification states: |
+ </p> |
+ <blockquote cite="http://www.w3.org/TR/REC-DOM-Level-1/level-one-html.html#ID-40002357"> |
+ <p> |
+ The <code>FORM</code> element encompasses behavior similar to a collection and an element. |
+ It provides direct access to the contained <code>input</code> elements as well as the |
+ attributes of the <code>FORM</code> element. [<a href="conclusion.html#controls-normref">DOM1</a>] |
+ </p> |
+ </blockquote> |
+ |
+ <p> |
+ <cite>"Similar to a collection?"</cite> |
+ <em>What</em> collection? Similar in what way? |
+ The only standardized feature that is <cite>"similar to a collection"</cite> is |
+ the <code>length</code> property. |
+ </p> |
+ |
+ <p> |
+ In most browsers, a form has direct access to all named form controls, |
+ (except for <code>input type="image"</code>), not just <code>input</code> elements. |
+ </p> |
+ <p> |
+ Accessing controls as named or indexed properties is not standardized by the w3c DOM specification. |
+ It is a holdover feature from Netscape Navigator that was copied by Internet Explorer |
+ and since copied by every other major browser vendor. |
+ </p> |
+ |
+ <h4>How the Nonstandard Form-as-a-Collection <em>Really</em> Works</h4> |
+ <p> |
+ Controls may be accessed directly off the form. |
+ </p> |
+ |
+ <p>Given the following form:</p> |
+ |
+ <pre> |
+<form action=""> |
+ <input type="text" name="a"> |
+</form> |
+</pre> |
+ <p> |
+ The <code>input name="a"</code> may be retrieved in one of two ways, from the form |
+ or from the <code>elements</code> collection. |
+ </p> |
+ <h5>The elements Collection (standard)</h5> |
+ |
+ <pre> |
+ // Standard. |
+ document.forms[0].elements[0]; |
+ document.forms[0].elements.a; |
+</pre> |
+ <p> |
+ The control may be accessed directly off the form: |
+ </p> |
+ <h5>Directly from the Form (nonstandard)</h5> |
+ <pre> |
+ // non-standard. |
+ document.forms[0][0]; |
+ document.forms[0].a; |
+</pre> |
+ |
+ <h4>Side Effects</h4> |
+ <p> |
+ Accessing a named control directly off the form can have undesirable results. |
+ </p> |
+ <p> |
+ In a few browsers, removing a named control from the form will leave the named |
+ control as a property of the form. |
+ </p> |
+ <h5>Form-as-a-Collection Leak Example</h5> |
+ <p> |
+ This <a href="simple-leak-form-input.html">Simple leak</a> example shows |
+ that accessing a named element property directly from the <code>form</code> |
+ may cause the property to remain on the form, even after the element |
+ has been removed from the DOM. |
+ </p> |
+ <h5>Results</h5> |
+ <strong>Firefox 3, Safari 3</strong> |
+ <pre> |
+foo: [object HTMLInputElement] |
+bar: undefined |
+elements.foo: undefined |
+</pre> |
+ <strong>Opera 9.5, IE 6, Safari 2</strong> |
+ <pre> |
+foo: undefined |
+bar: undefined |
+elements.foo: undefined |
+</pre> |
+ |
+ <p> |
+ Similarly, when a named <code>FORM</code> element is removed from the <code>document</code> |
+ some browsers will keep that form name as a property of the <code>document</code>. |
+ Accessing named <code>FORM</code> controls as properties of the document is also nonstandard. |
+ </p> |
+ |
+ <h5>Standard</h5> |
+ <pre>document.forms.myform;</pre> |
+ <h5>Nonstandard</h5> |
+ <pre>document.myform;</pre> |
+ |
+ <p> |
+ A <code>form</code>'s indexed form control properties may also appear out of order. |
+ This behavior would not be compliant for the <code>elements</code> collection, |
+ it does not violate any standard for the form-as-a-collection (because |
+ there is no standard). |
+ </p> |
+ |
+ <p> |
+ Form-as-a-collection is unreliable and therefore should never be used. |
+ </p> |
+ |
+ <h3>The <code>elements</code> Collection</h3> |
+ <p> |
+ The <code>form.elements</code> collection |
+ provides programmers a safe place to access form controls. |
+ </p> |
+ |
+ <p> |
+ The <code>elements</code> collection contains the following properties: |
+ <code>length</code>, <code>item</code>, <code>namedItem</code>, plus an ordinal |
+ index property for each form control (excepting <code>input type="image"</code> controls). |
+ Some browsers also have a <code>tags</code> property on the <code>elements</code> collection. |
+ </p> |
+ |
+ <h4>The elements Collection is Live</h4> |
+ <p> |
+ When a form control is removed from the DOM, the <code>elements</code> collection |
+ is updated; however, the property will still remain on the form in some browsers |
+ (<a href="https://bugzilla.mozilla.org/show_bug.cgi?id=307415">Mozilla bug 307415</a>). |
+ </p> |
+ <h5>Element Removal Example</h5> |
+ <p> |
+ <a href="form_dom_removal.html">element removal example</a> |
+ </p> |
+ |
+ <div id="toc"> |
+ <h4>Table of Contents</h4> |
+ <ul class="pagination linkList"> |
+ <li>Introduction</li> |
+ <li><a href="extra_props.html">Extra Properties: <code>FORM</code> Elements</a></li> |
+ <li><a href="extra_props_document.html">Extra Properties: <code>document</code></a></li> |
+ <li><a href="extra_props_global.html">Extra Properties: <code>global</code></a></li> |
+ <li><a href="event_handler.html">Event Handler Scope</a></li> |
+ <li><a href="api_design.html">API Design?</a></li> |
+ <li><a href="unsafe_names.html">Unsafe Names</a></li> |
+ <li><a href="conclusion.html">Conclusion</a></li> |
+ </ul> |
+ </div> |
+ <ul id="nextLink" class="linkList"> |
+ <li> |
+ <span class="next">Next:</span> <a href="extra_props.html">Extra Properties: <code>FORM</code> Elements</a> |
+ </li> |
+ </ul> |
+</body> |
+</html> |
/cljs/names/index.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/names/callable_example.html |
=================================================================== |
--- cljs/names/callable_example.html (nonexistent) |
+++ cljs/names/callable_example.html (revision 2) |
@@ -0,0 +1,59 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
+ "http://www.w3.org/TR/html4/loose.dtd"> |
+<html lang="en"> |
+<head> |
+ <title>Callable HTMLCollection</title> |
+ <link rel="Start" href="./"> |
+ <link rev="Section" href="api_design.html"> |
+</head> |
+<body> |
+<form action="" id="a" name="d"><input type="text"></form> |
+<h3>Your Browser's Result:</h3> |
+<pre id="callableResult">-</pre> |
+<pre> |
+<script type="text/javascript">(function(){ |
+var f = document.forms, isCallable = true, |
+ callableResult = document.getElementById('callableResult'); |
+try { |
+ f(0); |
+} catch(ex) { |
+ isCallable = false; |
+} |
+if(!isCallable) { |
+ callableResult.firstChild.data = "form is not callable"; |
+} else { |
+ callableResult.firstChild.data = |
+ ["typeof f " + "\""+ (typeof f) + "\"", |
+ "f('0') " + f('0'), |
+ "f('a') " + f('a'), |
+ "f('d') " + f('d')].join('\n'); |
+} |
+})();</script> |
+</pre> |
+<hr> |
+<h3>Browser Results:</h3> |
+Firefox |
+<pre>form is not callable</pre> |
+Opera 9 |
+<pre> |
+typeof f "object" |
+f('0') [object HTMLFormElement] |
+f('a') [object HTMLFormElement] |
+f('d') [object HTMLFormElement] |
+</pre> |
+IE6, IE7, IE8 |
+<pre> |
+typeof f "object" |
+f('0') [object] |
+f('a') [object] |
+f('d') [object] |
+</pre> |
+Safari |
+<pre> |
+typeof f "function" |
+f('0') [object HTMLFormElement] |
+f('a') [object HTMLFormElement] |
+f('d') [object HTMLFormElement] |
+</pre> |
+</body> |
+</html> |
/cljs/names/callable_example.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/names/names.js |
=================================================================== |
--- cljs/names/names.js (nonexistent) |
+++ cljs/names/names.js (revision 2) |
@@ -0,0 +1,316 @@ |
+var names = [ |
+ // HTMLFormElement |
+ "elements","length", //readonly. |
+ "name", "acceptCharset", "action", "enctype", "method", "target", "submit", "reset", |
+ |
+ // HTMLElement |
+ "id", "title", "lang", "dir", "className", |
+ |
+ // Element. |
+ "tagName", "schemaTypeInfo", // readonly. |
+ "getAttribute", "removeAttribute", "getAttributeNode", |
+ "setAttributeNode", "removeAttributeNode", "getElementsByTagName", |
+ "getAttributeNS", "setAttributeNS", "removeAttributeNS", |
+ "getAttributeNodeNS", "setAttributeNodeNS", "getElementsByTagNameNS", |
+ "hasAttribute", "hasAttributeNS", "setIdAttribute", "setIdAttributeNS", |
+ "setIdAttributeNode", |
+ |
+ // Node. |
+ // Node constants. |
+ "ELEMENT_NODE", |
+ "ATTRIBUTE_NODE", |
+ "TEXT_NODE", |
+ "CDATA_SECTION_NODE", |
+ "ENTITY_REFERENCE_NODE", |
+ "ENTITY_NODE", |
+ "PROCESSING_INSTRUCTION_NODE", |
+ "COMMENT_NODE", |
+ "DOCUMENT_NODE", |
+ "DOCUMENT_TYPE_NODE", |
+ "DOCUMENT_FRAGMENT_NODE", |
+ "NOTATION_NODE", |
+ "DOCUMENT_POSITION_DISCONNECTED", |
+ "DOCUMENT_POSITION_PRECEDING", |
+ "DOCUMENT_POSITION_FOLLOWING", |
+ "DOCUMENT_POSITION_CONTAINS", |
+ "DOCUMENT_POSITION_CONTAINED_BY", |
+ "DOCUMENT_POSITION_IMPLEMENTATION_SPECIFIC", |
+ |
+ // Readonly. |
+ "nodeName", |
+ "nodeType", |
+ "parentNode", |
+ "childNodes", |
+ "firstChild", |
+ "lastChild", |
+ "previousSibling", |
+ "nextSibling", |
+ "attributes", |
+ "ownerDocument", |
+ "namespaceURI", |
+ "localName", |
+ "baseURI", |
+ |
+ "nodeValue", |
+ "insertBefore", |
+ "replaceChild", |
+ "removeChild", |
+ "appendChild", |
+ "hasChildNodes", |
+ "cloneNode", |
+ "normalize", |
+ "isSupported", |
+ "prefix", |
+ "hasAttributes", |
+ "compareDocumentPosition", |
+ "textContent", |
+ "isSameNode", |
+ "lookupPrefix", |
+ "isDefaultNamespaceURI", |
+ "isEqualNode", |
+ "getFeature", |
+ "setUserData", |
+ "getUserData", |
+ |
+ // ElementCSSInlineStyle. |
+ "style", // readonly. |
+ |
+ // EventTarget. |
+ "addEventListener", |
+ "removeEventListener", |
+ "dispatchEvent", |
+ |
+ // Mouse Events |
+ "onclick", |
+ "onmousedown", |
+ "onmouseup", |
+ "onmouseover", |
+ "onmousemove", |
+ "onmouseout", |
+ "ondblclick", |
+ |
+ // MouseWheelEvent. |
+ "onmousewheel", |
+ "onmousemultiwheel", |
+ |
+ // Key Events. |
+ "onkeydown", |
+ "onkeyup", |
+ "onkeypress", |
+ |
+ // bubbled events? |
+ "onchage", |
+ "onabort", |
+ "onerror", |
+ "onselect", |
+ "onresize", |
+ "onscroll", |
+ |
+ // New Events for Element: |
+ "onfocus", |
+ "onblur", |
+ |
+ // Proprietary MSIE (also HTML 5/FF). |
+ "clientHeight", |
+ "clientWidth", |
+ "offsetHeight", |
+ "offsetWidth", |
+ "clientLeft", |
+ "clientTop", |
+ "contentEditable", |
+ "getBoundingClientRect", |
+ "getClientRects", |
+ "getElementsByClassName", |
+ "scrollIntoView", |
+ "scrollLeft", |
+ "scrollTop", |
+ "scrollWidth", |
+ "scrollHeight", |
+ "tabIndex", |
+ "encoding", |
+ "spellcheck", |
+ "innerHTML", |
+ "innerText", |
+ "children", |
+ |
+ "ariaBusy", |
+ "ariaChecked", |
+ "ariaControls", |
+ "ariaDescribability", |
+ "ariaDisabled", |
+ "ariaExpanded", |
+ "ariaFlowto", |
+ "ariaHaspopup", |
+ "ariaHidden", |
+ "ariaInvalid", |
+ "ariaLabelledby", |
+ "ariaLevel", |
+ "ariaMultiselect", |
+ "ariaOwns", |
+ "ariaPosinset", |
+ "ariaPressed", |
+ "ariaReadonly", |
+ "ariaRequired", |
+ "ariaSecret", |
+ "ariaSelected", |
+ "ariaSetsize", |
+ "ariaValuemax", |
+ "ariaValuemin", |
+ "ariaValuenow", |
+ |
+ "autocomplete", |
+ "blockDiraction", |
+ "canHaveChildren", |
+ "canHaveHTML", |
+ "hideFocus", |
+ "isContentEditable", |
+ "isDisabled", |
+ "isMultiLine", |
+ "isTextEdit", |
+ "language", |
+ "msBlockProgression", |
+ "msBoxSizing", |
+ "onOffBehavior", |
+ "outerHTML", |
+ "outerText", |
+ "parentTextEdit", |
+ "quotes", |
+ "role", |
+ "scopeName", |
+ "sourceIndex", |
+ "tagUrn", |
+ "uniqueID", |
+ |
+ "all", |
+ "behaviorUrns", |
+ |
+ "onactivate", |
+ "onbeforeactivate", |
+ "onbeforecopy", |
+ "onbeforecut", |
+ "onbeforedeactivate", |
+ "onbeforeeditfocus", |
+ "onbeforepaste", |
+ "oncontextmenu", |
+ "oncopy", |
+ "oncut", |
+ "ondeactivate", |
+ "ondrag", |
+ "ondragend", |
+ "ondragenter", |
+ "ondragleave", |
+ "ondragover", |
+ "onfocusin", |
+ "onfocusout", |
+ "onhelp", |
+ "onclosecapture", |
+ "onmouseenter", |
+ "onmouseleave", |
+ "onmove", |
+ "onmoveend", |
+ "onmovestart", |
+ "onpaste", |
+ "onpropertychange", |
+ "onreadystatechange", |
+ "onresizeend", |
+ "onresizestart", |
+ "onselectstart", |
+ "ontimeerror", |
+ |
+ // methods. |
+ "addBehavior", |
+ "applyElement", |
+ "attachEvent", |
+ "blur", |
+ "clearAttributes", |
+ "click", |
+ "componentFromPoint", |
+ "contains", |
+ "detachEvent", |
+ "dragDrop", |
+ "fireEvent", |
+ "focus", |
+ "getAdjacentText", |
+ "getExpression", |
+ "insertAdjacentElement", |
+ "insertAdjacentHTML", |
+ "insertAdjacentText", |
+ "item", |
+ "mergeAttributes", |
+ "namedItem", |
+ "querySelector", |
+ "querySelectorAll", |
+ "releaseCapture", |
+ "removeBehavior", |
+ "removeExpression", |
+ "removeNode", |
+ "replaceAdjacentText", |
+ "replaceNode", |
+ "setActive", |
+ "setCapture", |
+ "setExpression", |
+ "swapNode", |
+ "urns", |
+ |
+ // objects. |
+ "currentStyle", |
+ "runtimeStyle", |
+ |
+ // WF2.0 |
+ "accept", |
+ "checkValidity", |
+ "replace", |
+ "data", |
+ "resetFromData", |
+ "dispatchFormInput", |
+ "dispatchFormChange", |
+ "templateElements", |
+ |
+ // Proprietary Moz/HTML 5 |
+ "isDefaultNamespace", |
+ |
+ // Opera |
+ "childElementCount", |
+ "firstElementChild", |
+ "lastElementChild", |
+ "previousElementSibling", |
+ "repeatMin", |
+ "repeatStart", |
+ "repetitionBlocks", |
+ "repetitionIndex", |
+ "repetitionTemplate", |
+ "repetitionType", |
+ "repeatMax", |
+ "text", |
+ "unselectable", |
+ "addRepetitionBlock", |
+ "addRepetitionBlockByIndex", |
+ "moveRepetitionBlock", |
+ "removeRepetitionBlock", |
+ "selectNodes", |
+ "selectSingleNode", |
+ "addEventSource", |
+ "removeEventSource", |
+ |
+ // Webkit |
+ "oninput", |
+ "scrollByLines", |
+ "scrollByPages", |
+ "document", |
+ "onsearch", |
+ "onunload", |
+ |
+ // Scope chain for event handler attributes. |
+ "window", |
+ |
+ // Object.prototype |
+ "constructor", |
+ "toString", |
+ "toLocaleString", |
+ "valueOf", |
+ "hasOwnProperty", |
+ "isPrototypeOf", |
+ "propertyIsEnumerable", |
+ "watch", |
+ "unwatch" |
+].sort(); |
\ No newline at end of file |
/cljs/names/names.js |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/index.xml |
=================================================================== |
--- cljs/index.xml (nonexistent) |
+++ cljs/index.xml (revision 2) |
@@ -0,0 +1,2300 @@ |
+<FAQ VERSION="32.2" DATE="2010-10-08"> |
+ <TITLE>comp.lang.javascript FAQ</TITLE> |
+ <CONTENTS> |
+ <CONTENT TITLE="Meta-FAQ meta-questions" ID="meta" NUMID="1"> |
+ <P> |
+This is the <EM>comp.lang.javascript</EM> meta-FAQ, <VER/>. The latest |
+version is available at <URL>http://jibbering.com/faq/</URL> in HTML form. |
+</P> |
+<P> |
+Each day, one section of the FAQ is posted for review and questions, |
+and as a reminder that the FAQ is available. |
+</P> |
+<P> |
+For additional explanation and detail relating to some aspects |
+of the FAQ, please see the |
+<URL LINKTEXT="FAQ Notes">notes/</URL>. |
+It has been provided separately to avoid increasing the size of |
+the FAQ to a point where it would be unreasonable to post it to |
+the group. |
+</P> |
+<P> |
+Code examples in this FAQ use <URL LINKTEXT="JSDoc Toolkit" |
+>http://jsdoctoolkit.org/</URL> comments. |
+</P> |
+ <CONTENT TITLE="Which newsgroups deal with javascript?" ID="newsgroups" NUMID="2_1"> |
+ <P> |
+The official Big 8 Usenet newsgroup dealing with javascript is |
+<NEWSGROUP>comp.lang.javascript</NEWSGROUP>. |
+Some "language" hierarchies also have *.comp.lang.javascript groups. |
+ </P> |
+ <P> |
+c.l.js is an unmoderated newsgroup. |
+ </P> |
+ </CONTENT> |
+ <CONTENT TITLE="What questions are on-topic for comp.lang.javascript?" ID="appropriateQuestions" NUMID="2_2"> |
+ <P> |
+The comp.lang.javascript newsgroup deals with ECMAScript |
+languages, so any questions about JavaScript or JScript are |
+welcome. However, the majority of questions sent to this group |
+relates to javascript in a web browser. If you are experiencing |
+issues with a particular browser, or the host is not a browser |
+at all, please make this information clear. |
+ </P> |
+ <P> |
+Javascript and Java are two completely different languages. |
+Java questions should be asked in one of the comp.lang.java.* |
+newsgroups; they are not appropriate for c.l.js (as Java and |
+javascript are distinct programming languages with only |
+superficial similarities due to sharing a C-like syntax and |
+some of the characters in their names). |
+ </P> |
+ <P> |
+Questions dealing with other scripting languages, such as |
+VBScript, PerlScript or CGI scripting are also off-topic, |
+as are HTML-only or CSS-only questions. |
+ </P> |
+ <!-- |
+ <P> |
+ Questions about the design of various javascript libraries are |
+ appropriate; questions on how to <EM>use</EM> such libraries |
+ are not. Check <URL LINKTEXT="c.l.js FAQ Resources" |
+ >http://jibbering.comindex.html#libraryResources</URL> or search the web. |
+ </P> |
+ --> |
+ <P> |
+Questions that are specific to Microsoft's JScript may also |
+be appropriately asked at: |
+<NEWSGROUP>microsoft.public.scripting.jscript</NEWSGROUP> |
+ </P> |
+ <P> |
+The comp.lang.javascript newsgroup charter is included in |
+<URL>faq_notes/cljs_charter.html</URL>. |
+ </P> |
+ </CONTENT> |
+ <CONTENT TITLE="What should I do before posting to comp.lang.javascript?" ID="posting" NUMID="2_3"> |
+ |
+ <P> |
+Before posting to c.l.js, you should read this document. |
+You should also check the <URL LINKTEXT="Resources section">#onlineResources</URL>. |
+ </P> |
+ <LIST TYPE="UL" TITLE="How to Ask a Question" ID="ask"> |
+ <LI> |
+State your question clearly and concisely. |
+ </LI> |
+ <LI> |
+Use the Subject: line to show the type of problem you have but |
+include the question in the body as well. |
+ </LI> |
+ <LI> |
+For a more detailed explanation of formatting, see |
+ <URL |
+LINKTEXT='&quot;Posting Questions and Replies to comp.lang.javascript&quot;'>notes/posting/</URL>. |
+ </LI> |
+ </LIST> |
+ |
+ <LIST TYPE="UL" TITLE="Replying" ID="reply"> |
+ <LI> |
+Quote only relevant parts of earlier messages, and add your |
+comments below each quoted section |
+(<URL LINKTEXT="FYI28/RFC1855">http://www.ietf.org/rfc/rfc1855.txt</URL>). |
+ </LI> |
+ <LI> |
+Link to specific sections of the FAQ that are relevant. |
+ </LI> |
+ <LI> |
+Avoid being unnecessarily rude, but do not complain about other rude posts. |
+ </LI> |
+ <LI> |
+Don't quote signatures. |
+ </LI> |
+ </LIST> |
+ |
+ <LIST TYPE="UL" TITLE="Posting Code" ID="postCode"> |
+ <LI> |
+Remove everything that does not contribute to the problem (images, |
+markup, other scripts, etc). |
+ </LI> |
+ <LI> |
+Validate the HTML and CSS <URL>http://validator.w3.org/</URL>, <URL>http://jigsaw.w3.org/css-validator/</URL>. |
+ </LI> |
+ <LI> |
+Make sure the code is executable as transmitted. |
+ </LI> |
+ <LI> |
+Format lines to 72 characters; indent with 2-4 spaces (not tabs). |
+ </LI> |
+ <LI> |
+State what you expect the code to do. |
+ </LI> |
+ <LI> |
+Mention the platforms, browsers, and versions. |
+ </LI> |
+ <LI> |
+See also the <URL LINKTEXT="FAQ section on debugging" |
+>#debugging</URL>. |
+ </LI> |
+ <LI> |
+Post in plain-text only. Do not encode it. Do not attach files. |
+ </LI> |
+ <LI> |
+If the code is more than about 100 lines, provide a URL in addition. |
+ </LI> |
+ <LI> |
+Do not multi-post; cross-post if necessary |
+(<URL LINKTEXT="Wikipedia description">http://en.wikipedia.org/wiki/Cross-post</URL>). |
+ </LI> |
+ </LIST> |
+ <LIST TYPE="UL" TITLE="What Not to Post" ID="doNotPost"> |
+ <LI> |
+Do not post job postings. Job postings should go to |
+an appropriate regional jobs group. |
+ </LI> |
+ <LI> |
+Do not post copyright material without permission |
+from the copyright holder. |
+ </LI> |
+ </LIST> |
+ <P> |
+Relevant announcements are welcome, but no more often than once |
+per major release, as a short link to the product's webpage. |
+ </P> |
+ </CONTENT> |
+ <CONTENT TITLE="Why was my post not answered?" ID="noAnswer" NUMID="2_4"> |
+ <P> |
+This could be for several reasons: |
+ <UL> |
+ <LI> |
+It was a variation of a frequently asked question and was |
+therefore ignored by everyone. |
+ </LI> |
+ <LI> |
+Nobody knows the answer. |
+ </LI> |
+ <LI> |
+The person with the answer has not seen the post. |
+ </LI> |
+ <LI> |
+It might not be possible to do what you want to do but perhaps |
+readers of c.l.js are reluctant to answer your post in the negative |
+when they are not convinced that it cannot be done. |
+ </LI> |
+ <LI> |
+The question was not asked clearly enough, or did not included |
+enough information to be answered. |
+ </LI> |
+ <LI> |
+The questioner did not realise the need to read the group, for a |
+few days, to see the answers posted there. |
+ </LI> |
+ <LI>You ignored the <URL LINKTEXT="section on posting" |
+ >#posting</URL> |
+ </LI> |
+ </UL> |
+If it is not one of these, then after a few days consider |
+reposting after checking <URL>http://groups.google.com/group/comp.lang.javascript/topics</URL> |
+for replies. Make sure the post is phrased well, and everything |
+needed to answer is correct, and the subject is appropriate. |
+ </P> |
+ </CONTENT> |
+ </CONTENT> |
+ <CONTENT TITLE="Language Overview" ID="tips" NUMID="2"> |
+ |
+ <CONTENT TITLE="What is ECMAScript?" ID="ecma" NUMID="2_6"> |
+ <P> |
+ |
+<URL LINKTEXT="ECMA-262">http://www.ecma-international.org/publications/standards/Ecma-262.htm</URL> |
+is the international standard that current language implementations |
+(JavaScript&trade;, JScript etc.) are based on. |
+ |
+ </P> |
+ <P> |
+<URL LINKTEXT="ECMA-262">http://www.ecma-international.org/publications/standards/Ecma-262.htm</URL> |
+defines the language Syntax, Types, Keywords, Operators, and built-in |
+objects. The ECMAScript specification is the reference to determine the |
+expected behavior of a program. ECMAScript does not define any host |
+objects, such as <ICODE>document</ICODE>, <ICODE>window</ICODE>, or <ICODE>ActiveXObject</ICODE>. |
+ </P> |
+<P> |
+ECMA-327 defines the Compact Profile of ECMAScript by |
+describing the features from ECMA 262 that may be omitted in some |
+resource-constrained environments. |
+<URL>http://www.ecma-international.org/publications/standards/Ecma-327.htm</URL> |
+ </P> |
+ <P> |
+The most widely supported edition of ECMA-262 is the 3rd edition (1999). |
+There is fair support for this edition in JScript 5.5+ (buggy) and good |
+support JavaScript 1.5. |
+</P> |
+ <P> |
+The term "javascript" is used as a common name for all dialects of ECMAScript. |
+ </P> |
+ </CONTENT> |
+ <CONTENT TITLE="What is JScript?" ID="jScript" NUMID="2_7"> |
+ <P> |
+JScript is Microsoft's implementation of ECMAScript. |
+ </P> |
+ <P> |
+Questions that are specific to Microsoft's JScript may also |
+be appropriately asked at: |
+<NEWSGROUP>microsoft.public.scripting.jscript</NEWSGROUP>. |
+ </P> |
+ |
+ </CONTENT> |
+ <CONTENT TITLE="What is the Document Object Model (DOM)?" ID="dom" NUMID="2_9"> |
+ <P> |
+The <DFN>Document Object Model</DFN> (DOM) is a interface-based model for <ICODE>Document</ICODE> |
+objects. The DOM allows scripts to dynamically access and update a |
+document's content, style, and event handlers. |
+</P> |
+<P> |
+The DOM is <EM>not</EM> part of the ECMAScript programming language. |
+</P> |
+<P> |
+Official DOM standards are defined by the World Wide Web Consortium. |
+Scriptable browsers also have <DFN>proprietary</DFN> DOM features (<URL |
+LINKTEXT="MSDN">http://msdn.microsoft.com/en-us/library/ms533050(VS.85).aspx</URL>, <URL |
+LINKTEXT="MDC">https://developer.mozilla.org/en/DOM_Client_Object_Cross-Reference</URL>), |
+such as <ICODE>document.writeln()</ICODE>. |
+ </P> |
+<P> |
+Also see the section on <URL LINKTEXT="DOM and Forms">#domRef</URL>. |
+<MOREINFO> |
+<URL LINKTEXT="c.l.js DOM Resources">#onlineResources</URL> |
+<URL LINKTEXT="W3C DOM FAQ">http://www.w3.org/DOM/faq.html</URL> |
+<URL LINKTEXT="W3C DOM ">http://www.w3.org/DOM/</URL> |
+<URL LINKTEXT="MDC: What is the DOM?">https://developer.mozilla.org/en/Gecko_DOM_Reference/Introduction#What_is_the_DOM.3F</URL> |
+</MOREINFO> |
+ </P> |
+ </CONTENT> |
+ <CONTENT TITLE="Internationalisation and Localisation in javascript" ID="localization" |
+ NUMID="2_10"> |
+ <P> |
+<DFN>Internationalisation</DFN> means using one form which is everywhere both |
+acceptable and understood. Any international standard not supported by |
+default can be coded for. |
+ </P> |
+ <P> |
+For example, there is an International Standard for numeric Gregorian |
+date format; but none for decimal and thousands separators. |
+ </P> |
+ <P> |
+<DFN>Localisation</DFN> is the process of adapting software for a specific region |
+or language by adding locale-specific components and translating text. It |
+cannot work well in general, because it requires a knowledge of all |
+preferences and the ability to choose the right one, in an environment |
+where many systems are inappropriately set anyway. |
+ </P> |
+ <P> |
+ECMAScript has a few <DFN>localisation</DFN> features. The various |
+<ICODE>toString()</ICODE> methods are all implementation dependent, |
+but tend to use either UK or US settings (not necessarily correctly). |
+ECMAScript Ed. 3 introduced some capabilities, including the |
+<ICODE>toLocaleString()</ICODE>method which should create a string |
+based on the host's locale. |
+ </P> |
+<P> |
+ECMAScript 5th Edition introduces limited ISO 8601 capabilities with |
+<ICODE>Date.prototype.toISOString()</ICODE> and new behavior for <ICODE>Date.parse()</ICODE>. |
+</P> |
+ </CONTENT> |
+ <CONTENT TITLE="What does the future hold for ECMAScript?" ID="futureEcmaScript" NUMID="2_12"> |
+ <P> |
+The 5th edition of ECMAScript was approved on 2009-12-04. There is some |
+support in implementations released before approval date (JScript 5.8, |
+JavaScript 1.8, JavaScriptCore). |
+http://www.ecma-international.org/publications/standards/Ecma-262.htm |
+<MOREINFO> |
+<URL>http://www.ecma-international.org/publications/standards/Ecma-262.htm</URL> |
+</MOREINFO> |
+</P> |
+ </CONTENT> |
+ </CONTENT> |
+ <CONTENT TITLE="Javascript Resources" ID="ecmascriptResources" NUMID="3"> |
+ <CONTENT TITLE="What books are recommended for javascript?" ID="books" NUMID="3_1"> |
+ <P> |
+Most javascript books have been found to contain so many technical |
+errors that consensus recommendations have not emerged from the group. |
+ </P> |
+ <P> |
+The following books have been considered to have value by some |
+individuals on c.l.js. The reviews of these books are provided: |
+ </P> |
+<LIST TYPE="UL"> |
+<LI><EM>&quot;JavaScript: The Definitive Guide,&quot;</EM> 5th Edition, by David Flanagan |
+ <UL> |
+ <LI>Published: 2006-08</LI> |
+ <LI>Pages: 1018</LI> |
+ <LI>Errata: <URL>http://oreilly.com/catalog/9780596101992/errata/</URL></LI> |
+ <LI>Discussed in: |
+ <UL> |
+ <LI> |
+ <URL LINKTEXT="FAQ Update 9.85 Dated 2007-08-31" |
+ >http://groups.google.com/group/comp.lang.javascript/browse_thread/thread/7283898f77fd2a66/9252aa024e058dea#c5f145ae807c918e</URL> |
+ </LI> |
+ </UL> |
+ </LI> |
+ </UL> |
+</LI> |
+ <LI> |
+ <EM>"JavaScript, The Good Parts,"</EM> 1st Edition, by Douglas Crockford |
+ <UL> |
+ <LI>Published: 2008-05</LI> |
+ <LI>Pages: 170</LI> |
+ <LI>Errata: <URL>http://oreilly.com/catalog/9780596517748/errata/</URL></LI> |
+ <LI>Discussed in: |
+ <UL> |
+ <LI> |
+ <URL LINKTEXT="Crockford's 'The Good Parts': a short review" |
+ >http://groups.google.com/group/comp.lang.javascript/browse_thread/thread/d084d2109f7b4ec7#</URL> |
+ </LI> |
+ <LI> |
+ <URL LINKTEXT="FunctionExpression's and memory consumptions" |
+ >http://groups.google.com/group/comp.lang.javascript/browse_thread/thread/db1e49ab113aa05c/3987eac87ad27966#3987eac87ad27966</URL> |
+ </LI> |
+ <LI> |
+ <URL LINKTEXT="FAQ Topic - What books are recommended for javascript? (2008-12-02)" |
+ >http://groups.google.com/group/comp.lang.javascript/browse_thread/thread/6a41f7835ee728de/da5ccfc65e2df64a#da5ccfc65e2df64a</URL> |
+ </LI> |
+ <LI> |
+ <URL LINKTEXT="Augmenting functions" |
+ >http://groups.google.com/group/comp.lang.javascript/browse_thread/thread/3a08fb741525ab6d/</URL> |
+ </LI> |
+ |
+ <LI> |
+ <URL LINKTEXT="Crockford's JavaScript, The Good Parts (a book review)." |
+ >http://groups.google.com/group/comp.lang.javascript/browse_thread/thread/bf26be6e63494ee2/acb733a1c35f6ce5#ee9e4ee29e658d5d</URL> |
+ </LI> |
+ <LI> |
+ <URL LINKTEXT="Closures Explained" |
+ >http://groups.google.com/group/comp.lang.javascript/browse_thread/thread/df602506ee48b400/e65e00f5cad07676#e65e00f5cad07676</URL> |
+ </LI> |
+ <LI> |
+ <URL LINKTEXT="Javascript library development" |
+ >http://groups.google.com/group/comp.lang.javascript/browse_thread/thread/acadf1b22b219433/4f69a95607d0b3ae#4f69a95607d0b3ae</URL> |
+ </LI> |
+ </UL> |
+ </LI> |
+ </UL> |
+ </LI> |
+</LIST> |
+ |
+ </CONTENT> |
+ <CONTENT TITLE="What online resources are available?" ID="onlineResources" NUMID="3_2"> |
+ |
+ <LIST TITLE="ECMAScript" TYPE="DL" ID="ecmaResources"> |
+ <DT> |
+The Official ECMAScript Specification |
+ </DT> |
+ <DD> |
+<URL>[ECMA-262] http://www.ecma-international.org/publications/standards/Ecma-262-arch.htm</URL> |
+ </DD> |
+ |
+ <DT> |
+[ISO16262] ISO/IEC 16262, Second Edition 2002-06-01 : ISO Standard matching |
+ECMA-262 3rd Edition, with corrections. |
+ </DT> |
+ <DD> |
+ <URL>http://standards.iso.org/ittf/PubliclyAvailableStandards/c033835_ISO_IEC_16262_2002(E).zip</URL> |
+ </DD> |
+ |
+ <DT> |
+ [MS-ES3]: Internet Explorer ECMA-262 ECMAScript Language Specification Standards Support |
+ </DT> |
+ <DD> |
+ <URL>http://msdn.microsoft.com/en-us/library/ff520996%28VS.85%29.aspx</URL> |
+ </DD> |
+ <DD><URL>res/%5BMS-ES3%5D.pdf</URL> (local alias)</DD> |
+ |
+ <DT> |
+ [MS-ES3EX]: Microsoft JScript Extensions to the ECMAScript Language Specification Third Edition |
+ </DT> |
+ <DD> |
+ <URL>http://msdn.microsoft.com/en-us/library/ff521046%28VS.85%29.aspx</URL> |
+ </DD> |
+ <DD><URL>res/%5BMS-ES3EX%5D.pdf</URL> (local alias)</DD> |
+ |
+ <DT>ECMAScript on Wikipedia |
+ </DT> |
+ <DD> |
+<URL>http://en.wikipedia.org/wiki/ECMAScript</URL> |
+ </DD> |
+ </LIST> |
+ |
+ <LIST TITLE="W3C DOM" TYPE="DL" ID="domResources"> |
+ <DT> |
+DOM Level 1 ECMAScript Binding |
+ </DT> |
+ <DD> |
+<URL>http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html</URL> |
+ </DD> |
+ <DT> |
+DOM Level 2 ECMAScript Binding |
+ </DT> |
+ <DD> |
+<URL>http://www.w3.org/TR/DOM-Level-2-HTML/ecma-script-binding.html</URL> |
+ </DD> |
+ <DT> |
+DOM Level 2 Events |
+ </DT> |
+ <DD> |
+<URL>http://www.w3.org/TR/DOM-Level-2-Events/events.html</URL> |
+ </DD> |
+ |
+ <DT> |
+DOM Level 2 Style |
+ </DT> |
+ <DD> |
+<URL>http://www.w3.org/TR/DOM-Level-2-Style/</URL> |
+ </DD> |
+ |
+ <DT> |
+DOM Level 3 ECMAScript Binding |
+ </DT> |
+ <DD> |
+<URL>http://www.w3.org/TR/DOM-Level-3-Core/ecma-script-binding.html</URL> |
+ </DD> |
+ </LIST> |
+ |
+ <LIST TITLE="Browser Documentation" TYPE="DL" ID="browserResources"> |
+ <DT> |
+Mozilla |
+ </DT> |
+ <DD>JavaScript: |
+<URL>http://developer.mozilla.org/en/docs/JavaScript</URL> |
+ </DD> |
+ <DD>Gecko DOM Reference: |
+<URL>http://developer.mozilla.org/en/docs/Gecko_DOM_Reference</URL> |
+ </DD> |
+ <DT> |
+Microsoft |
+ </DT> |
+ <DD>HTML and DHTML Reference: |
+<URL>http://msdn.microsoft.com/en-us/library/ms533050.aspx</URL> |
+ </DD> |
+ |
+ <DD>JScript Language Reference: |
+<URL>http://msdn.microsoft.com/en-us/library/hbxc2t98%28VS.85%29.aspx</URL> |
+ </DD> |
+ <DD>Scripting: |
+<URL>http://msdn.microsoft.com/en-us/library/ms950396.aspx</URL> |
+ </DD> |
+ |
+ <DT> |
+Opera |
+ </DT> |
+ <DD>Web Specifications Support: |
+<URL>http://www.opera.com/docs/specs/#ecmascript</URL> |
+ </DD> |
+ |
+ <DD>JavaScript Support: |
+<URL>http://www.opera.com/docs/specs/js/</URL> |
+ </DD> |
+ |
+ <DD>ECMAScript Support: |
+<URL>http://www.opera.com/docs/specs/js/ecma</URL> |
+ </DD> |
+ |
+ <DT> |
+BlackBerry JavaScript Reference |
+ </DT> |
+ <DD> |
+<URL>http://docs.blackberry.com/en/developers/deliverables/11849/</URL> |
+ </DD> |
+ |
+ <DT> |
+ICab InScript |
+ </DT> |
+ <DD> |
+<URL>http://www.muchsoft.com/inscript/</URL> |
+ </DD> |
+ |
+ <DT>Apple Safari</DT> |
+ <DD>Web Content Guide: |
+<URL |
+>http://developer.apple.com/safari/library/documentation/AppleApplications/Reference/SafariWebContent/Introduction/Introduction.html</URL> |
+ </DD> |
+ |
+ <DT> |
+Webkit |
+ </DT> |
+ <DD>Project Site: <URL>http://webkit.org/</URL></DD> |
+ <DD> |
+ Wiki: <URL>http://trac.webkit.org/wiki</URL> |
+ </DD> |
+ <DD>DOM Reference: |
+<URL |
+>http://developer.apple.com/Mac/library/documentation/AppleApplications/Reference/WebKitDOMRef/index.html#//apple_ref/doc/uid/TP40006089</URL> |
+ </DD> |
+ <DT> |
+Netscape 4 Client-Side JavaScript Reference |
+ </DT> |
+ <DD> |
+<URL>http://docs.sun.com/source/816-6408-10/</URL> |
+ </DD> |
+ |
+ <DT> |
+Archived documentation for MSIE 3.x |
+ </DT> |
+ <DD> |
+<URL>http://members.tripod.com/%7Ehousten/download/</URL> |
+ </DD> |
+ </LIST> |
+ |
+ <LIST TITLE="Standalone ECMAScript Implementations" TYPE="DL" ID="standaloneImplementations"> |
+ <DT> |
+Rhino: An open-source implementation of JavaScript written in Java |
+ </DT> |
+ <DD> |
+<URL>http://www.mozilla.org/rhino/</URL> |
+ </DD> |
+ <DT> |
+Besen IDE: ECMAScript Edition 5 with IDE |
+ </DT> |
+ <DD> |
+<URL>http://besen.sourceforge.net/</URL> |
+ </DD> |
+ <DT> |
+V8: Google's open source JavaScript engine |
+ </DT> |
+ <DD> |
+<URL>http://code.google.com/p/v8/</URL> |
+ </DD> |
+ <DT> |
+SpiderMonkey: Mozilla's C implementation of JavaScript |
+ </DT> |
+ <DD> |
+<URL>http://www.mozilla.org/js/spidermonkey/</URL> |
+ </DD> |
+ <DT> |
+Digital Mars DMD Script, console and MS Active Script implementation of ECMAScript |
+ </DT> |
+ <DD> |
+<URL>http://www.digitalmars.com/dscript/</URL> |
+ </DD> |
+ </LIST> |
+ |
+ <LIST TITLE="Other ECMAScript Implementations" TYPE="DL" ID="nonBrowserResources"> |
+ <DT> |
+Developing Dashboard Widgets: Apple Developer Connection |
+ </DT> |
+ <DD> |
+<URL>http://developer.apple.com/macosx/dashboard.html</URL> |
+ </DD> |
+ <DT> |
+Whitebeam Apache Module: Server Side JavaScript in Apache |
+ </DT> |
+ <DD> |
+<URL>http://www.whitebeam.org/</URL> |
+ </DD> |
+ </LIST> |
+ </CONTENT> |
+ <CONTENT TITLE="Javascript Libraries" ID="libraryResources"> |
+ <P> |
+No javascript libraries are endorsed by this group. If you want help |
+with using a library, visit that library's discussion group instead. |
+ </P> |
+</CONTENT> |
+ |
+ </CONTENT> |
+ <CONTENT TITLE="Functions" ID="functions"> |
+ <CONTENT TITLE="What is (function(){ /*...*/ })() ?" ID="scope"> |
+<P> |
+This is an anonymous <DFN>FunctionExpression</DFN> that is called |
+immediately after creation. |
+</P> |
+<P> |
+Variables declared inside a function are not accessible from |
+outside the function. This can be useful, for example, to hide |
+implementation details or to avoid polluting the global scope. |
+<MOREINFO> |
+<URL>http://yura.thinkweb2.com/named-function-expressions/</URL> |
+<URL>notes/closures/</URL> |
+<URL>http://dmitrysoshnikov.com/ecmascript/chapter-5-functions/#question-about-surrounding-parentheses</URL> |
+</MOREINFO> |
+</P> |
+</CONTENT> |
+<CONTENT TITLE="What is a function statement?" ID="functionStatement"> |
+<P> |
+The term <DFN>function statement</DFN> has been widely and wrongly used to |
+describe a <ICODE>FunctionDeclaration</ICODE>. This is misleading because in ECMAScript, |
+a <ICODE>FunctionDeclaration</ICODE> is not a <DFN>Statement</DFN>; there are places in a program |
+where a <DFN>Statement</DFN> is permitted but a <ICODE>FunctionDeclaration</ICODE> is not. To add |
+to this confusion, some implementations, notably Mozillas', provide a |
+syntax extension called <DFN>function statement</DFN>. This is allowed under |
+section 16 of ECMA-262, Editions 3 and 5. |
+</P> |
+<P> |
+Example of nonstandard <DFN>function statement</DFN>: |
+<CODE> |
+// Nonstandard syntax, found in GMail source code. DO NOT USE. |
+try { |
+ // FunctionDeclaration not allowed in Block. |
+ function Fze(b,a){return b.unselectable=a} |
+ /*...*/ |
+} catch(e) { _DumpException(e) } |
+</CODE> |
+</P> |
+ |
+<P> |
+Code that uses <DFN>function statement</DFN> has three known interpretations. Some |
+implementations process <ICODE>Fze</ICODE> as a <DFN>Statement</DFN>, in order. Others, including |
+JScript, evaluate <ICODE>Fze</ICODE> upon entering the execution context that it |
+appears in. Yet others, notably DMDScript and default configuration of BESEN, |
+throw a <ICODE>SyntaxError</ICODE>. |
+</P> |
+<P> |
+For consistent behavior across implementations, <EM>do not use function |
+statement</EM>; use either <ICODE>FunctionExpression</ICODE> or <ICODE>FunctionDeclaration</ICODE> instead. |
+</P> |
+<P> |
+Example of <ICODE>FunctionExpression</ICODE> (valid): |
+<CODE> |
+var Fze; |
+try { |
+ Fze = function(b,a){return b.unselectable=a}; |
+ /*...*/ |
+} catch(e) { _DumpException(e) } |
+</CODE> |
+Example of <ICODE>FunctionDeclaration</ICODE> (valid): |
+<CODE> |
+// Program code |
+function aa(b,a){return b.unselectable=a} |
+</CODE> |
+ |
+</P> |
+ |
+<P> |
+<!-- |
+Notable examples of the misuse of the term "function statement" |
+can be seen in David Flanagan's "JavaScript: The Definitive Guide", |
+Douglas Crockford's "JavaScript: The Good Parts", MDC documentation, |
+JSLint error messages. |
+--> |
+<MOREINFO> |
+<URL>example/functionStatement.html</URL> |
+<URL>https://mail.mozilla.org/pipermail/es-discuss/2008-February/005314.html</URL> |
+<URL>http://groups.google.com/group/comp.lang.javascript/msg/aa9a32d0c6ae0342</URL> |
+<URL>http://groups.google.com/group/comp.lang.javascript/msg/3987eac87ad27966</URL> |
+<URL>http://nanto.asablo.jp/blog/2005/12/10/172622</URL> (Article in Japanese) |
+</MOREINFO> |
+</P> |
+</CONTENT> |
+</CONTENT> |
+ <CONTENT TITLE="Dates" ID="dates"> |
+<P> |
+ISO 8601 defines date and time formats. Some benefits include: |
+</P> |
+<LIST TYPE="UL"> |
+<LI>language-independent and unambiguous world-wide</LI> |
+<LI>sortable with a trivial string comparison</LI> |
+<LI>easily readable and writable by software</LI> |
+<LI>compatible with standards ISO 9075 and <URL LINKTEXT="rfc 3339">http://www.ietf.org/rfc/rfc3339.txt</URL></LI> |
+</LIST> |
+<P> |
+The ISO Extended format for common date is <ICODE>YYYY-MM-DD</ICODE>, and for time is |
+<ICODE>hh:mm:ss</ICODE>. |
+</P> |
+ |
+<P> |
+For an event with an offset from UTC, use <ICODE>YYYY-MM-DDThh:mm:ss&#177;hh:mm</ICODE>. |
+</P> |
+<P> |
+Never use a local date/time format for a non-local event. Instead, use |
+UTC, as in <ICODE>YYYY-MM-DDThh:mm:ssZ</ICODE> (<ICODE>Z</ICODE> is the only letter suffix). |
+</P> |
+<P> |
+The <ICODE>T</ICODE> can be omitted where that would not cause ambiguity. For |
+rfc 3339 compliance, it may be replaced by a space and for SQL, |
+it <EM>must</EM> be replaced by a single space. |
+</P> |
+<P> |
+Year <ICODE>0000</ICODE> is unrecognized by some formats (XML Schema, <ICODE>xs:date</ICODE>). |
+ <MOREINFO> |
+ <URL LINKTEXT="ECMA-262 Date.prototype, s. 15.9">#onlineResources</URL> |
+ <URL LINKTEXT="A summary of the international standard date and time notation, by Markus Kuhn" |
+>http://www.cl.cam.ac.uk/~mgk25/iso-time.html</URL> |
+ <URL>http://en.wikipedia.org/wiki/ISO_8601</URL> |
+ <URL LINKTEXT="ISO 8601:2004(E)">res/ISO_8601-2004_E.pdf</URL> |
+ <URL LINKTEXT="W3C QA Tip: Use international date format (ISO)">http://www.w3.org/QA/Tips/iso-date</URL> |
+ <URL LINKTEXT="RFC 3339, Date and Time on the Internet: Timestamps |
+">http://www.ietf.org/rfc/rfc3339.txt</URL> |
+ <URL>http://www.w3.org/TR/xmlschema-2/#dateTime</URL> |
+ </MOREINFO> |
+</P> |
+ |
+ <CONTENT TITLE="How do I format a Date object with javascript?" |
+ ID="formatDate" NUMID="4_30"> |
+ <P> |
+A local <ICODE>Date</ICODE> object where <ICODE>0 &lt;= year &lt;= 9999</ICODE> can be |
+formatted to a common ISO 8601 format <ICODE>YYYY-MM-DD</ICODE> with:- |
+ <CODE> |
+ /** Formats a Date to YYYY-MM-DD (local time), compatible with both |
+ * ISO 8601 and ISO/IEC 9075-2:2003 (E) (SQL 'date' type). |
+ * @param {Date} dateInRange year 0000 to 9999. |
+ * @throws {RangeError} if the year is not in range |
+ */ |
+ function formatDate(dateInRange) { |
+ var year = dateInRange.getFullYear(), |
+ isInRange = year &gt;= 0 &amp;&amp; year &lt;= 9999, yyyy, mm, dd; |
+ if(!isInRange) { |
+ throw RangeError("formatDate: year must be 0000-9999"); |
+ } |
+ yyyy = ("000" + year).slice(-4); |
+ mm = ("0" + (dateInRange.getMonth() + 1)).slice(-2); |
+ dd = ("0" + (dateInRange.getDate())).slice(-2); |
+ return yyyy + "-" + mm + "-" + dd; |
+ } |
+ </CODE> |
+ <MOREINFO> |
+ <URL>http://www.merlyn.demon.co.uk/js-date9.htm</URL> |
+ </MOREINFO> |
+ </P> |
+</CONTENT> |
+ <CONTENT TITLE="How can I create a Date object from a String?" ID="parseDate"> |
+ <P> |
+An Extended ISO 8601 local Date format <ICODE>YYYY-MM-DD</ICODE> can be parsed to a |
+Date with the following:- |
+<CODE> |
+ /**Parses string formatted as YYYY-MM-DD to a Date object. |
+ * If the supplied string does not match the format, an |
+ * invalid Date (value NaN) is returned. |
+ * @param {string} dateStringInRange format YYYY-MM-DD, with year in |
+ * range of 0000-9999, inclusive. |
+ * @return {Date} Date object representing the string. |
+ */ |
+ function parseISO8601(dateStringInRange) { |
+ var isoExp = /^\s*(\d{4})-(\d\d)-(\d\d)\s*$/, |
+ date = new Date(NaN), month, |
+ parts = isoExp.exec(dateStringInRange); |
+ |
+ if(parts) { |
+ month = +parts[2]; |
+ date.setFullYear(parts[1], month - 1, parts[3]); |
+ if(month != date.getMonth() + 1) { |
+ date.setTime(NaN); |
+ } |
+ } |
+ return date; |
+ }</CODE> |
+</P> |
+ </CONTENT> |
+ </CONTENT> |
+ |
+ <CONTENT TITLE="Numbers" ID="numbers"> |
+ <CONTENT TITLE="How do I format a Number as a String with exactly 2 decimal places?" |
+ ID="formatNumber" NUMID="4_6"> |
+ <P> |
+When formatting money for example, to format 6.57634 to 6.58, 6.7 to |
+6.50, and 6 to 6.00? |
+ </P> |
+ <P> |
+Rounding of x.xx5 is unreliable, as most numbers are not represented |
+exactly. See also: |
+<URL LINKTEXT="Why does simple decimal arithmetic give strange results?">#binaryNumbers</URL> |
+ </P> |
+ <P> |
+The statement <ICODE>n = Math.round(n * 100)/100</ICODE> converts <ICODE>n</ICODE> to a <ICODE>Number</ICODE> value |
+close to a multiple of <ICODE>0.01</ICODE>. However, there are some problems. |
+Converting the number to a string <ICODE>(n + "")</ICODE>, does not give |
+trailing zeroes. Rounding numbers that are very close to <ICODE>x.5</ICODE>, for example, |
+<ICODE>Math.round(0.49999999999999992)</ICODE> results <ICODE>1</ICODE>. |
+ </P> |
+ <P> |
+ECMA-262 3rd Edition introduced <ICODE>Number.prototype.toFixed</ICODE>. |
+There are bugs in JScript 5.8 and below with certain numbers, for example |
+<ICODE>0.007.toFixed(2)</ICODE> incorrectly results <ICODE>0.00</ICODE>. |
+ </P> |
+ <P> |
+ <CODE> |
+var numberToFixed = |
+(function() { |
+ return toFixedString; |
+ |
+ function toFixedString(n, digits) { |
+ var unsigned = toUnsignedString(Math.abs(n), digits); |
+ return (n &lt; 0 ? "-" : "") + unsigned; |
+ } |
+ |
+ function toUnsignedString(m, digits) { |
+ var t, s = Math.round(m * Math.pow(10, digits)) + "", |
+ start, end; |
+ if (/\D/.test(s)) { |
+ return "" + m; |
+ } |
+ s = padLeft(s, 1 + digits, "0"); |
+ start = s.substring(0, t = (s.length - digits)); |
+ end = s.substring(t); |
+ if(end) { |
+ end = "." + end; |
+ } |
+ return start + end; // avoid "0." |
+ } |
+ /** |
+ * @param {string} input: input value converted to string. |
+ * @param {number} size: desired length of output. |
+ * @param {string} ch: single character to prefix to s. |
+ */ |
+ function padLeft(input, size, ch) { |
+ var s = input + ""; |
+ while(s.length &lt; size) { |
+ s = ch + s; |
+ } |
+ return s; |
+ } |
+})(); |
+ |
+// Test results |
+document.writeln([ |
+ "numberToFixed(9e-3, 12) =&gt; " + numberToFixed(9e-3, 12), |
+ "numberToFixed(1.255, 2) =&gt; " + numberToFixed(1.255, 2), |
+ "numberToFixed(1.355, 2) =&gt; " + numberToFixed(1.355, 2), |
+ "numberToFixed(0.1255, 3) =&gt; " + numberToFixed(0.1255, 3), |
+ "numberToFixed(0.07, 2) =&gt; " + numberToFixed(0.07, 2), |
+ "numberToFixed(0.0000000006, 1) =&gt; " + numberToFixed(0.0000000006, 1), |
+ "numberToFixed(0.0000000006, 0) =&gt; " + numberToFixed(0.0000000006, 0) |
+].join("\n")); |
+</CODE> |
+ <MOREINFO> |
+ <URL>http://www.merlyn.demon.co.uk/js-round.htm</URL> |
+ <URL>http://msdn.microsoft.com/en-us/library/sstyff0z%28VS.85%29.aspx</URL> |
+ </MOREINFO> |
+ </P> |
+ </CONTENT> |
+ <CONTENT TITLE="Why does simple decimal arithmetic give strange results?" |
+ ID="binaryNumbers" NUMID="4_7"> |
+ <P> |
+For example, <ICODE>5 * 1.015</ICODE> does not give exactly |
+<ICODE>5.075</ICODE> and <ICODE>0.06+0.01</ICODE> does |
+not give exactly <ICODE>0.07</ICODE> in javascript. |
+ </P> |
+ <P> |
+ECMAScript numbers are represented in binary as IEEE-754 (IEC 559) |
+Doubles, with a resolution of 53 bits, giving an accuracy of |
+15-16 decimal digits; integers up to just over <ICODE>9e15</ICODE> are |
+precise, but few decimal fractions are. Given this, arithmetic |
+is as exact as possible, but no more. Operations on integers |
+are exact if the true result and all intermediates are integers |
+within that range. |
+ </P> |
+ <P> |
+In particular, non-integer results should not normally be |
+compared for equality; and non-integer computed results |
+commonly need rounding; see <URL |
+LINKTEXT="How do I format a Number as a String with exactly 2 decimal places?" |
+>#formatNumber</URL> |
+ <MOREINFO> |
+ <URL>http://msdn.microsoft.com/en-us/library/7wkd9z69%28VS.85%29.aspx</URL> |
+ <URL>http://www.merlyn.demon.co.uk/js-misc0.htm#DW4</URL> |
+ </MOREINFO> |
+ </P> |
+ <P> |
+Otherwise, use <ICODE>Math.round</ICODE> on the results of expressions which |
+should be of integer value. |
+ </P> |
+ </CONTENT> |
+ <CONTENT TITLE="Why does K = parseInt('09') set K to 0?" ID="parseIntBase" NUMID="4_12"> |
+ <P> |
+Method <ICODE>parseInt</ICODE> generally needs a second parameter, <ICODE>radix</ICODE>, |
+for the base (from 2 to 36). |
+ </P> |
+ <P> |
+If <ICODE>radix</ICODE> is omitted, the base is determined by the contents of |
+the string. Any string beginning with <ICODE>'0x'</ICODE> or <ICODE>'0X'</ICODE> represents a |
+hexadecimal number. A string beginning with a leading 0 may be parsed as |
+octal (as if <ICODE>raxix</ICODE> were 8), in ECMA-262 Ed 3 (octal digits are <ICODE>0-7</ICODE>). |
+If string <ICODE>'09'</ICODE> is converted to <ICODE>0</ICODE>. |
+ </P> |
+ <P> |
+To force use of a particular base, use the <ICODE>radix</ICODE> |
+parameter: <ICODE>parseInt("09", base)</ICODE>. |
+ |
+ <!-- [omit] |
+ If base 10 is desired, |
+ the unary <ICODE>+</ICODE> operator can be an option. Example: |
+ <ICODE> |
+var s = '-09.1'; // Input string. |
+var j = +s; // Convert to number. Result: -9.1 |
+var n = j|0; // Chop off decimal (convert ToInt32). Result: -9 |
+</ICODE> |
+ [/omit] --> |
+ </P> |
+ <P> |
+ <MOREINFO> |
+ <URL>http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Functions/parseInt</URL> |
+ <URL>http://msdn.microsoft.com/en-us/library/x53yedee%28VS.85%29.aspx</URL> |
+ <URL>http://docs.sun.com/source/816-6408-10/toplev.htm#1064173</URL> |
+ <URL>notes/type-conversion/#tcPrIntRx</URL> |
+ </MOREINFO> |
+ </P> |
+ </CONTENT> |
+ <CONTENT TITLE="Why does 1+1 equal 11? or How do I convert a string to a number?" ID="typeConvert"> |
+ <P> |
+Variables are not typed; their values are. The conversion between a |
+string and a number happens automatically. |
+</P> |
+<P> |
+The addition operator (<ICODE>+</ICODE>) performs concatenation if either operand is a |
+string, thus <ICODE>"1" + 1</ICODE> results <ICODE>"11"</ICODE>. To perform addition, you might need |
+to first convert the string to a number. For example <ICODE>+varname</ICODE> or |
+<ICODE>Number(varname)</ICODE> or <ICODE>parseInt(varname, 10)</ICODE> or |
+<ICODE>parseFloat(varname)</ICODE>. Form control values are strings, as is the result |
+from a <ICODE>prompt</ICODE> dialog. Convert these to numbers before performing |
+addition: <ICODE>+'1' + 1</ICODE> results <ICODE>2</ICODE>. |
+ <MOREINFO> |
+Additional Notes: <URL>notes/type-conversion/</URL> |
+ <URL>http://msdn.microsoft.com/en-us/library/67defydd%28VS.85%29.aspx</URL> |
+ </MOREINFO> |
+ </P> |
+ </CONTENT> |
+ <CONTENT TITLE="How do I generate a random integer from 1 to n?" |
+ ID="randomNumber" NUMID="4_22"> |
+ <P> |
+ <ICODE>Math.random()</ICODE> returns a value <ICODE>R</ICODE> such that <ICODE>0 &lt;= R &lt; 1.0</ICODE>; therefore: |
+ <CODE> |
+ // positive integer expected |
+ function getRandomNumber(n) { |
+ return Math.floor(n * Math.random()); |
+ } |
+</CODE> |
+- gives an evenly distributed random integer in the range from |
+ <ICODE>0</ICODE> to <ICODE>n - 1</ICODE> inclusive; use <ICODE>getRandomNumber(n)+1</ICODE> for <ICODE>1</ICODE> to <ICODE>n</ICODE>. |
+ <MOREINFO> |
+ <URL>http://msdn.microsoft.com/en-us/library/41336409%28VS.85%29.aspx</URL> |
+ <URL>http://docs.sun.com/source/816-6408-10/math.htm</URL> |
+How to Deal and Shuffle, see in: <URL>http://www.merlyn.demon.co.uk/js-randm.htm</URL> |
+ </MOREINFO> |
+ </P> |
+ </CONTENT> |
+ </CONTENT> |
+ |
+ <CONTENT TITLE="Objects" ID="objects"> |
+ <CONTENT TITLE="What is a native object?" ID="nativeObject"> |
+<P> |
+A <DFN>native object</DFN> is any object whose semantics are fully defined by |
+ECMA-262. |
+</P> |
+<P> |
+Some <DFN>native objects</DFN> are <DFN>built-in</DFN>; others, such as <DFN>user-defined</DFN> objects, |
+may be constructed during the execution of an ECMAScript program. |
+</P> |
+<P> |
+Example: |
+<CODE> |
+// Native built-in objects: |
+var m = Math, // Built-in Math object. |
+ slice = Array.prototype.slice, // Built-in native method. |
+ o = {}, // Native user-defined object. |
+ f = function(){}, // Native user-defined function. |
+ d = new Date(), |
+ a = [], |
+ e = new Error("My Message."); |
+ </CODE> |
+See also: |
+<MOREINFO> |
+<URL>http://dmitrysoshnikov.com/ecmascript/chapter-7-2-oop-ecmascript-implementation/</URL> |
+</MOREINFO> |
+</P> |
+ </CONTENT> |
+ <CONTENT TITLE="What is a built-in object?" ID="builtInObject"> |
+ <P> |
+ A <DFN>built-in</DFN> object is any object supplied by an ECMAScript |
+ implementation, independent of the host environment, that is present |
+ at the start of the execution of an ECMAScript program. |
+ </P> |
+ <P> |
+ECMA-262 3rd Edition defines the following <DFN>built-in</DFN> objects: |
+</P> |
+<LIST TYPE="DL" ID="builtInsList"> |
+ <DT>Objects</DT> |
+ <DD><EM>global</EM>, Math</DD> |
+ |
+ <DT>Constructors</DT> |
+ <DD>Object, Function, Array, String, Boolean, Number, Date, RegExp</DD> |
+ |
+ <DT>Errors</DT> |
+ <DD>Error, Date, EvalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError</DD> |
+ |
+ <DT>Functions</DT> |
+ <DD>eval, parseInt, parseFloat, isNaN, isFinite, decodeURI, |
+ decodeURIComponent, encodeURI, encodeURIComponent</DD> |
+ </LIST> |
+ <P> |
+ECMA-262 Edition 5 defines also the built-in object <ICODE>JSON</ICODE>. |
+</P> |
+<P> |
+Nonstandard <DFN>built-in</DFN> objects may include <ICODE>RuntimeObject</ICODE>, |
+<ICODE>String.prototype.link</ICODE>, <ICODE>CollectGarbage</ICODE>, and more. |
+</P> |
+</CONTENT> |
+ |
+ <CONTENT TITLE="What is a host object?" ID="hostObject" NUMID="2_8"> |
+ <P> |
+A <DFN>host object</DFN> is any object supplied by the host environment to |
+complete the execution environment of ECMAScript. |
+</P> |
+<P> |
+A <DFN>host object</DFN> is not part of the ECMAScript implementation, but is |
+exposed to the ECMAScript implementation. |
+</P> |
+<P> |
+A <DFN>host object</DFN> may be implemented as a native ECMAScript object, however |
+this is not required. For example, Internet Explorer implements many |
+scriptable DOM objects as ActiveX Objects, often resulting in unexpected errors. |
+</P> |
+<P> |
+Availability and behavior of a host object depends on the host environment. |
+</P> |
+<P> |
+For example, in a browser, <ICODE>XMLHttpRequest</ICODE> might be available, with or |
+without standard or proprietary features or events. Windows Script Host object model |
+has the <ICODE>WScript</ICODE> object available. |
+</P> |
+<P> |
+ For information on a particular host object, consult the pertinent |
+ documentation available for the implementation(s). For web browsers, |
+ this usually includes the w3c specifications as well as documentation |
+ for that browser. |
+ See also: |
+ |
+<MOREINFO> |
+<URL>notes/code-guidelines/#hostObjects</URL> |
+<URL>http://peter.michaux.ca/articles/feature-detection-state-of-the-art-browser-scripting</URL> |
+</MOREINFO> |
+</P> |
+ </CONTENT> |
+ <CONTENT TITLE="When should I use eval?" ID="eval" NUMID="4_40"> |
+ <P> |
+The <ICODE>eval</ICODE> function should <EM>only</EM> be used when it is necessary to |
+evaluate a string supplied or composed at run-time; the string |
+can be anything from a simple (but unpredictable) expression such |
+as <ICODE>"12 * 2.54"</ICODE> to a substantial piece of javascript code. |
+</P> |
+<P> |
+When <ICODE>eval( '{"key" : 42}' )</ICODE> is called, <ICODE>{</ICODE> is interpreted as a block of |
+code instead of an object literal. Hence, the Grouping Operator (parentheses) |
+is used to force <ICODE>eval</ICODE> to interpret the JSON as an object literal: |
+<ICODE>eval( '({"key" : 42})' );</ICODE>. |
+ <MOREINFO> |
+ <URL>http://json.org/</URL> |
+ <URL LINKTEXT="How do I access a property of an object using a string?" |
+ >#propertyAccessAgain</URL> |
+ <URL>notes/square-brackets/</URL> |
+ </MOREINFO> |
+ </P> |
+ </CONTENT> |
+ <CONTENT TITLE="How do I access a property of an object using a string?" |
+ ID="propertyAccessAgain" NUMID="4_39"> |
+ <P> |
+There are two ways to access properties: dot notation and square bracket |
+notation. What you are looking for is the square bracket notation in |
+which the dot, and the identifier to its right, are replaced with a set |
+of square brackets containing a string. The value of the string matches |
+the identifier. For example:- |
+<CODE> |
+ //dot notation |
+ var bodyElement = document.body; |
+ |
+ //square bracket notation, using an expression |
+ var bodyElement = document[&quot;bo&quot;+&quot;dy&quot;];</CODE> |
+ <MOREINFO> |
+ <URL>notes/square-brackets/</URL> |
+ </MOREINFO> |
+ </P> |
+ </CONTENT> |
+ </CONTENT> |
+ <CONTENT TITLE="Strings and RegExp" ID="strings"> |
+ <CONTENT TITLE="How do I trim whitespace?" ID="trimString" NUMID="4_16"> |
+ <P> |
+ECMAScript 5 defines <ICODE>String.prototype.trim</ICODE>. Where not supported, |
+it can be added as a function that uses a <DFN>regular expression</DFN>: |
+<CODE> |
+if(!String.prototype.trim) { |
+ String.prototype.trim = function() { |
+ return String(this).replace(/^\s+|\s+$/g, ""); |
+ }; |
+} |
+</CODE> |
+Implementations are inconsistent with <ICODE>\s</ICODE>. For example, |
+some implementations, notably JScript 5.8 and Safari 2, do not match <ICODE>\xA0</ICODE> |
+(no-break space), among others. |
+ </P> |
+ <P> |
+A more consistent approach would be to create a character class |
+that defines the characters to trim. |
+ </P> |
+ <P> |
+<MOREINFO> |
+<URL>https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/RegExp</URL> |
+<URL>http://thinkweb2.com/projects/prototype/whitespace-deviations/</URL> |
+<URL>https://developer.mozilla.org/en/Firefox_3.1_for_developers</URL> |
+<URL>http://docs.sun.com/source/816-6408-10/regexp.htm</URL> |
+<URL>http://msdn.microsoft.com/en-us/library/6wzad2b2%28VS.85%29.aspx</URL> |
+<URL>http://groups.google.com/group/comp.lang.javascript/browse_frm/thread/c7010139217600c3/31092c5eb99625d0?#31092c5eb99625d0</URL> |
+<URL>http://unicode.org/Public/UNIDATA/PropList.txt</URL> |
+</MOREINFO> |
+</P> |
+ </CONTENT> |
+ </CONTENT> |
+ |
+ <CONTENT TITLE="DOM and Forms" ID="domRef"> |
+ |
+ |
+ <CONTENT TITLE="How do I get the value of a form control?" |
+ ID="formControlAccess" NUMID="4_13"> |
+ <P> |
+In HTML documents, a form may be referred to as a property of the |
+<ICODE>document.forms</ICODE> collection, either by its ordinal index or by name |
+(if the <ICODE>form</ICODE> has a name). A <ICODE>form</ICODE>'s controls may be similarly referenced |
+from its <ICODE>elements</ICODE> collection: |
+<CODE> |
+ var frm = document.forms[0]; |
+ var control = frm.elements[&quot;elementname&quot;]; |
+</CODE> |
+Once a reference to a control is obtained, its (string) <ICODE>value</ICODE> |
+property can be read:- |
+<CODE> |
+ var value = control.value; |
+ value = +control.value; //string to number. |
+</CODE> |
+Some exceptions would be: |
+</P> |
+<P> |
+First Exception: Where the control is a <ICODE>SELECT</ICODE> element, and |
+support for older browsers, such as NN4, is required: |
+<CODE> |
+ var value = control.options[control.selectedIndex].value; |
+</CODE> |
+Second Exception: Where several controls share the same name, |
+such as radio buttons. These are made available as collections |
+and require additional handling. For more information, see:- |
+<MOREINFO> |
+<URL>notes/form-access/</URL> |
+<URL LINKTEXT="Unsafe Names for HTML Form Controls">names/</URL> |
+</MOREINFO> |
+ </P> |
+ <P> |
+Third Exception: File inputs. Most current browsers do not allow |
+reading of <ICODE>type="file"</ICODE> input elements in a way that is useful. |
+ </P> |
+ </CONTENT> |
+ <CONTENT TITLE="My element is named myselect[], how do I access it?" |
+ ID="propertyAccess" NUMID="4_25"> |
+ <P> |
+Form controls with any &quot;illegal&quot; characters can be accessed with |
+<ICODE>formref.elements[&quot;myselect[]&quot;]</ICODE> - The bracket characters, |
+amongst others, are illegal in ID attributes and javascript |
+identifiers, so you should try to avoid them as browsers may |
+handle them incorrectly. |
+<MOREINFO> |
+<URL>http://msdn.microsoft.com/en-us/library/ms537449%28VS.85%29.aspx</URL> |
+<URL>https://developer.mozilla.org/en/DOM/form</URL> |
+<URL>notes/form-access/</URL> |
+</MOREINFO> |
+ </P> |
+ </CONTENT> |
+ <CONTENT TITLE="Why doesn't the global variable &quot;divId&quot; always refer to the element with id=&quot;divId&quot;?" |
+ ID="globalPollution" NUMID="4_41"> |
+ <P> |
+Microsoft introduced a shortcut that can be used to reference |
+elements which include an <ICODE>id</ICODE> attribute where the |
+<ICODE>id</ICODE> becomes a globally-accessible property. Some browsers reproduce |
+this behavior. Some, most notably Gecko-based browsers (Netscape and Mozilla), |
+do so only in "quirks" mode. The best approach is the <ICODE>document.getElementById</ICODE> |
+method, which is part of the W3C DOM standard and implemented |
+in modern browsers (including IE from version 5.0). So an |
+element with <ICODE>id=&quot;foo&quot;</ICODE> can be referenced |
+with:- |
+ <CODE> |
+ var el = document.getElementById(&quot;foo&quot;); |
+</CODE> |
+Note: make sure not to use the same <ICODE>id</ICODE> twice in the same document |
+and do not give an element a <ICODE>name</ICODE> that matches an <ICODE>id</ICODE> |
+of another in the same document or it will trigger bugs in MSIE &lt;= 7 with |
+<ICODE>document.getElementsByName</ICODE> and <ICODE>document.getElementById</ICODE>. |
+<MOREINFO> |
+<URL>https://developer.mozilla.org/en/Using_Web_Standards_in_your_Web_Pages/Using_the_W3C_DOM#Accessing_Elements_with_the_W3C_DOM |
+</URL> |
+<URL>faq_notes/faq_notes.html#FAQN4_41</URL> |
+</MOREINFO> |
+</P> |
+ </CONTENT> |
+ <CONTENT TITLE="How do I modify the content of the current page?" |
+ ID="updateContent" NUMID="4_15"> |
+ <P> |
+Using the non-standard but widely implemented |
+<ICODE>innerHTML</ICODE> property: |
+<ICODE>&lt;div id=&quot;anID&quot;&gt;Some Content&lt;/div&gt;</ICODE> with script: |
+ <CODE> |
+ document.getElementById(&quot;anID&quot;).innerHTML = |
+ &quot;Some &lt;em&gt;new&lt;/em&gt; Content&quot;; |
+</CODE> |
+Where <ICODE>&quot;anID&quot;</ICODE> is the (unique on the HTML page) |
+<ICODE>id</ICODE> attribute value of the element to modify. |
+ </P> |
+ <P> |
+All versions of Internet Explorer exhibit problems with innerHTML, including: |
+ </P> |
+ <LIST TYPE="UL"> |
+ <LI>Fails with FRAMESET, HEAD, HTML, STYLE, SELECT, |
+OBJECT, and all TABLE-related elements. |
+ </LI> |
+ <LI>Replaces consecutive whitespace characters with a single space.</LI> |
+ <LI>Changes attribute values and order of appearance.</LI> |
+ <LI>Removes quotations around attribute values.</LI> |
+ </LIST> |
+ <P> |
+If the new content is only text and does not need to replace existing HTML, |
+it is more efficient to modify the <ICODE>data</ICODE> property of a text node. |
+ <CODE> |
+ document.getElementById(&quot;anID&quot;).firstChild.data = &quot;Some new Text&quot;; |
+</CODE> |
+</P> |
+<P> |
+Compatibility Note: Implementations have been known to split long text |
+content among several adjacent text nodes, so replacing the data of the |
+first text node may not replace all the element's text. The <ICODE>normalize</ICODE> |
+method, where supported, will combine adjacent text nodes. |
+</P> |
+<P> |
+Note: Make sure the element exists in the document (has been parsed) before trying to |
+reference it. |
+ <MOREINFO> |
+<URL>http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-FF21A306</URL> |
+<URL>http://msdn.microsoft.com/en-us/library/cc304097%28VS.85%29.aspx</URL> |
+<URL>http://msdn.microsoft.com/en-us/library/ms533897%28VS.85%29.aspx</URL> |
+<URL>http://developer.mozilla.org/en/Whitespace_in_the_DOM</URL> |
+<URL>http://developer.mozilla.org/en/docs/DOM:element.innerHTML</URL> |
+<URL>http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#html-fragment-serialization-algorithm</URL> (draft) |
+ </MOREINFO> |
+ </P> |
+ </CONTENT> |
+ <CONTENT TITLE="Why does my code fail to access an element?" ID="accessElementBeforeDefined"> |
+ <P> |
+An element can only be accessed after it exists in the document. |
+ </P> |
+ <P> |
+Either: |
+A) include your script after the HTML element it refers to, or |
+B) use the <ICODE>"load"</ICODE> event to trigger your script. |
+ </P> |
+ <P> |
+Example A: |
+<CODE> |
+&lt;div id="snurgle"&gt;here&lt;/div&gt; |
+&lt;script type="text/javascript"&gt; |
+// Don't forget var. |
+var snurgleEl = document.getElementById("snurgle"); |
+window.alert(snurgleEl.parentNode); |
+&lt;/script&gt; |
+</CODE> |
+ </P> |
+ |
+ <P> |
+Example B: |
+<CODE> |
+// In the HEAD. |
+&lt;script type="text/javascript"&gt; |
+window.onload = function(){ |
+ var snurgleEl = document.getElementById("snurgle"); |
+}; |
+&lt;/script&gt; |
+</CODE> |
+</P> |
+<LIST TYPE="UL" TITLE="Other problems can include:"> |
+<LI>invalid HTML</LI> |
+<LI>two elements with the same <ICODE>name</ICODE> or <ICODE>id</ICODE></LI> |
+<LI>use of an unsafe name: http://jibbering.com/names/</LI>. |
+</LIST> |
+ </CONTENT> |
+ <CONTENT TITLE="How can I see in javascript if a web browser accepts cookies?" |
+ ID="testCookie" NUMID="4_4"> |
+ <P> |
+Write a cookie and read it back and check if it's the same. |
+ <MOREINFO> |
+Additional Notes: |
+<URL>http://www.ietf.org/rfc/rfc2965.txt</URL> |
+<URL>http://www.galasoft-lb.ch/myjavascript/consulting/2001012701/</URL> |
+<URL>http://www.cookiecentral.com/</URL> |
+</MOREINFO> |
+ </P> |
+ </CONTENT> |
+ </CONTENT> |
+ |
+ <CONTENT TITLE="Windows and Frames" ID="windows"> |
+<P> |
+The <ICODE>window</ICODE> object (also referred to by <ICODE>self</ICODE>) is "DOM Level 0". |
+No formal standard for it exists. |
+</P> |
+ <CONTENT TITLE="How can I disable the back button in a web browser?" ID="disableBackButton" NUMID="4_2"> |
+ <P> |
+You can't. The browser's history cannot be modified. However, you |
+can use <ICODE>self.location.replace(url);</ICODE> in some browsers to replace |
+the current page in the history. |
+ <MOREINFO> |
+ <URL>http://msdn.microsoft.com/en-us/library/ms536712%28VS.85%29.aspx</URL> |
+ <URL>http://docs.sun.com/source/816-6408-10/location.htm#1194240</URL> |
+ </MOREINFO> |
+ </P> |
+ </CONTENT> |
+ <CONTENT TITLE="How do I access a frame's content?" |
+ ID="frameRef" NUMID="4_8"> |
+ <P> |
+To reference another frame on the <EM>same domain</EM>: |
+</P> |
+<P> |
+The <DFN>content window</DFN> of a <ICODE>FRAME</ICODE> or <ICODE>IFRAME</ICODE> can be |
+accessed by the <ICODE>frames</ICODE> collection. |
+</P> |
+<P> |
+Example: |
+<CODE> |
+var fwin; |
+fwin = self.frames[0]; // or: |
+fwin = self.frames["iframeName"]; |
+</CODE> |
+</P> |
+<P>or, from the <ICODE>IFRAME</ICODE> or <ICODE>FRAME</ICODE> element: |
+<CODE> |
+var iframeEl = document.getElementById("myFrame"); |
+var fwin = iframeEl.contentWindow; // Nonstandard, but widely supported. |
+var fdoc = iframeEl.contentDocument; // DOM2 HTML Standard. |
+</CODE> |
+</P> |
+<P> |
+A global identifier <ICODE>moomin</ICODE> in the the iframe's <DFN>content window</DFN> |
+is accessed as <ICODE>fwin.moomin</ICODE>. |
+ </P> |
+ <P> |
+To communicate between frames on <EM>different</EM> domains: |
+</P> |
+<P> |
+Where supported, (IE8, Firefox 3, Opera 9, Safari 4), use |
+<ICODE>window.postMessage( message[, port], otherDomain);</ICODE>. |
+</P> |
+<P> |
+Example: |
+<URL>http://jibbering.com/faq/example/postMessage.html</URL> |
+ </P> |
+ <P> |
+Where <ICODE>window.postMessage</ICODE> is not supported, the <ICODE>window.name</ICODE> property |
+can be set on the other window, which can poll for updates to that |
+property using <ICODE>setInterval(checkWinName, 100);</ICODE> where <ICODE>checkWinName</ICODE> |
+is a function that polls to check the value of |
+<ICODE>self.name</ICODE>. |
+<MOREINFO> |
+<URL>http://en.wikipedia.org/wiki/Same_origin_policy</URL> |
+<URL>http://www-archive.mozilla.org/docs/dom/domref/dom_frame_ref5.html</URL> |
+<URL>https://developer.mozilla.org/en/DOM/window.postMessage</URL> |
+<URL>http://msdn.microsoft.com/en-us/library/cc197015(VS.85).aspx</URL> |
+</MOREINFO> |
+</P> |
+ |
+ </CONTENT> |
+ <CONTENT TITLE="How do I find the size of the window?" ID="getWindowSize" |
+ NUMID="4_9"> |
+ <P> |
+Here is a detailed explanation of a cross-browser strategy to |
+find the dimensions of the viewport, excepting all chrome |
+(excludes scrollbars, etc). |
+ </P> |
+ <P> |
+We can consider various properties: |
+ <CODE> |
+ window.innerWidth |
+ document.clientWidth |
+ document.documentElement.clientWidth |
+ document.body.clientWidth |
+</CODE> |
+ |
+Of the browsers that have an <ICODE>innerWidth</ICODE> property, most |
+include scrollbar dimensions. Some versions of KHTML browsers |
+(including Safari 2) do <EM>not</EM> include scrollbar width. |
+ </P> |
+ |
+ <P> |
+The <ICODE>window.inner*</ICODE> properties are unreliable and not |
+useful here. We don't want scrollbar dimensions included. |
+<CODE> document.clientWidth</CODE> |
+ </P> |
+ <P> |
+Certain versions of KHTML, including Safari 2, have |
+<ICODE>document.clientHeight</ICODE> and <ICODE>document.clientWidth</ICODE> |
+properties. Where supported, these rare properties accurately |
+return the height and width of the viewport, without including |
+scrollbar dimensions. |
+ <CODE> |
+ document.documentElement.clientWidth |
+ document.body.clientWidth |
+</CODE> |
+MSHTML (Trident), Firefox (Gecko), Opera (Presto), and Safari |
+(Webkit) all support <ICODE>clientHeight</ICODE> on <ICODE>document.body</ICODE> |
+and <ICODE>document.documentElement</ICODE>. The difficulty is figuring out |
+which one is reliable. In other words which object to get the |
+<ICODE>clientHeight</ICODE> property from:<ICODE>documentElement</ICODE> or <ICODE>body</ICODE>? |
+ </P> |
+ |
+ <P> |
+What the number returned from either of these properties |
+represents depends on the environment. The environment includes |
+the browser, its version, and the rendering mode of the document. |
+In quirks mode, we'll mostly want to use <ICODE>body.clientHeight</ICODE> |
+(except for in Safari 2). |
+ |
+ <CODE> document.body.clientHeight</CODE> |
+ |
+Some environments will return the viewport height. Others will |
+return <ICODE>0</ICODE>. Yet others will return the <ICODE>clientHeight</ICODE> of |
+the <ICODE>BODY</ICODE> element. |
+ |
+ <CODE> document.documentElement.clientHeight</CODE> |
+ |
+This is the more "standard" property for getting the height of |
+the viewport. It usually "works" in modern browsers in |
+<DFN>standards mode</DFN>. Notable exceptions include Safari 2 and |
+Opera &lt;= 9.25, both of which return the <ICODE>clientHeight</ICODE> |
+of the <ICODE>html</ICODE> <EM>element</EM>. (Oddly, Opera &lt;= 9.25 |
+in standards mode returns the width of the viewport for |
+<ICODE>documentElement.clientWidth</ICODE>). |
+ </P> |
+ <P> |
+With the exception of Safari 2, <ICODE>body.clientHeight</ICODE> is reliable |
+where <ICODE>documentElement.clientHeight</ICODE> is found to be unreliable. |
+For example, in Safari 3+, Opera, and Mozilla, all in quirks mode, |
+<ICODE>document.documentElement.clientHeight</ICODE> returns the <ICODE>clientHeight</ICODE> |
+of the <ICODE>html</ICODE> element (this may seem unsurprising but |
+it is not what we want). |
+ </P> |
+ <P> |
+Conversely, <ICODE>document.body.clientHeight</ICODE> will return |
+the height of the viewport in most cases where |
+<ICODE>document.documentElement.clientHeight</ICODE> does not. An exception |
+to that is Safari 2, where <ICODE>documentElement.clientHeight</ICODE> |
+and <ICODE>body.clientHeight</ICODE> both return the height of their |
+corresponding element (not what we want). |
+ </P> |
+ <P> |
+By using a combination of <DFN>Feature Testing</DFN> and <DFN>Capability Testing</DFN>, |
+the dimensions of the viewport can be strategically retrieved |
+from the property that works in the environment the script is |
+running in. The trick is determining which property will give us |
+the value we want. |
+ </P> |
+ <P> |
+Since <ICODE>document.clientHeight</ICODE> is reliable where |
+(rarely) supported, and since browsers that support this property |
+don't return the viewport dimensions from |
+<ICODE>document.body.clientHeight</ICODE> or |
+<ICODE>document.documentElement.clientHeight</ICODE>, this should be the |
+very first condition: |
+ |
+ <CODE> |
+ // Safari 2 uses document.clientWidth (default). |
+ if(typeof document.clientWidth == "number") { |
+ // use document.clientWidth. |
+ } |
+</CODE> |
+ |
+The next strategy is to determine if |
+<ICODE>document.documentElement.clientHeight</ICODE> property is unreliable. |
+It is deemed "unreliable" when it is either <ICODE>0</ICODE> or taller |
+than the viewport. |
+ </P> |
+ <P> |
+ Determining if <ICODE>documentElement.clientHeight</ICODE> is <ICODE>0</ICODE> is easy. |
+ The result is stored in a variable <ICODE>IS_BODY_ACTING_ROOT</ICODE>. |
+ |
+ <CODE> |
+ var docEl = document.documentElement, |
+ IS_BODY_ACTING_ROOT = docEl &amp;&amp; docEl.clientHeight === 0; |
+ docEl = null; |
+</CODE> |
+ |
+To determine if <ICODE>documentElement.clientHeight</ICODE> returns |
+a value taller than the viewport, we need a <DFN>Capability Test.</DFN> |
+ </P> |
+ |
+ <P> |
+If we can force <ICODE>documentElement</ICODE> to be very tall |
+(taller than a normal viewport) we can then check to see if |
+<ICODE>documentElement.clientHeight</ICODE> returns that "very tall" number. |
+If it does, then it is unreliable. |
+ </P> |
+ |
+ <P> |
+We can force <ICODE>documentElement</ICODE> to be taller than the viewport |
+(or any "normal" viewport) by adding a <ICODE>div</ICODE> to the <ICODE>body</ICODE>, |
+give that <ICODE>div</ICODE> a height larger than any normal monitor, |
+and then check to see if <ICODE>documentElement.clientHeight</ICODE> is |
+that high (or "almost" that high, to account for <ICODE>documentElement</ICODE> |
+having a border). |
+ |
+ <CODE> |
+ // Used to feature test Opera returning wrong values |
+ // for documentElement.clientHeight. |
+ // The results of this function should be cached, |
+ // so it does not need to be called more than once. |
+ function isDocumentElementHeightOff(){ |
+ var d = document, |
+ div = d.createElement('div'); |
+ div.style.height = "2500px"; |
+ d.body.insertBefore(div, d.body.firstChild); |
+ var r = d.documentElement.clientHeight &gt; 2400; |
+ d.body.removeChild(div); |
+ return r; |
+ } |
+</CODE> |
+ |
+We can use this function to see if we should use |
+<ICODE>body.clientHeight</ICODE>, instead. (but only after checking if |
+<ICODE>document.clientHeight</ICODE> is supported). |
+ |
+ <CODE> |
+ // Safari 2 uses document.clientWidth (default). |
+ if(typeof document.clientWidth == "number") { |
+ // use document.clientHeight/Width. |
+ } |
+ else if(IS_BODY_ACTING_ROOT || isDocumentElementHeightOff()) { |
+ // use document.body.clientHeight/Width. |
+ } else { |
+ // use document.documentElement.clientHeight/Width. |
+ } |
+</CODE> |
+The preceding strategy was developed by Garrett Smith with input |
+from John David Dalton. A complete and tested example can be found |
+in APE Library under <ICODE>APE.dom.getViewportDimensions</ICODE>. |
+Source code: |
+<URL>http://dhtmlkitchen.com/ape/build/dom/viewport-f.js</URL>. |
+APE is publicly released under Academic Free License. |
+APE home: <URL>http://dhtmlkitchen.com/ape/</URL>. |
+ </P> |
+ |
+ <P> |
+Note: The dimensions cannot be determined accurately until after |
+the document has finished loading. |
+<MOREINFO> |
+<URL>http://msdn.microsoft.com/en-us/library/ms533566%28VS.85%29.aspx</URL> |
+<URL>http://developer.mozilla.org/en/DOM/window.innerWidth</URL> |
+<URL>http://dev.opera.com/articles/view/using-capability-detection/</URL> |
+</MOREINFO> |
+ </P> |
+ </CONTENT> |
+ |
+ <CONTENT TITLE="How do I check to see if a child window is open, before opening another?" |
+ ID="isWindowOpen" NUMID="4_10"> |
+ <P> |
+ <CODE> |
+ var myWin; |
+ function openWin(aURL) { |
+ if (!myWin || myWin.closed ) { |
+ myWin = window.open(aURL,'myWin'); |
+ } else { |
+ myWin.location.href = aURL; |
+ myWin.focus(); |
+ } |
+ }</CODE> |
+Popup windows cause usability problems and are generally best avoided. |
+<MOREINFO> |
+<URL>https://developer.mozilla.org/en/DOM:window.open</URL> |
+<URL>http://msdn.microsoft.com/en-us/library/ms533574%28VS.85%29.aspx</URL> |
+<URL>http://docs.sun.com/source/816-6408-10/window.htm#1201877</URL> |
+<URL>http://www.useit.com/alertbox/990530.html</URL> |
+</MOREINFO> |
+ </P> |
+ </CONTENT> |
+ <CONTENT TITLE="Why does framename.print() not print the correct frame in IE?" |
+ ID="printFrame" NUMID="4_11"> |
+ <P> |
+IE prints the frame that has focus when you call the print |
+method <ICODE>frameref.focus();frameref.print();</ICODE> |
+<MOREINFO> |
+<URL>http://msdn.microsoft.com/en-us/library/ms976105.aspx</URL> |
+</MOREINFO> |
+ </P> |
+ </CONTENT> |
+ |
+ <CONTENT TITLE="How do I close a window and why does it not work on the first one?" |
+ ID="windowClose" NUMID="4_14"> |
+ <P> |
+If a window was opened by javascript, then it can be closed |
+without confirmation by using <ICODE>windowRef.close()</ICODE>. |
+</P> |
+<P> |
+Before calling <ICODE>windowRef.close()</ICODE> (or other <ICODE>window</ICODE> methods), make |
+sure the window reference is not null and its <ICODE>closed</ICODE> property is <ICODE>false</ICODE>. |
+</P> |
+<P> |
+Popup windows cause usability problems and are generally best avoided. |
+</P> |
+<P> |
+<MOREINFO> |
+<URL>http://www.useit.com/alertbox/990530.html</URL> |
+<URL>#isWindowOpen </URL> |
+<URL>http://msdn.microsoft.com/en-us/library/ms536367%28VS.85%29.aspx</URL> |
+<URL>https://developer.mozilla.org/en/DOM/window.close#Description</URL> |
+<URL>http://docs.sun.com/source/816-6408-10/window.htm#1201822</URL> |
+</MOREINFO> |
+ </P> |
+ </CONTENT> |
+ <CONTENT TITLE="Why do I get permission denied when accessing a frame/window?" |
+ ID="permissionDenied" NUMID="4_19"> |
+ <P> |
+In the normal browser security model, a script may only access the |
+properties of documents served from the same domain or IP address, |
+protocol, and port. |
+ </P> |
+<P> |
+Any attempt to access a property in such cases will result in a &quot;Permission |
+Denied&quot; error. Signed scripts or trusted ActiveX objects can |
+overcome this in limited situations. |
+<MOREINFO> |
+<URL>http://msdn.microsoft.com/en-us/library/ms533028%28VS.85%29.aspx</URL> |
+<URL>https://developer.mozilla.org/En/Same_origin_policy_for_JavaScript</URL> |
+</MOREINFO> |
+ </P> |
+ </CONTENT> |
+ <CONTENT TITLE="How do I make a 10 second delay?" ID="setTimeout" NUMID="4_20"> |
+ <P> |
+There is no built-in way to pause execution in javascript such |
+as a sleep function, but hosts usually provide a method of some |
+form. Web browsers are designed for event driven programming and |
+only provide the <ICODE>setTimeout</ICODE> and <ICODE>setInterval</ICODE> functions |
+to facilitate timed delays. The delay before calling <ICODE>getSnork</ICODE> may |
+exceed the second parameter to <ICODE>setTimeout</ICODE> and <ICODE>setInterval</ICODE> |
+due to implementation differences among browsers. |
+ </P> |
+ <P> |
+ To call the function <ICODE>getSnork</ICODE>, approximately 10 seconds |
+ after the function <ICODE>getMoomin()</ICODE> completes, you would do this: |
+ <CODE> |
+ getMoomin(); |
+ setTimeout(getSnork, 10000); |
+</CODE> |
+Script execution is not stopped, and adding <ICODE>getSnufkin()</ICODE> after the |
+<ICODE>setTimeout</ICODE> line would immediately execute the function <ICODE>getSnufkin</ICODE> |
+before <ICODE>getSnork</ICODE>. |
+ </P> |
+ <P> |
+Achieving delays through running a loop of some sort for a pre-defined |
+period is a bad strategy, as that will inhibit whatever was supposed to |
+be happening during the delay, including blocking user interation. |
+ </P> |
+ <P> |
+Other (less event driven) hosts have different wait functions, |
+such as <ICODE>WScript.Sleep()</ICODE> in the Windows Script Host. |
+<MOREINFO> |
+<URL>http://msdn.microsoft.com/en-us/library/ms536753%28VS.85%29.aspx</URL> |
+<URL>http://docs.sun.com/source/816-6408-10/window.htm#1203758</URL> |
+<URL>http://en.wikipedia.org/wiki/Event-driven_programming</URL> |
+<URL>faq_notes/misc.html#mtSetTI</URL> |
+</MOREINFO> |
+ </P> |
+ </CONTENT> |
+ |
+ <CONTENT TITLE="How do I change print settings for window.print()?" |
+ ID="printSettings" NUMID="4_23"> |
+ <P> |
+In a normal security environment, you can't change anything. |
+</P> |
+<P> |
+Print Stylesheet rules provide options. |
+</P> |
+<P>For IE, <ICODE>ActiveX</ICODE> or Plugin ScriptX and |
+Neptune from Meadroid to give you more control for Windows |
+versions of Internet Explorer, Netscape, and Opera. |
+<MOREINFO> |
+<URL>http://www.meadroid.com/scriptx/</URL> |
+<URL>http://msdn.microsoft.com/en-us/library/ms976105.aspx</URL> |
+</MOREINFO> |
+ </P> |
+ </CONTENT> |
+ <CONTENT TITLE="How do I change the confirm box to say yes/no or default to cancel?" |
+ ID="changeBrowserDialog" NUMID="4_28"> |
+ <P> |
+The buttons on a confirm box cannot be changed, nor can a default |
+button be specified. |
+ </P> |
+<P> |
+Change the question to a statement so that "OK" is suitable as the |
+default response. |
+</P> |
+<P> |
+ Example: |
+ "Would you like us to charge your credit card?" (wrong) |
+ "We will now charge your credit card." (right). |
+</P> |
+ </CONTENT> |
+ <CONTENT TITLE="How do I prompt a &quot;Save As&quot; dialog for an accepted mime type?" |
+ ID="fileDownload" NUMID="4_33"> |
+ <P> |
+It is not possible with client-side javascript. |
+ </P> |
+ <P> |
+Some browsers accept the Content-Disposition header, but this |
+must be added by the server. Taking the form:- |
+<ICODE>Content-Disposition: attachment; filename=filename.ext</ICODE> |
+<MOREINFO> |
+<URL>http://classicasp.aspfaq.com/general/how-do-i-prompt-a-save-as-dialog-for-an-accepted-mime-type.html</URL> |
+<URL>http://support.microsoft.com/kb/q260519/</URL> |
+</MOREINFO> |
+ </P> |
+ </CONTENT> |
+ <!-- Can we remove this entry? |
+ http://groups.google.com/group/comp.lang.javascript/msg/c70b57d86300fa91 |
+ |
+ CONTENT TITLE="I have window.status="Moomin"; why doesn't the statusbar change?" |
+ ID="returnValue" NUMID="4_35"> |
+ <P> |
+When changing the status in an event (e.g. <ICODE>onmouseover</ICODE>) you |
+should return true from the event. Also a number of browsers |
+require a short delay before setting the status to overcome their |
+default behaviour with the statusbar. |
+<ICODE>onevent=&quot;setTimeout('window.status=\'Moomin\'',15);&quot;</ICODE> |
+ </P> |
+ <P> |
+Many browsers are configured, by default, to disallow scripts from setting |
+the status bar text. Some browsers don't have such a bar, or don't have it by default. |
+ </P> |
+ </CONTENT--> |
+ |
+ <CONTENT TITLE="How do I modify the current browser window?" ID="modifyChrome" NUMID="4_36"> |
+ <P> |
+In a default security environment you are very limited in how much |
+you can modify the current browser window. You can use |
+<ICODE>window.resizeTo</ICODE> or <ICODE>window.moveTo</ICODE> to resize or move a |
+window respectively, but that is it. Normally you can only |
+suggest chrome changes in a <ICODE>window.open</ICODE>. |
+<MOREINFO> |
+<URL>http://msdn.microsoft.com/en-us/library/ms536651%28VS.85%29.aspx</URL> |
+<URL>https://developer.mozilla.org/en/DOM:window.open</URL> |
+</MOREINFO> |
+ </P> |
+ </CONTENT> |
+ <CONTENT TITLE="How do I POST a form to a new window?" ID="target" NUMID="4_37"> |
+ <P> |
+Use the target attribute on the form, opening a window with |
+that name and your feature string in the onsubmit handler of the |
+FORM. |
+ <CODE> |
+ &lt;form action=&quot;&quot; method="post" |
+ target=&quot;wndname&quot; onsubmit=&quot;window.open('',this.target);return true;&quot;&gt;</CODE> |
+ <MOREINFO> |
+<URL>http://www.htmlhelp.com/reference/html40/forms/form.html</URL> |
+ </MOREINFO> |
+ </P> |
+ </CONTENT> |
+ <CONTENT TITLE="How do I open a new window with javascript?" ID="openWindow" NUMID="4_42"> |
+ <P> |
+New windows can be opened on browsers that support the |
+<ICODE>window.open</ICODE> function and are not subject to the action of any |
+pop-up blocking mechanism with code such as:- |
+ <CODE> |
+ var wRef; |
+ if(window.open){ |
+ wRef = window.open("http://example.com/page.html","windowName"); |
+ }</CODE> |
+<MOREINFO> |
+<URL>https://developer.mozilla.org/en/DOM:window.open</URL> |
+<URL>http://www.infimum.dk/HTML/JSwindows.html</URL> |
+</MOREINFO> |
+ </P> |
+ </CONTENT> |
+ </CONTENT> |
+ <CONTENT TITLE="Ajax and Server Communication" ID="ajaxRef"> |
+ <CONTENT TITLE="What is Ajax?" ID="ajax" NUMID="4_44"> |
+ <P> |
+<DFN TITLE="Asynchronous JavaScript and XML">Ajax</DFN> |
+is shorthand for Asynchronous JavaScript and XML. The technology is |
+based on the <ICODE>XMLHttpRequest</ICODE> Object. At its simplest, |
+it is the sending/retrieving of new data from the server without |
+changing or reloading the window location. |
+<MOREINFO> |
+Mozilla Documentation: |
+<URL>http://developer.mozilla.org/en/docs/XMLHttpRequest</URL> |
+MSDN Documention: |
+<URL>http://msdn.microsoft.com/en-us/library/ms535874%28VS.85%29.aspx</URL> |
+<URL>http://msdn.microsoft.com/en-us/library/ms759148%28VS.85%29.aspx</URL> |
+ |
+<DFN TITLE="Asynchronous JavaScript and XML">Ajax</DFN> |
+Libraries and Tutorial Sites: |
+<URL>http://jibbering.com/2002/4/httprequest.html</URL> |
+<URL>http://www.ajaxtoolbox.com/</URL> |
+</MOREINFO> |
+ </P> |
+ </CONTENT> |
+ <CONTENT TITLE="How do I download a page to a variable?" ID="downloadPage" NUMID="4_38"> |
+ <P> |
+Although <ICODE>XMLHttpRequest</ICODE> can be used to download |
+entire pages, it is often used for downloading small pieces |
+of data that can be used to update the current page. |
+ <MOREINFO> |
+ <URL>http://jibbering.com/2002/4/httprequest.html</URL> |
+ <URL>http://www.ajaxtoolbox.com/</URL> |
+ </MOREINFO> |
+ </P> |
+ </CONTENT> |
+ <CONTENT TITLE="How do I get a jsp/php variable into client-side javascript?" |
+ ID="getServerVariable" NUMID="4_18"> |
+ <P> |
+Use a server-side language to generate the javascript. |
+</P> |
+<P> |
+Certain characters of ECMAScript strings must be escaped by backslash. |
+These include quote marks, backslash, and line terminators. |
+</P> |
+<P>JSP Example, using Apache Commons: <ICODE>org.apache.commons.lang.StringEscapeUtils</ICODE>: |
+ <CODE> |
+var jsVar = "&lt;%= StringEscapeUtils.escapeJavaScript(str) %&gt;"; |
+</CODE> |
+</P> |
+<P>PHP example using <ICODE>addcslashes</ICODE>: |
+<CODE> |
+var jsVar = "&lt;?php echo addcslashes($str,"\\\'\"\n\r"); ?&gt;"; |
+</CODE> |
+ <MOREINFO> |
+ <URL>example/addcslashes.php</URL> |
+ <URL>http://php.net/manual/en/function.addcslashes.php</URL> |
+ <URL>http://commons.apache.org/lang/</URL> |
+ </MOREINFO> |
+ </P> |
+ </CONTENT> |
+ <CONTENT TITLE="How do I log-out a user when they leave my site?" |
+ ID="sessionExpired" NUMID="4_29"> |
+ <P> |
+This cannot be done reliably. Here's why: |
+ <UL> |
+ <LI> |
+The user may disable javascript so the log-out script will |
+never execute. |
+ </LI> |
+ <LI> |
+The user may not be on-line when they close your web page. |
+ </LI> |
+ <LI> |
+Javascript errors elsewhere in the page may prevent the script |
+executing. |
+ </LI> |
+ <LI> |
+The browser may not support the onunload event, or may not fire |
+it under certain circumstances, so the log-out function will |
+not execute. |
+ </LI> |
+ </UL> |
+The URL below has more information. |
+<MOREINFO> |
+<URL>http://groups.google.com/groups?selm=BlmZ7.55691%244x4.7344316%40news2-win.server.ntlworld.com</URL> |
+ </MOREINFO> |
+ </P> |
+ </CONTENT> |
+ <CONTENT TITLE="How do I run a server side script?" ID="runServerScript" NUMID="4_34"> |
+ <P> |
+You trigger a server-side script by sending an HTTP request. |
+This can be achieved by setting the <ICODE>src</ICODE> of an <ICODE>img</ICODE>, |
+<ICODE>Image</ICODE>, <ICODE>frame</ICODE>, or <ICODE>iframe</ICODE>, or by using <DFN |
+TITLE="XMLHttpRequest or XMLHTTP">XHR</DFN>, where supported. |
+ </P> |
+ <P> |
+An image will also |
+&quot;swallow&quot; the data sent back by the server, so that they will |
+not be visible anywhere. |
+</P> |
+ <P> |
+ <CODE> |
+ var dummyImage = new Image(); |
+ dummyImage.src = &quot;scriptURL.asp?param=&quot; + varName; |
+</CODE> |
+ </P> |
+ <P> |
+Mozilla, Opera 7.6+, Safari 1.2+, and Windows IE 7 |
+provide the <ICODE>XMLHttpRequest</ICODE> object |
+(Windows IE versions 5+, provides ActiveX to acheive an analagous |
+effect). <ICODE>XMLHttpRequest</ICODE> can send HTTP requests to |
+the server, and provides access the <ICODE>responseText</ICODE> or <ICODE>responseXML</ICODE> |
+(when the response is XML), and HTTP header information. |
+<MOREINFO> |
+<URL>http://jibbering.com/2002/4/httprequest.html</URL> |
+<URL>http://www.w3.org/TR/XMLHttpRequest/</URL> |
+<URL>http://developer.mozilla.org/en/XMLHttpRequest</URL> |
+<URL>http://msdn.microsoft.com/en-us/library/ms537505(VS.85).aspx</URL> |
+</MOREINFO> |
+</P> |
+ <CONTENT TITLE="Why are my rollovers so slow?" ID="imageCache" NUMID="4_31"> |
+ <P> |
+Images are cached by the browser depending on the headers sent by |
+the server. If the server does not send sufficient information |
+for the browser to decide the image is cacheable, the browser |
+will check if the image has been updated every time you change the |
+src of an image (in some user settings). To overcome this you |
+must send suitable headers. |
+<MOREINFO> |
+<URL>http://www.mnot.net/cache_docs/</URL> |
+</MOREINFO> |
+ </P> |
+ </CONTENT> |
+ </CONTENT> |
+ <CONTENT TITLE="How do I force a reload from the server/prevent caching?" |
+ ID="noCache" NUMID="4_17"> |
+ <P> |
+To reload a page, use <ICODE>location.reload()</ICODE>. However, this depends |
+upon the cache headers that your server sends. To change this, |
+you need to alter the server configuration. A quick fix on the |
+client is to change the page URI so that it contains a unique |
+element, such as the current time. For example: |
+<ICODE>location.replace(location.href+'?d='+new Date().valueOf())</ICODE> |
+If the <ICODE>location.href</ICODE> already contains a query String, use: |
+<ICODE>location.replace(location.href+'&amp;d='+new Date().valueOf())</ICODE> |
+ <MOREINFO> |
+ <URL>http://www.mnot.net/cache_docs/</URL> |
+ <URL>http://docs.sun.com/source/816-6408-10/date.htm</URL> |
+ </MOREINFO> |
+ </P> |
+ </CONTENT> |
+ <CONTENT |
+ TITLE="Why is my Ajax page not updated properly when using an HTTP GET request in Internet Explorer?" |
+ ID="ajaxCache" NUMID="4_45"> |
+ <P> |
+ Browsers cache the results of HTTP requests to reduce network traffic. |
+ To force the browser to request the document from the server, either |
+ set the <ICODE>EXPIRES</ICODE> and/or <ICODE>CACHE-CONTROL</ICODE> response header(s) |
+ with a past date or use a unique query string. |
+ <CODE> |
+ req.open("GET", "/example.jsp?date=" + (+new Date), true); |
+</CODE> |
+ |
+Always use the appropriate HTTP method. Do not use <ICODE>POST</ICODE> |
+to prevent caching. See <URL LINKTEXT="RFC 2616" |
+>http://www.faqs.org/rfcs/rfc2616.html</URL>. |
+ |
+<MOREINFO> |
+<URL>http://www.mnot.net/cache_docs/#EXPIRES</URL> |
+<URL>http://www.mnot.net/javascript/xmlhttprequest/cache.html </URL> |
+</MOREINFO> |
+</P> |
+ </CONTENT> |
+ </CONTENT> |
+ |
+ <CONTENT TITLE="Debugging" ID="debugging"> |
+ <CONTENT TITLE="How do I get my browser to report javascript errors?" |
+ ID="javascriptErrors" NUMID="4_43"> |
+ <P> |
+There are debugging tools for many browsers. Learn to use them all. |
+ </P> |
+ <LIST TYPE="DL"> |
+ <DT>Windows</DT> |
+ <DD> |
+<URL LINKTEXT="Fiddler">http://www.fiddlertool.com/fiddler/</URL>. |
+Fiddler is an HTTP Debugging proxy (it won't find script |
+errors). Fiddler logs HTTP activity, like Firebug's Net |
+tab, but can be attached to any browser running on Windows. |
+ </DD> |
+ <DT>Windows IE</DT> |
+ <DD>Microsoft Script Editor. Included with Visual Studio or Microsoft |
+Word 2003 (discontinued in Office 2007). |
+To enable, |
+<ICODE>Tools</ICODE>, <ICODE>Internet Options</ICODE>, <ICODE>Advanced</ICODE>, and uncheck |
+<ICODE>Disable Script Debugging</ICODE>. After enabling Script Debugging, |
+a <ICODE>Script Debugger</ICODE> option will appear in the <ICODE>View</ICODE> menu.</DD> |
+ |
+<DD><URL LINKTEXT="IETester">http://www.my-debugbar.com/wiki/IETester/HomePage</URL> for testing IE 5.5- IE8.</DD> |
+<DD><URL LINKTEXT="CompanionJS">http://www.my-debugbar.com/wiki/CompanionJS/HomePage</URL> <ICODE>console</ICODE> for IE.</DD> |
+ <DD> |
+<EM>Note:</EM> For debugging scripts in IE, the Microsoft Script <EM>Editor</EM> |
+is recommended. However, if not available, the <URL LINKTEXT="Microsoft Script Debugger" |
+>http://www.microsoft.com/downloads/details.aspx?FamilyId=2F465BE0-94FD-4569-B3C4-DFFDF19CCD99&amp;displaylang=en</URL> may be somewhat helpful. |
+ </DD> |
+ <DD> |
+<URL LINKTEXT="Internet Explorer Developer Toolbar" |
+ >http://www.microsoft.com/downloads/details.aspx?FamilyID=e59c3964-672d-4511-bb3e-2d5e1db91038&amp;displaylang=en</URL> |
+ </DD> |
+ <DD> |
+To report errors: Wait until a little yellow |
+triangle appears at the left end of the status bar, double click |
+on it and, when the error dialog box appears, check the &quot;Always |
+show errors&quot; checkbox it contains. |
+ |
+Or, <ICODE>Internet Options</ICODE>, <ICODE>Advanced</ICODE>, deselect <ICODE>"Disable Script Debugging"</ICODE>, |
+select <ICODE>"Display a notification ..."</ICODE>. |
+ </DD> |
+ <DT>Firefox</DT> |
+ <DD> |
+ <ICODE>Tools &gt; Error console</ICODE> (<ICODE>Ctrl</ICODE> + <ICODE>Shift</ICODE> + <ICODE>j</ICODE>). |
+ </DD> |
+ <DD> |
+<URL LINKTEXT="Firebug">http://getfirebug.com/</URL> |
+ </DD> |
+ <DD> |
+<URL LINKTEXT="YSlow">https://addons.mozilla.org/en-US/firefox/addon/5369</URL>. |
+YSlow analyzes web pages and tells you why they're slow |
+based on Yahoo's rules for high performance web sites. |
+ </DD> |
+ <DD> |
+<URL LINKTEXT="Lori">https://addons.mozilla.org/en-US/firefox/addon/1743</URL> |
+<DFN>Lori</DFN> or Life-of-request info, is useful for troubleshooting |
+server response and page load time. |
+ </DD> |
+ <DD> |
+<URL LINKTEXT="Web Developer Toolbar">https://addons.mozilla.org/en-US/firefox/addon/60</URL>. |
+ </DD> |
+ <DD> |
+<URL LINKTEXT="Cookie Watcher">https://addons.mozilla.org/en-US/firefox/addon/1201</URL>. |
+ </DD> |
+ <DD> |
+<URL LINKTEXT="XPather">https://addons.mozilla.org/en-US/firefox/addon/1192</URL>. |
+XPath generator, editor and inspector. |
+ </DD> |
+ <DT>Opera</DT> |
+ <DD> |
+Tools &gt; Advanced &gt; Error console |
+ </DD> |
+ <DD> |
+<URL LINKTEXT="Introduction to Opera Dragonfly" |
+ >http://dev.opera.com/articles/view/introduction-to-opera-dragonfly/</URL> |
+ </DD> |
+ <DT>Safari</DT> |
+ <DD> |
+To display the <ICODE>Develop</ICODE> menu in Safari 3.1 or higher, select |
+the checkbox labeled "Show Develop menu in menu bar" in |
+Safari's <ICODE>Advanced</ICODE> Preferences panel. |
+ </DD> |
+ <DD> |
+<URL LINKTEXT="Safari Web Inspector">http://trac.webkit.org/wiki/Web%20Inspector </URL> |
+ </DD> |
+ <DT>Chrome</DT> |
+ <DD> |
+JavaScript Console: click the <ICODE>Page</ICODE> menu icon and select |
+<ICODE>Developer &gt; JavaScript Console</ICODE>. From here, you'll be |
+able to view errors in the JavaScript execution, and enter |
+additional javascript commands to execute. |
+ </DD> |
+ <DD> |
+JavaScript Debugger: available as <ICODE>Page</ICODE> menu icon &gt; <ICODE>Developer</ICODE> |
+&gt; Debug JavaScript, the debugger provides a command prompt from which you |
+can set breakpoints, backtrace, and more. Type <ICODE>help</ICODE> at the debugger |
+command line to get started. |
+ </DD> |
+ <DD> |
+ <UL> |
+ <LI><URL LINKTEXT="Google Chrome Script Debugging" |
+ >http://www.google.com/chrome/intl/en/webmasters-faq.html#jsexec</URL></LI> |
+ <LI><URL LINKTEXT="Developer Tools for Google Chrome" |
+ >http://blog.chromium.org/2009/06/developer-tools-for-google-chrome.html</URL></LI> |
+ <LI><URL LINKTEXT="Tools for Eclipse Users">http://blog.chromium.org/2009/08/google-chrome-developer-tools-for.html</URL></LI> |
+ </UL> |
+ </DD> |
+ <DT>Mac IE</DT> |
+ <DD> |
+Use the Preferences dialog. |
+ </DD> |
+ </LIST> |
+ </CONTENT> |
+ </CONTENT> |
+ <CONTENT TITLE="Things not to attempt in a browser" ID="doNotTry"> |
+ <CONTENT TITLE="How do I detect Opera/Safari/IE?" ID="detectBrowser" NUMID="4_26"> |
+ <P> |
+The short answer: <EM>Don't do that</EM>. |
+ </P> |
+ <P> |
+The <ICODE>navigator</ICODE> <DFN>host object</DFN> contains properties which |
+may identify the browser and version. These properties are historically |
+inaccurate. Some browsers allow the user to set <ICODE>navigator.userAgent</ICODE> to any value. For |
+example, Firefox, (type <ICODE>about:config</ICODE> and search <ICODE>useragent</ICODE> |
+or Safari, <ICODE>Develop &gt; User Agent &gt; Other...</ICODE>, IE, via Registry. |
+ </P> |
+ <P> |
+Other browsers, such as Opera, provide a list of user agents |
+for the user to select from. There are also at least 25 other |
+javascript capable browsers, with multiple versions, each |
+with their own string. |
+ </P> |
+ <P> |
+Browser detection is unreliable, at best. It usually causes |
+forward-compatibility and maintenance problems. It is unrelated to the |
+problem or incompatiblity it is trying to solve and obscures the |
+problems it is used for, where it is used. |
+ </P> |
+ <P> |
+Object detection is checking that the object in question exists. |
+<URL LINKTEXT="Capability detection" |
+>http://dev.opera.com/articles/view/using-capability-detection/</URL |
+ > goes one step further to actually test the object, |
+method, or property, to see if behaves in the desired manner. |
+ </P> |
+ <P> |
+Feature Test Example: |
+ <CODE> |
+/** |
+ * Returns the element/object the user targeted. |
+ * If neither DOM nor IE event model is supported, returns undefined. |
+ * @throws TypeError if the event is not an object. |
+ */ |
+function getEventTarget(e) { |
+ e = e || window.event; |
+ // First check for the existence of standard "target" property. |
+ return e.target || e.srcElement; |
+}</CODE> |
+<MOREINFO> |
+<URL>notes/detect-browser/</URL> |
+<URL>http://dev.opera.com/articles/view/using-capability-detection/</URL> |
+<URL>http://developer.apple.com/internet/webcontent/objectdetection.html</URL> |
+<URL>http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43</URL> |
+</MOREINFO> |
+ </P> |
+ </CONTENT> |
+ <CONTENT TITLE="How can I prevent access to a web page by using javascript?" |
+ ID="preventAccess" NUMID="4_5"> |
+ <P> |
+In practice you can't. While you could create a suitable |
+encryption system with a password in the page, the level of |
+support you need to do this means it's always simpler to do it |
+server-side. Anything that &quot;protects&quot; a page |
+other than the current one is definitely flawed. |
+ </P> |
+ </CONTENT> |
+ <CONTENT TITLE="How do I protect my javascript code?" ID="hideSource" NUMID="4_1"> |
+ <P> |
+With clientside javascript you can't as your code is distributed |
+in source form and is easily readable. With JScript, there is the |
+Script Encoder (see MSDN), but this is nothing more than obfuscation. |
+Attempting to disable the context menu does nothing to |
+protect your script in a Web browser. |
+ <MOREINFO> |
+ Your code is likely protected under copyright laws. See: |
+ <URL>http://www.wipo.int/about-ip/en/copyright.html</URL> |
+ <URL>http://webdesign.about.com/od/copyright/Copyright_Issues_on_the_Web_Intellectual_Property.htm</URL> |
+ </MOREINFO> |
+ </P> |
+ </CONTENT> |
+ <CONTENT TITLE="How do I suppress a context menu (right-click menu)?" |
+ ID="disableRightClick" NUMID="4_27"> |
+ <P> |
+A context menu, often triggered by right-click, can be requested by the |
+user in a few ways. For example, on windows, shift + F10 and on macs, |
+click-and-hold. Other input devices exist and mouse buttons can be |
+configured, making the term "right click" a misnomer, in context. |
+</P> |
+<P> |
+In browsers that allow it, a script can suppress the context menu by |
+returning false from an object's <ICODE>oncontextmenu</ICODE> event handler. |
+<CODE> |
+document.oncontextmenu = function() { |
+ return false; |
+}; |
+</CODE> |
+Some browsers lack context menus (e.g. iphone). Browsers that have |
+context menus do not always have a scriptable event for them. Some |
+browsers can be configured to disallow scripts from detecting context |
+menu events (IE, Opera); others may fire the event but be configured to |
+disallow scripts from suppressing the context menu (Firefox,Seamonkey). |
+</P> |
+<P> |
+Even when the context menu has been suppressed, it will still be |
+possible to view/save the source code and to save images. |
+<MOREINFO> |
+<URL>http://en.wikipedia.org/wiki/Context_menu</URL> |
+<URL>http://kb.mozillazine.org/Ui.click_hold_context_menus</URL> |
+<URL>http://support.microsoft.com/kb/823057</URL> |
+<URL>http://stackoverflow.com/questions/1870880/opera-custom-context-menu-picking-up-the-right-click/1902730#1902730</URL> |
+<URL>http://support.mozilla.com/en-US/kb/Javascript#Advanced_JavaScript_settings</URL> |
+<URL>http://msdn.microsoft.com/en-us/library/ms536914%28VS.85%29.aspx</URL> |
+</MOREINFO> |
+</P> |
+</CONTENT> |
+ <CONTENT TITLE="How can I access the client-side filesystem?" ID="readFile" NUMID="4_3"> |
+ <P> |
+Security means that by default you can't. In a more restricted |
+environment, there are options. For example, using LiveConnect to |
+connect to Java with Netscape, and using the FileSystemObject in |
+IE. Check <URL LINKTEXT="Google Groups archives">http://groups.google.com/group/comp.lang.javascript/topics</URL> |
+for previous posts on the subject. |
+ <MOREINFO> |
+ <URL>http://msdn.microsoft.com/en-us/library/z9ty6h50%28VS.85%29.aspx</URL> |
+ <URL>http://www.javaworld.com/javaworld/jw-10-1998/jw-10-apptowin32.html</URL> |
+ </MOREINFO> |
+ </P> |
+ </CONTENT> |
+ <CONTENT TITLE="I have &lt;a href=&quot;javascript:somefunction()&quot;&gt; what ... ?" |
+ ID="javascriptURI" NUMID="4_24"> |
+ <P> |
+Whatever the rest of your question, this is generally a very bad idea. |
+The <ICODE>javascript:</ICODE> pseudo protocol was designed to replace the |
+current document with the value that is returned from the expression. |
+For example: |
+ <CODE> |
+ &lt;a href=&quot;javascript:'&amp;lt;h1&amp;gt;' + document.lastModified + '&amp;lt;/h1&amp;gt;'&quot;&gt;lastModified&lt;/a&gt; |
+</CODE> |
+will result in replacing the current document with the value |
+returned from <ICODE>document.lastModified</ICODE>, wrapped in an <ICODE>&lt;h1&gt;</ICODE> |
+tag. |
+ </P> |
+ <P> |
+When the expression used evaluates to an <ICODE>undefined</ICODE> value |
+(as some function calls do), the contents of the current page are not |
+replaced. Regardless, some browsers (notably IE6) interpret this as |
+navigation and will enter into a 'navigation' state where GIF |
+animations and plugins (such as movies) will stop and navigational |
+features such as <ICODE>META</ICODE> refresh, assignment to <ICODE>location.href</ICODE>, and image |
+swaps fail. |
+ </P> |
+ <P> |
+It is also possible for IE to be configured such that it supports |
+javascript but not the <ICODE>javascript:</ICODE> protocol. This results |
+in the user seeing a protocol error for <ICODE>javascript:</ICODE> URIs. |
+ </P> |
+ <P> |
+The <ICODE>javascript:</ICODE> pseudo protocol creates accessibility and |
+usability problems. It provides no fallback for when the script is not |
+supported. |
+ </P> |
+ <P> |
+Instead, use |
+<ICODE>&lt;a href=&quot;something.html&quot; onclick=&quot;somefunction();return false&quot;&gt;</ICODE> |
+where <ICODE>something.html</ICODE> is a meaningful alternative. Alternatively, |
+attach the <ICODE>click</ICODE> callback using an event registry. |
+ <MOREINFO> |
+ <URL>example/jsuri/</URL> |
+ <URL LINKTEXT="Set/Navigate to a Location">http://groups.google.com/group/comp.lang.javascript/msg/f665cfca3b619692</URL> |
+ <URL LINKTEXT="Top Ten Web-Design Mistakes of 2002">http://www.useit.com/alertbox/20021223.html</URL> |
+ </MOREINFO> |
+ </P> |
+ </CONTENT> |
+ </CONTENT> |
+ |
+ <CONTENT TITLE="Comments and Suggestions" ID="comments" NUMID="5"> |
+ <P HTMLONLY="true"> |
+The FAQ uses the stylesheet <URL>faq.css</URL> and is generated |
+from the xml source <URL>index.xml</URL> by the windows script |
+host script <URL>process.wsf</URL> which also checks the links. |
+ </P> |
+ <CONTENT TITLE="Why do some posts have &lt;FAQENTRY&gt; in them?" |
+ ID="FAQENTRY" NUMID="5_1"> |
+ <P> |
+If a poster feels that the question they are answering should be |
+covered in the FAQ, placing &lt;FAQENTRY&gt; in the post lets the FAQ |
+robot collect the messages for easy review and inclusion. A Draft Proposal |
+for the FAQ is requested and appreciated. |
+ </P> |
+ <P> |
+The &lt;FAQENTRY&gt; should not be used in posts except in |
+conjunction with a suggestion/proposal for the FAQ. It should |
+also not be literally quoted in replies, instead it should be |
+partly obscured as, e.g. &lt;FAQ**TRY&gt; or similar. |
+ </P> |
+ </CONTENT> |
+ <CONTENT TITLE="How do I make a suggestion?" NUMID="5_2" ID="makeSuggestion"> |
+ <P> |
+To make a suggestion to the FAQ, use either the FAQENTRY method |
+above, or email Garrett Smith dhtmlkitchen&#64;gmail.com (current FAQ editor) |
+or Jim Ley (jim.ley&#64;gmail.com). All comments, suggestions, and |
+especially corrections are welcome. |
+ </P> |
+ </CONTENT> |
+ <!-- |
+ <P> |
+ This FAQ is (C) Copyright Contributors on behalf of the |
+ newsgroup comp.lang.javascript. Upon change of the FAQ maintainer, |
+ the copyright will automatically pass over to the new maintainer. |
+ </P> |
+ --> |
+ </CONTENT> |
+ </CONTENTS> |
+</FAQ> |
/cljs/index.xml |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/notes/closures/index.html |
=================================================================== |
--- cljs/notes/closures/index.html (nonexistent) |
+++ cljs/notes/closures/index.html (revision 2) |
@@ -0,0 +1,1574 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" |
+ "http://www.w3.org/TR/html4/strict.dtd"> |
+<html lang="en"> |
+<head> |
+<title>Javascript Closures</title> |
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> |
+<link href="../../faq.css" rel="stylesheet" type="text/css"> |
+<link href="../notes.css" rel="stylesheet" type="text/css"> |
+<style type="text/css"> |
+CODE { white-space:nowrap; } |
+.scopeCh { |
+ white-space:nowrap; |
+ font-family:Courier, monospace; |
+} |
+</style> |
+</head> |
+<body> |
+ |
+<h1>Javascript Closures</h1> |
+<div id="faqNav"> |
+ <a href="../../">FAQ</a> > <a href="../">FAQ Notes</a> |
+</div> |
+ |
+<ul> |
+ <li><a href="#clIntro">Introduction</a></li> |
+ <li><a href="#clResO">The Resolution of Property Names on Objects</a> |
+ <ul> |
+ <li><a href="#clResA">Assignment of Values</a></li> |
+ <li><a href="#clResR">Reading of Values</a></li> |
+ </ul> |
+ </li> |
+ <li><a href="#clIRExSc">Identifier Resolution, Execution Contexts and scope chains</a> |
+ <ul> |
+ <li><a href="#clExCon">The Execution Context</a></li> |
+ <li><a href="#clScCh">scope chains and [[scope]]</a></li> |
+ <li><a href="#clIdRes">Identifier Resolution</a></li> |
+ </ul> |
+ </li> |
+ <li><a href="#clClose">Closures</a> |
+ <ul> |
+ <li><a href="#clAtGb">Automatic Garbage Collection</a></li> |
+ <li><a href="#clFrmC">Forming Closures</a></li> |
+ </ul> |
+ </li> |
+ <li><a href="#clClDo">What can be done with Closures?</a> |
+ <ul> |
+ <li><a href="#clSto">Example 1: setTimeout with Function References</a></li> |
+ <li><a href="#clObjI">Example 2: Associating Functions with Object Instance Methods</a></li> |
+ <li><a href="#clEncap">Example 3: Encapsulating Related Functionality</a></li> |
+ <li><a href="#clOtE">Other Examples</a></li> |
+ </ul> |
+ </li> |
+ <li><a href="#clAc">Accidental Closures</a></li> |
+ <li><a href="#clMem">The Internet Explorer Memory Leak Problem</a></li> |
+</ul> |
+ |
+<h2 id="clIntro">Introduction</h2> |
+ |
+<blockquote cite="http://groups.google.com/groups?selm=wu535hos.fsf@hotpop.com"> |
+ <dl> |
+ <dt id="clDefN">Closure</dt> |
+ <dd>A "closure" is an expression (typically a function) that |
+ can have free variables together with an environment that binds |
+ those variables (that "closes" the expression). |
+ <dd> |
+ </dl> |
+</blockquote> |
+ |
+<p> |
+Closures are one of the most powerful features of ECMAScript |
+(javascript) but they cannot be property exploited without |
+understanding them. They are, however, relatively easy to create, |
+even accidentally, and their creation has potentially harmful |
+consequences, particularly in some relatively common web browser |
+environments. To avoid accidentally encountering the drawbacks and |
+to take advantage of the benefits they offer it is necessary to |
+understand their mechanism. This depends heavily on the role of |
+scope chains in identifier resolution and so on the resolution of |
+property names on objects. |
+</p> |
+ |
+<p> |
+The simple explanation of a Closure is that ECMAScript allows inner |
+functions; function definitions and function expressions that are |
+inside the function bodes of other functions. And that those inner |
+functions are allowed access to all of the local variables, parameters |
+and declared inner functions within their outer function(s). A closure |
+is formed when one of those inner functions is made accessible outside |
+of the function in which it was contained, so that it may be executed |
+after the outer function has returned. At which point it still has |
+access to the local variables, parameters and inner function |
+declarations of its outer function. Those local variables, parameter |
+and function declarations (initially) have the values that they had |
+when the outer function returned and may be interacted with by the |
+inner function. |
+</p> |
+ |
+<p> |
+Unfortunately, properly understanding closures requires an |
+understanding of the mechanism behind them, and quite a bit of |
+technical detail. While some of the ECMA 262 specified algorithms have |
+been brushed over in the early part of the following explanation, much |
+cannot be omitted or easily simplified. Individuals familiar with |
+object property name resolution may skip that section but only people |
+already familiar with closures can afford to skip the following |
+sections, and they can stop reading now and get back to exploiting |
+them. |
+</p> |
+ |
+<h2 id="clResO">The Resolution of Property Names on Objects</h2> |
+ |
+<p> |
+ECMAScript recognises two categories of object, "Native Object" |
+and "Host Object" with a sub-category of native objects called |
+"Built-in Object" (ECMA 262 3rd Ed Section 4.3). Native objects |
+belong to the language and host objects are provided by the environment, |
+and may be, for example, document objects, DOM nodes and the like. |
+</p> |
+ |
+<p> |
+Native objects are loose and dynamic bags of named properties (some |
+implementations are not that dynamic when it comes to the built in |
+object sub-category, though usually that doesn't matter). The defined |
+named properties of an object will hold a value, which may be a |
+reference to another Object (functions are also Objects in this sense) |
+or a primitive value: String, Number, Boolean, Null or Undefined. The |
+Undefined primitive type is a bit odd in that it is possible to assign |
+a value of Undefined to a property of an object but doing so does not |
+remove that property from the object; it remains a defined named |
+property, it just holds the value <code>undefined</code>. |
+</p> |
+ |
+<p> |
+The following is a simplified description of how property values are |
+read and set on objects with the internal details brushed over to the |
+greatest extent possible. |
+</p> |
+ |
+<h3><a name="clResA" id="clResA">Assignment of Values</a></h3> |
+ |
+<p> |
+Named properties of objects can be created, or values set on existing |
+named properties, by assigning a value to that named property. So |
+given:- |
+</p> |
+ |
+<pre> |
+var objectRef = new Object(); <span class="commentJS">//create a generic javascript object.</span> |
+</pre> |
+ |
+<p> |
+A property with the name "testNumber" can be created as:- |
+</p> |
+ |
+<pre> |
+objectRef.testNumber = 5; |
+<span class="commentJS">/* - or:- */</span> |
+objectRef["testNumber"] = 5; |
+</pre> |
+ |
+<p> |
+The object had no "testNumber" property prior to the |
+assignment but one is created when the assignment is made. Any |
+subsequent assignment does not need to create the property, it just |
+re-sets its value:- |
+</p> |
+ |
+<pre> |
+objectRef.testNumber = 8; |
+<span class="commentJS">/* - or:- */</span> |
+objectRef["testNumber"] = 8; |
+</pre> |
+ |
+<p> |
+Javascript objects have prototypes that can themselves be objects, as |
+will be described shortly, and that prototype may have named |
+properties. But this has no role in assignment. If a value is assigned |
+and the actual object does not have a property with the corresponding |
+name a property of that name is created and the value is assigned to |
+it. If it has the property then its value is re-set. |
+</p> |
+ |
+<h3><a name="clResR" id="clResR">Reading of Values</a></h3> |
+ |
+<p> |
+It is in reading values from object properties that prototypes come |
+into play. If an object has a property with the property name used in |
+the property accessor then the value of that property is returned:- |
+</p> |
+ |
+<pre> |
+<span class="commentJS">/* Assign a value to a named property. If the object does not have a |
+ property with the corresponding name prior to the assignment it |
+ will have one after it:- |
+*/</span> |
+objectRef.testNumber = 8; |
+ |
+<span class="commentJS">/* Read the value back from the property:- */</span> |
+ |
+var val = objectRef.testNumber; |
+<span class="commentJS">/* and - val - now holds the value 8 that was just assigned to the |
+ named property of the object. */</span> |
+ </pre> |
+ |
+<p> |
+But all objects may have prototypes, and prototypes are objects so they, in |
+turn, may have prototypes, which may have prototypes, and so on forming |
+what is called the prototype chain. The prototype chain ends when one |
+of the objects in the chain has a null prototype. The default prototype for the |
+<code>Object</code> constructor has a null prototype so:- |
+</p> |
+ |
+<pre> |
+var objectRef = new Object(); <span class="commentJS">//create a generic javascript object.</span> |
+</pre> |
+ |
+<p> |
+Creates an object with the prototype <code>Object.prototype</code> that itself has a |
+null prototype. So the prototype chain for <code>objectRef</code> contains only one |
+object: <code>Object.prototype</code>. However:- |
+</p> |
+ |
+<pre> |
+<span class="commentJS">/* A "constructor" function for creating objects of a - |
+ MyObject1 - type. |
+*/</span> |
+function MyObject1(formalParameter){ |
+ <span class="commentJS">/* Give the constructed object a property called - testNumber - and |
+ assign it the value passed to the constructor as its first |
+ argument:- |
+ */</span> |
+ this.testNumber = formalParameter; |
+} |
+ |
+<span class="commentJS">/* A "constructor" function for creating objects of a - |
+ MyObject2 - type:- |
+*/</span> |
+function MyObject2(formalParameter){ |
+ <span class="commentJS">/* Give the constructed object a property called - testString - |
+ and assign it the value passed to the constructor as its first |
+ argument:- |
+ */</span> |
+ this.testString = formalParameter; |
+} |
+ |
+<span class="commentJS">/* The next operation replaces the default prototype associated with |
+ all MyObject2 instances with an instance of MyObject1, passing the |
+ argument - 8 - to the MyObject1 constructor so that its - |
+ testNumber - property will be set to that value:- |
+*/</span> |
+MyObject2.prototype = new MyObject1( 8 ); |
+ |
+<span class="commentJS">/* Finally, create an instance of - MyObject2 - and assign a reference |
+ to that object to the variable - objectRef - passing a string as the |
+ first argument for the constructor:- |
+*/</span> |
+ |
+var objectRef = new MyObject2( "String_Value" ); |
+</pre> |
+ |
+<p> |
+The instance of <code>MyObject2</code> referred to by the <code>objectRef</code> variable has a |
+prototype chain. The first object in that chain is the instance of |
+<code>MyObject1</code> that was created and assigned to the prototype |
+property of the <code>MyObject2</code> constructor. The instance of |
+<code>MyObject1</code> has a prototype, the object that was assigned to the function |
+<code>MyObject1</code>'s prototype property by the implementation. That object has |
+a prototype, the default <code>Object</code> prototype that corresponds with the |
+object referred to by <code>Object.prototype</code>. <code>Object.prototype</code> has a null |
+prototype so the prototype chain comes to an end at this point. |
+</p> |
+<p> |
+When a property accessor attempts to read a named property form the |
+object referred to by the variable <code>objectRef</code> the whole |
+prototype chain can enter into the process. In the simple case:- |
+</p> |
+ |
+<pre> |
+var val = objectRef.testString; |
+</pre> |
+ |
+<p> |
+- the instance of <code>MyObject2</code> referred to by <code>objectRef</code> has |
+a property with the name "testString" so it is the value of |
+that property, set to "String_Value", that is assigned to the |
+variable <code>val</code>. However:- |
+</p> |
+ |
+<pre> |
+var val = objectRef.testNumber; |
+</pre> |
+ |
+<p> |
+- cannot read a named property form the instance of |
+<code>MyObject2</code> itself as it has no such property but the |
+variable <code>val</code> is set to the value of <code>8</code> rather |
+than undefined because having failed to find a corresponding named |
+property on the object itself the interpreter then examines the object |
+that is its prototype. Its prototype is the instance of |
+<code>MyObject1</code> and it was created with a property named |
+"testNumber" with the value <code>8</code> assigned to that property, so |
+the property accessor evaluates as the value <code>8</code>. Neither |
+<code>MyObject1</code> or <code>MyObject2</code> have defined a |
+<code>toString</code> method, but if a property accessor attempts to |
+read the value of a <code>toString</code> property from |
+<code>objectRef</code>:- |
+</p> |
+ |
+<pre> |
+var val = objectRef.toString; |
+</pre> |
+ |
+<p> |
+- the <code>val</code> variable is assigned a reference to a function. |
+That function is the <code>toString</code> property of |
+<code>Object.prototype</code> and is returned because the process of |
+examining the prototype of <code>objectRef</code>, when |
+<code>objectRef</code> turns out not to have a "toString" |
+property, is acting on an object, so when that prototype is found to |
+lack the property its prototype is examined in turn. Its prototype |
+is <code>Object.prototype</code>, which does have a |
+<code>toString</code> method so it is a reference to that function |
+object that is returned. |
+</p> |
+ |
+<p> |
+Finally:- |
+</p> |
+ |
+<pre> |
+var val = objectRef.madeUpProperty; |
+</pre> |
+ |
+<p> |
+- returns <code>undefined</code>, because as the process of working up the prototype |
+chain finds no properties on any of the object with the name |
+"madeUpPeoperty" it eventually gets to the prototype of |
+<code>Object.prototype</code>, which is null, and the process ends |
+returning <code>undefined</code>. |
+</p> |
+ |
+<p> |
+The reading of named properties returns the first value found, on the |
+object or then from its prototype chain. The assigning of a value to a |
+named property on an object will create a property on the object itself |
+if no corresponding property already exists. |
+</p> |
+ |
+<p> |
+This means that if a value was assigned as |
+<code>objectRef.testNumber = 3</code> a "testNumber" property |
+will be created on the instance of <code>MyObject2</code> itself, and |
+any subsequent attempts to read that value will retrieve that value as |
+set on the object. The prototype chain no longer needs to be examined |
+to resolve the property accessor, but the instance of |
+<code>MyObject1</code> with the value of <code>8</code> assigned to its |
+"testNumber" property is unaltered. The assignment to the |
+<code>objectRef</code> object masks the corresponding property in its |
+prototype chain. |
+</p> |
+ |
+<p> |
+Note: ECMAScript defines an internal <code>[[prototype]]</code> |
+property of the internal Object type. This property is not directly accessible with |
+scripts, but it is the chain of objects referred to with the |
+internal <code>[[prototype]]</code> property that is used in property |
+accessor resolution; the object's prototype chain. A public |
+<code>prototype</code> property exists to allow the assignment, |
+definition and manipulation of prototypes in association with the |
+internal <code>[[prototype]]</code> property. The details of the |
+relationship between to two are described in ECMA 262 (3rd edition) |
+and are beyond the <dfn>scope</dfn> of this discussion. |
+</p> |
+ |
+<h2 id="clIRExSc">Identifier Resolution, Execution Contexts and scope chains</h2> |
+ |
+<h3 id="clExCon">The Execution Context</h3> |
+ |
+<p> |
+An <dfn>execution context</dfn> is an abstract concept used by the ECMSScript |
+specification (ECMA 262 3rd edition) to define the behaviour required |
+of ECMAScript implementations. The specification does not say anything |
+about how <dfn>execution contexts</dfn> should be implemented but execution |
+contexts have associated attributes that refer to specification defined |
+structures so they might be conceived (and even implemented) as objects |
+with properties, though not public properties. |
+</p> |
+ |
+<p> |
+All javascript code is executed in an <dfn>execution context</dfn>. Global code |
+(code executed inline, normally as a JS file, or <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> page, loads) gets |
+executed in <dfn>global</dfn> <dfn>execution context</dfn>, and each invocation of a function (possibly as a constructor) has an associated |
+<dfn>execution context</dfn>. Code executed with the <code>eval</code> function |
+also gets a distinct execution context but as <code>eval</code> is |
+never normally used by javascript programmers it will not be discussed |
+here. The specified details of <dfn>execution contexts</dfn> are to be found in |
+section 10.2 of ECMA 262 (3rd edition). |
+</p> |
+ |
+<p> |
+When a javascript function is called it enters an <dfn>execution context</dfn>, |
+if another function is called (or the same function recursively) a new |
+<dfn>execution context</dfn> is created and execution enters that context for the |
+duration of the function call. Returning to the original execution |
+context when that called function returns. Thus running javascript code |
+forms a stack of <dfn>execution contexts</dfn>. |
+</p> |
+ |
+<p> |
+When an <dfn>execution context</dfn> is created a number of things happen in a |
+defined order. First, in the <dfn>execution context</dfn> of a function, an |
+"Activation" object is created. The activation object is |
+another specification mechanism. It can be considered as an object |
+because it ends up having accessible named properties, but it is not a |
+normal object as it has no prototype (at least not a defined prototype) |
+and it cannot be directly referenced by javascript code. |
+</p> |
+ |
+<p> |
+The next step in the creation of the <dfn>execution context</dfn> for a function |
+call is the creation of an <code>arguments</code> object, which is an |
+array-like object with integer indexed members corresponding with the |
+arguments passed to the function call, in order. It also has |
+<code>length</code> and <code>callee</code> properties (which are not |
+relevant to this discussion, see the spec for details). A property of |
+the Activation object is created with the name "arguments" |
+and a reference to the <code>arguments</code> object is assigned to |
+that property. |
+</p> |
+ |
+<p> |
+Next the <dfn>execution context</dfn> is assigned a <dfn>scope</dfn>. A <dfn>scope</dfn> consists of a |
+list (or chain) of objects. Each function object has an internal |
+<code>[[scope]]</code> property (which we will go into more detail |
+about shortly) that also consists of a list (or chain) of objects. |
+The <dfn>scope</dfn> that is assigned to the <dfn>execution context</dfn> of a function call |
+consists of the list referred to by the <code>[[scope]]</code> property |
+of the corresponding function object with the Activation object added |
+at the front of the chain (or the top of the list). |
+</p> |
+ |
+<p> |
+Then the process of "variable instantiation" takes place using an object |
+that ECMA 262 refers to as the "Variable" object. However, |
+the Activation object is used as the Variable object (note this, it is |
+important: they are the same object). Named properties of the Variable |
+object are created for each of the function's formal parameters, and if |
+arguments to the function call correspond with those parameters the |
+values of those arguments are assigned to the properties (otherwise the |
+assigned value is <code>undefined</code>). Inner function definitions |
+are used to create function objects which are assigned to properties of |
+the Variable object with names that correspond to the function name |
+used in the function declaration. The last stage of variable |
+instantiation is to create named properties of the Variable object |
+that correspond with all the local variables declared within the |
+function. |
+</p> |
+ |
+<p> |
+The properties created on the Variable object that correspond with |
+declared local variables are initially assigned <code>undefined</code> |
+values during variable instantiation, the actual initialisation of |
+local variables does not happen until the evaluation of the |
+corresponding assignment expressions during the execution of the |
+function body code. |
+</p> |
+ |
+<p> |
+It is the fact that the Activation object, with its |
+<code>arguments</code> property, and the Variable object, with named |
+properties corresponding with function local variables, are the same |
+object, that allows the identifier <code>arguments</code> to be treated |
+as if it was a function local variable. |
+</p> |
+ |
+<p> |
+Finally a value is assigned for use with the <code>this</code> keyword. |
+If the value assigned refers to an object then property accessors |
+prefixed with the <code>this</code> keyword reference properties of |
+that object. If the value assigned (internally) is null then the |
+<code>this</code> keyword will refer to the global object. |
+</p> |
+ |
+<p> |
+The global execution context gets some slightly different handling as |
+it does not have arguments so it does not need a defined Activation |
+object to refer to them. The global execution context does need a <dfn>scope</dfn> |
+and its <dfn>scope chain</dfn> consists of exactly one object, the global object. |
+The global execution context does go through variable instantiation, |
+its inner functions are the normal top level function declarations that |
+make up the bulk of javascript code. The global object is used as the |
+Variable object, which is why globally declared functions become |
+properties of the global object. As do globally declared variables. |
+</p> |
+ |
+<p> |
+The global execution context also uses a reference to the global object |
+for the <code>this</code> object. |
+</p> |
+ |
+<h3 id="clScCh">scope chains and [[scope]]</h3> |
+ |
+<p> |
+The <dfn>scope chain</dfn> of the execution context for a function call is |
+constructed by adding the execution context's Activation/Variable |
+object to the front of the <dfn>scope chain</dfn> held in the function |
+object's <code>[[scope]]</code> property, so it is important to |
+understand how the internal <code>[[scope]]</code> property is |
+defined. |
+</p> |
+ |
+<p> |
+In ECMAScript functions are objects, they are created during variable |
+instantiation from function declarations, during the evaluation of |
+function expressions or by invoking the <code>Function</code> |
+constructor. |
+</p> |
+ |
+<p> |
+Function objects created with the <code>Function</code> constructor |
+always have a <code>[[scope]]</code> property referring to a <dfn>scope |
+chain</dfn> that only contains the global object. |
+</p> |
+ |
+<p> |
+Function objects created with function declarations or function |
+expressions have the <dfn>scope chain</dfn> of the execution context in which |
+they are created assigned to their internal <code>[[scope]]</code> |
+property. |
+</p> |
+ |
+<p> |
+In the simplest case of a global function declaration such as:- |
+</p> |
+ |
+<pre> |
+function exampleFunction(formalParameter){ |
+ ... <span class="commentJS">// function body code</span> |
+} |
+</pre> |
+ |
+<p> |
+- the corresponding function object is created during the variable |
+instantiation for the global execution context. The global execution |
+context has a <dfn>scope chain</dfn> consisting of only the global object. Thus |
+the function object that is created and referred to by the property of |
+the global object with the name "exampleFunction" is |
+assigned an internal <code>[[scope]]</code> property referring to a |
+<dfn>scope chain</dfn> containing only the global object. |
+</p> |
+ |
+<p> |
+A similar <dfn>scope chain</dfn> is assigned when a function expression is |
+executed in the global context:- |
+</p> |
+ |
+<pre> |
+var exampleFuncRef = function(){ |
+ ... <span class="commentJS">// function body code</span> |
+} |
+</pre> |
+ |
+<p> |
+- except in this case a named property of the global object is created |
+during variable instantiation for the global execution context but the |
+function object is not created, and a reference to it assigned to the |
+named property of the global object, until the assignment expression is |
+evaluated. But the creation of the function object still happens in the |
+global execution context so the <code>[[scope]]</code> property of the |
+created function object still only contains the global object in the |
+assigned scope chain. |
+</p> |
+ |
+<p> |
+Inner function declarations and expressions result in function objects |
+being created within the execution context of a function so they get |
+more elaborate scope chains. Consider the following code, which defines |
+a function with an inner function declaration and then executes the |
+outer function:- |
+</p> |
+ |
+<pre> |
+function exampleOuterFunction(formalParameter){ |
+ function exampleInnerFuncitonDec(){ |
+ ... <span class="commentJS">// inner function body</span> |
+ } |
+ ... <span class="commentJS">// the rest of the outer function body.</span> |
+} |
+ |
+exampleOuterFunction( 5 ); |
+</pre> |
+ |
+<p> |
+The function object corresponding with the outer function declaration |
+is created during variable instantiation in the global execution context |
+so its <code>[[scope]]</code> property contains the one item scope |
+chain with only the global object in it. |
+</p> |
+ |
+<p> |
+When the global code executes the call to the |
+<code>exampleOuterFunction</code> a new execution context is created for |
+that function call and an Activation/Variable object along with it. |
+The <dfn>scope</dfn> of that new execution context becomes the chain consisting of |
+the new Activation object followed by the chain refereed to by the |
+outer function object's <code>[[scope]]</code> property (just the |
+global object). Variable instantiation for that new execution context |
+results in the creation of a function object that corresponds with the |
+inner function definition and the <code>[[scope]]</code> property of |
+that function object is assigned the value of the <dfn>scope</dfn> from the |
+execution context in which it was created. A <dfn>scope chain</dfn> that contains |
+the Activation object followed by the global object. |
+</p> |
+ |
+<p> |
+So far this is all automatic and controlled by the structure and |
+execution of the source code. The <dfn>scope chain</dfn> of the execution context |
+defines the <code>[[scope]]</code> properties of the function objects |
+created and the <code>[[scope]]</code> properties of the function |
+objects define the <dfn>scope</dfn> for their execution contexts (along with the |
+corresponding Activation object). But ECMAScript provides the |
+<code>with</code> statement as a means of modifying the scope chain. |
+</p> |
+ |
+<p> |
+The <code>with</code> statement evaluates an expression and if that |
+expression is an object it is added to the <dfn>scope chain</dfn> of the current |
+execution context (in front of the Activation/Variable object). The |
+<code>with</code> statement then executes another statement (that may |
+itself be a block statement) and then restores the execution context's |
+<dfn>scope chain</dfn>to what it was before. |
+</p> |
+ |
+<p> |
+A function declaration could not be affected by a <code>with</code> |
+statement as they result in the creation of function objects during |
+variable instantiation, but a function expression can be evaluated |
+inside a <code>with</code> statement:- |
+</p> |
+ |
+<pre> |
+<span class="commentJS">/* create a global variable - y - that refers to an object:- */</span> |
+var y = {x:5}; <span class="commentJS">// object literal with an - x - property</span> |
+function exampleFuncWith(){ |
+ var z; |
+ <span class="commentJS">/* Add the object referred to by the global variable - y - to the |
+ front of he scope chain:- |
+ */</span> |
+ with(y){ |
+ <span class="commentJS">/* evaluate a function expression to create a function object |
+ and assign a reference to that function object to the local |
+ variable - z - :- |
+ */</span> |
+ z = function(){ |
+ ... <span class="commentJS">// inner function expression body;</span> |
+ } |
+ } |
+ ... |
+} |
+ |
+<span class="commentJS">/* execute the - exampleFuncWith - function:- */</span> |
+exampleFuncWith(); |
+</pre> |
+ |
+<p> |
+When the <code>exampleFuncWith</code> function is called the resulting |
+execution context has a <dfn>scope chain</dfn> consisting of its Activation object |
+followed by the global object. The execution of the <code>with</code> |
+statement adds the object referred to by the global variable |
+<code>y</code> to the front of that <dfn>scope chain</dfn> during the evaluation |
+of the function expression. The function object created by the |
+evaluation of the function expression is assigned a |
+<code>[[scope]]</code> property that corresponds with the <dfn>scope</dfn> of the |
+execution context in which it is created. A <dfn>scope chain</dfn> consisting of |
+object <code>y</code> followed by the Activation object from the |
+execution context of the outer function call, followed by the global |
+object. |
+</p> |
+ |
+<p> |
+When the block statement associated with the <code>with</code> |
+statement terminates the <dfn>scope</dfn> of the execution context is restored |
+(the <code>y</code> object is removed), but the function object has |
+been created at that point and its <code>[[scope]]</code> property |
+assigned a reference to a <dfn>scope chain</dfn> with the <code>y</code> object |
+at its head. |
+</p> |
+ |
+<h3><a name="clIdRes" id="clIdRes">Identifier Resolution</a></h3> |
+ |
+<p> |
+Identifiers are resolved against the scope chain. ECMA 262 categorises |
+<code>this</code> as a keyword rather than an identifier, which is not |
+unreasonable as it is always resolved dependent on the |
+<code>this</code> value in the execution context in which it is used, |
+without reference to the scope chain. |
+</p> |
+ |
+<p> |
+Identifier resolution starts with the first object in the scope chain. |
+It is checked to see if it has a property with a name that corresponds |
+with the identifier. Because the <dfn>scope chain</dfn> is a chain of objects |
+this checking encompasses the prototype chain of that object (if it |
+has one). If no corresponding value can be found on the first object |
+in the <dfn>scope chain</dfn> the search progresses to the next object. And so on until |
+one of the objects in the chain (or one of its prototypes) has a |
+property with a name that corresponds with the identifier or the scope |
+chain is exhausted. |
+</p> |
+ |
+<p> |
+The operation on the identifier happens in the same way as the use of |
+property accessors on objects described above. The object identified |
+in the <dfn>scope chain</dfn> as having the corresponding property takes the |
+place of the object in the property accessor and the identifier acts |
+as a property name for that object. The global object is always at the |
+end of the scope chain. |
+</p> |
+ |
+<p> |
+As execution contexts associated with function calls will have the |
+Activation/Variable object at the front of the chain, identifiers used |
+in function bodies are effectively first checked to see whether they |
+correspond with formal parameters, inner function declaration names or |
+local variables. Those would be resolved as named properties of the |
+Activation/Variable object. |
+</p> |
+ |
+<h2><a name="clClose" id="clClose">Closures</a></h2> |
+ |
+<h3><a name="clAtGb" id="clAtGb">Automatic Garbage Collection</a></h3> |
+ |
+<p> |
+ECMAScript uses automatic garbage collection. The specification |
+does not define the details, leaving that to the implementers to sort |
+out, and some implementations are known to give a very low priority to |
+their garbage collection operations. But the general idea is that if an |
+object becomes un-referable (by having no remaining references to it |
+left accessible to executing code) it becomes available for garbage |
+collection and will at some future point be destroyed and any resources |
+it is consuming freed and returned to the system for re-use. |
+</p> |
+ |
+<p> |
+This would normally be the case upon exiting an execution context. The |
+<dfn>scope chain</dfn> structure, the Activation/Variable object and any objects |
+created within the execution context, including function objects, would |
+no longer be accessible and so would become available for garbage |
+collection. |
+</p> |
+ |
+<h3><a name="clFrmC" id="clFrmC">Forming Closures</a></h3> |
+ |
+<p> |
+A closure is formed by returning a function object that was created |
+within an execution context of a function call from that function call |
+and assigning a reference to that inner function to a property of another |
+object. Or by directly assigning a reference to such a function object |
+to, for example, a global variable, a property of a globally accessible |
+object or an object passed by reference as an argument to the outer |
+function call. e.g:- |
+</p> |
+ |
+<pre> |
+function exampleClosureForm(arg1, arg2){ |
+ var localVar = 8; |
+ function exampleReturned(innerArg){ |
+ return ((arg1 + arg2)/(innerArg + localVar)); |
+ } |
+ <span class="commentJS">/* return a reference to the inner function defined as - |
+ exampleReturned -:- |
+ */</span> |
+ return exampleReturned; |
+} |
+ |
+var globalVar = exampleClosureForm(2, 4); |
+</pre> |
+ |
+<p> |
+Now the function object created within the execution context of the |
+call to <code>exampleClosureForm</code> cannot be garbage collected |
+because it is referred to by a global variable and is still accessible, |
+it can even be executed with <code>globalVar(n)</code>. |
+</p> |
+ |
+<p> |
+But something a little more complicated has happened because the |
+function object now referred to by <code>globalVar</code> was created |
+with a <code>[[scope]]</code> property referring to a scope chain |
+containing the Activation/Variable object belonging to the execution |
+context in which it was created (and the global object). Now the |
+Activation/Variable object cannot be garbage collected either as the |
+execution of the function object referred to by <code>globalVar</code> |
+will need to add the whole <dfn>scope chain</dfn> from its <code>[[scope]]</code> |
+property to the <dfn>scope</dfn> of the execution context created for each call to |
+it. |
+</p> |
+ |
+<p> |
+A closure is formed. The inner function object has the free variables |
+and the Activation/Variable object on the function's <dfn>scope chain</dfn> is |
+the environment that binds them. |
+</p> |
+ |
+<p> |
+The Activation/Variable object is trapped by being |
+referred to in the <dfn>scope chain</dfn> assigned to the internal |
+<code>[[scope]]</code> property of the function object now referred to |
+by the <code>globalVar</code> variable. The Activation/Variable object |
+is preserved along with its state; the values of its properties. Scope |
+resolution in the execution context of calls to the inner function will |
+resolve identifiers that correspond with named properties of that |
+Activation/Variable object as properties of that object. The value of |
+those properties can still be read and set even though the execution |
+context for which it was created has exited. |
+</p> |
+ |
+<p> |
+In the example above that Activation/Variable object has a state that |
+represents the values of formal parameters, inner function definitions |
+and local variables, at the time when the outer function returned |
+(exited its execution context). The <code>arg1</code> property has the |
+value <code>2</code>,the <code>arg2</code> property the value |
+<code>4</code>, <code>localVar</code> the value <code>8</code> and an |
+<code>exampleReturned</code> property that is a reference to the inner |
+function object that was returned form the outer function. (We will be |
+referring to this Activation/Variable object as "ActOuter1" in later |
+discussion, for convenience.) |
+</p> |
+ |
+<p> |
+If the <code>exampleClosureForm</code> function was called again as:- |
+</p> |
+ |
+<pre> |
+var secondGlobalVar = exampleClosureForm(12, 3); |
+</pre> |
+ |
+<p> |
+- a new execution context would be created, along with a new Activation |
+object. And a new function object would be returned, with its own |
+distinct <code>[[scope]]</code> property referring to a scope chain |
+containing the Activation object form this second execution context, |
+with <code>arg1</code> being <code>12</code> and <code>arg2</code> |
+being <code>3</code>. (We will be referring to this Activation/Variable |
+object as "ActOuter2" in later discussion, for convenience.) |
+</p> |
+ |
+<p> |
+A second and distinct closure has been formed by the second execution |
+of <code>exampleClosureForm</code>. |
+</p> |
+ |
+<p> |
+The two function objects created by the execution of |
+<code>exampleClosureForm</code> to which references have been assigned |
+to the global variable <code>globalVar</code> and |
+<code>secondGlobalVar</code> respectively, return the expression |
+<code>((arg1 + arg2)/(innerArg + localVar))</code>. Which applies |
+various operators to four identifiers. How these identifiers are |
+resolved is critical to the use and value of closures. |
+</p> |
+ |
+<p> |
+Consider the execution of the function object referred to by |
+<code>globalVar</code>, as <code>globalVar(2)</code>. A new execution |
+context is created and an Activation object (we will call it |
+"ActInner1"), which is added to the head of the scope chain |
+referred to the <code>[[scope]]</code> property of the executed |
+function object. ActInner1 is given a property named |
+<code>innerArg</code>, after its formal parameter and the argument |
+value <code>2</code> assigned to it. The <dfn>scope chain</dfn> for this new |
+execution context is: <span class="scopeCh">ActInner1-></span> |
+<span class="scopeCh">ActOuter1-></span> |
+<span class="scopeCh">global object</span>. |
+</p> |
+ |
+<p> |
+Identifier resolution is done against the <dfn>scope chain</dfn> so in order |
+to return the value of the expression |
+<code>((arg1 + arg2)/(innerArg + localVar))</code> the values of the |
+identifiers will be determined by looking for properties, with names |
+corresponding with the identifiers, on each object in the scope chain |
+in turn. |
+</p> |
+ |
+<p> |
+The first object in the chain is ActInner1 and it has a property named |
+<code>innerArg</code> with the value <code>2</code>. All of the other |
+3 identifiers correspond with named properties of ActOuter1; |
+<code>arg1</code> is <code>2</code>, <code>arg2</code> is |
+<code>4</code> and <code>localVar</code> is <code>8</code>. The |
+function call returns <code>((2 + 4)/(2 + 8))</code>. |
+</p> |
+ |
+<p> |
+Compare that with the execution of the otherwise identical function |
+object referred to by <code>secondGlobalVar</code>, as |
+<code>secondGlobalVar(5)</code>. Calling the Activation object for |
+this new execution context "ActInner2", the scope chain |
+becomes: <span class="scopeCh">ActInner2-></span> |
+<span class="scopeCh">ActOuter2-></span> |
+<span class="scopeCh">global object</span>. ActInner2 returns |
+<code>innerArg</code> as <code>5</code> and ActOuter2 returns |
+<code>arg1</code>, <code>arg2</code> and <code>localVar</code> as |
+<code>12</code>, <code>3</code> and <code>8</code> respectively. The |
+value returned is <code>((12 + 3)/(5 + 8))</code>. |
+</p> |
+ |
+<p> |
+Execute <code>secondGlobalVar</code> again and a new Activation object |
+will appear at the front of the <dfn>scope chain</dfn> but ActOuter2 will still |
+be next object in the chain and the value of its named properties will |
+again be used in the resolution of the identifiers <code>arg1</code>, |
+<code>arg2</code> and <code>localVar</code>. |
+</p> |
+ |
+<p> |
+This is how ECMAScript inner functions gain, and maintain, access to the formal |
+parameters, declared inner functions and local variables of the |
+execution context in which they were created. And it is how the |
+forming of a closure allows such a function object to keep referring |
+to those values, reading and writing to them, for as long as it |
+continues to exist. The Activation/Variable object from the execution |
+context in which the inner function was created remains on the scope |
+chain referred to by the function object's <code>[[scope]]</code> |
+property, until all references to the inner function are freed and |
+the function object is made available for garbage collection (along |
+with any now unneeded objects on its scope chain). |
+</p> |
+ |
+<p> |
+Inner function may themselves have inner functions, and the inner |
+functions returned from the execution of functions to form closures |
+may themselves return inner functions and form closures of their own. |
+With each nesting the <dfn>scope chain</dfn> gains extra Activation objects |
+originating with the execution contexts in which the inner function |
+objects were created. The ECMAScript specification requires a scope |
+chain to be finite, but imposes no limits on their length. |
+Implementations probably do impose some practical limitation but no |
+specific magnitude has yet been reported. The potential for nesting |
+inner functions seems so far to have exceeded anyone's desire to |
+code them. |
+</p> |
+ |
+<h2><a name="clClDo" id="clClDo">What can be done with Closures?</a></h2> |
+ |
+<p> |
+Strangely the answer to that appears to be anything and everything. |
+I am told that closures enable ECMAScript to emulate anything, so the |
+limitation is the ability to conceive and implement the emulation. That |
+is a bit esoteric and it is probably better to start with something a |
+little more practical. |
+</p> |
+ |
+ |
+<h3><a name="clSto" id="clSto">Example 1: setTimeout with Function References</a></h3> |
+ |
+ |
+<p> |
+A common use for a closure is to provide parameters for the execution |
+of a function prior to the execution of that function. For example, |
+when a function is to be provided as the first argument to the |
+<code>setTimout</code> function that is common in web browser |
+environments. |
+</p> |
+ |
+<p> |
+<code>setTimeout</code> schedules the execution of a function (or a |
+string of javascript source code, but not in this context), provided as |
+its first argument, after an interval expressed in milliseconds (as its |
+second argument). If a piece of code wants to use |
+<code>setTimeout</code> it calls the <code>setTimeout</code> function |
+and passes a reference to a function object as the first argument and |
+the millisecond interval as the second, but a reference to a function |
+object cannot provide parameters for the scheduled execution of that |
+function. |
+</p> |
+ |
+<p> |
+However, code could call another function that returned a reference to |
+an inner function object, with that inner function object being passed |
+by reference to the <code>setTimeout</code> function. The parameters to |
+be used for the execution of the inner function are passed with the |
+call to the function that returns it. <code>setTimout</code> executes |
+the inner function without passing arguments but that inner function |
+can still access the parameters provided by the call to the outer |
+function that returned it:- |
+</p> |
+ |
+<pre> |
+function callLater(paramA, paramB, paramC){ |
+ <span class="commentJS">/* Return a reference to an anonymous inner function created |
+ with a function expression:- |
+ */</span> |
+ return (function(){ |
+ <span class="commentJS">/* This inner function is to be executed with - setTimeout |
+ - and when it is executed it can read, and act upon, the |
+ parameters passed to the outer function:- |
+ */</span> |
+ paramA[paramB] = paramC; |
+ }); |
+} |
+ |
+... |
+ |
+<span class="commentJS">/* Call the function that will return a reference to the inner function |
+ object created in its execution context. Passing the parameters that |
+ the inner function will use when it is eventually executed as |
+ arguments to the outer function. The returned reference to the inner |
+ function object is assigned to a local variable:- |
+*/</span> |
+var functRef = callLater(elStyle, "display", "none"); |
+<span class="commentJS">/* Call the setTimeout function, passing the reference to the inner |
+ function assigned to the - functRef - variable as the first argument:- |
+*/</span> |
+hideMenu=setTimeout(functRef, 500); |
+</pre> |
+ |
+<h3><a name="clObjI" id="clObjI">Example 2: Associating Functions with Object Instance Methods</a></h3> |
+ |
+<p> |
+There are many other circumstances when a reference to a function |
+object is assigned so that it would be executed at some future time |
+where it is useful to provide parameters for the execution of that |
+function that would not be easily available at the time of execution |
+but cannot be known until the moment of assignment. |
+</p> |
+ |
+<p> |
+One example might be a javascript object that is designed to |
+encapsulate the interactions with a particular DOM element. It has |
+<code>doOnClick</code>, <code>doMouseOver</code> and |
+<code>doMouseOut</code> methods and wants to execute those methods |
+when the corresponding events are triggered on the DOM element, but |
+there may be any number of instances of the javascript object created |
+associated with different DOM elements and the individual object |
+instances do not know how they will be employed by the code that |
+instantiated them. The object instances do not know how to reference |
+themselves globally because they do not know which global variables |
+(if any) will be assigned references to their instances. |
+</p> |
+ |
+<p> |
+So the problem is to execute an event handling function that has an |
+association with a particular instance of the javascript object, and |
+knows which method of that object to call. |
+</p> |
+ |
+<p> |
+The following example uses a small generalised closure based function |
+that associates object instances with element event handlers. |
+Arranging that the execution of the event handler calls the specified |
+method of the object instance, passing the event object and a reference |
+to the associated element on to the object method and returning the |
+method's return value. |
+</p> |
+ |
+<pre> |
+<span class="commentJS">/* A general function that associates an object instance with an event |
+ handler. The returned inner function is used as the event handler. |
+ The object instance is passed as the - obj - parameter and the name |
+ of the method that is to be called on that object is passed as the - |
+ methodName - (string) parameter. |
+*/</span> |
+function associateObjWithEvent(obj, methodName){ |
+ <span class="commentJS">/* The returned inner function is intended to act as an event |
+ handler for a DOM element:- |
+ */</span> |
+ return (function(e){ |
+ <span class="commentJS">/* The event object that will have been parsed as the - e - |
+ parameter on DOM standard browsers is normalised to the IE |
+ event object if it has not been passed as an argument to the |
+ event handling inner function:- |
+ */</span> |
+ e = e||window.event; |
+ <span class="commentJS">/* The event handler calls a method of the object - obj - with |
+ the name held in the string - methodName - passing the now |
+ normalised event object and a reference to the element to |
+ which the event handler has been assigned using the - this - |
+ (which works because the inner function is executed as a |
+ method of that element because it has been assigned as an |
+ event handler):- |
+ */</span> |
+ return obj[methodName](e, this); |
+ }); |
+} |
+ |
+<span class="commentJS">/* This constructor function creates objects that associates themselves |
+ with DOM elements whose IDs are passed to the constructor as a |
+ string. The object instances want to arrange than when the |
+ corresponding element triggers onclick, onmouseover and onmouseout |
+ events corresponding methods are called on their object instance. |
+*/</span> |
+function DhtmlObject(elementId){ |
+ <span class="commentJS">/* A function is called that retrieves a reference to the DOM |
+ element (or null if it cannot be found) with the ID of the |
+ required element passed as its argument. The returned value |
+ is assigned to the local variable - el -:- |
+ */</span> |
+ var el = getElementWithId(elementId); |
+ <span class="commentJS">/* The value of - el - is internally type-converted to boolean for |
+ the - if - statement so that if it refers to an object the |
+ result will be true, and if it is null the result false. So that |
+ the following block is only executed if the - el - variable |
+ refers to a DOM element:- |
+ */</span> |
+ if(el){ |
+ <span class="commentJS">/* To assign a function as the element's event handler this |
+ object calls the - associateObjWithEvent - function |
+ specifying itself (with the - this - keyword) as the object |
+ on which a method is to be called and providing the name of |
+ the method that is to be called. The - associateObjWithEvent |
+ - function will return a reference to an inner function that |
+ is assigned to the event handler of the DOM element. That |
+ inner function will call the required method on the |
+ javascript object when it is executed in response to |
+ events:- |
+ */</span> |
+ el.onclick = associateObjWithEvent(this, "doOnClick"); |
+ el.onmouseover = associateObjWithEvent(this, "doMouseOver"); |
+ el.onmouseout = associateObjWithEvent(this, "doMouseOut"); |
+ ... |
+ } |
+} |
+DhtmlObject.prototype.doOnClick = function(event, element){ |
+ ... <span class="commentJS">// doOnClick method body</span>. |
+} |
+DhtmlObject.prototype.doMouseOver = function(event, element){ |
+ ... <span class="commentJS">// doMouseOver method body.</span> |
+} |
+DhtmlObject.prototype.doMouseOut = function(event, element){ |
+ ... <span class="commentJS">// doMouseOut method body.</span> |
+} |
+</pre> |
+ |
+<p> |
+And so any instances of the <code>DhtmlObject</code> can associate themselves |
+with the DOM element that they are interested in without any need |
+to know anything about how they are being employed by other code, |
+impacting on the global namespace or risking clashes with other |
+instances of the <code>DhtmlObject</code>. |
+</p> |
+ |
+<h3><a name="clEncap" id="clEncap">Example 3: Encapsulating Related Functionality</a></h3> |
+ |
+<p> |
+Closures can be used to create additional scopes that can be used to |
+group interrelated and dependent code in a way that minimises the risk |
+of accidental interaction. Suppose a function is to build a string and |
+to avoid the repeated concatenation operations (and the creation of |
+numerous intermediate strings) the desire is to use an array to store |
+the parts of the string in sequence and then output the results using |
+the <code>Array.prototype.join</code> method (with an empty string as its argument). |
+The array is going to act as a buffer for the output, but defining it |
+locally to the function will result in its re-creation on each |
+execution of the function, which may not be necessary if the only |
+variable content of that array will be re-assigned on each function |
+call. |
+</p> |
+ |
+<p> |
+One approach might make the array a global variable so that it can be |
+re-used without being re-created. But the consequences of that will be |
+that, in addition to the global variable that refers to the function |
+that will use the buffer array, there will be a second global property |
+that refers to the array itself. The effect is to render the code less |
+manageable, as, if it is to be used elsewhere, its author has to remember |
+to include both the function definition and the array definition. It |
+also makes the code less easy to integrate with other code because |
+instead of just ensuring that the function name is unique within the |
+global namespace it is necessary to ensure that the Array on which it |
+is dependent is using a name that is unique within the global |
+namespace. |
+</p> |
+ |
+<p> |
+A Closure allows the buffer array to be associated (and neatly |
+packaged) with the function that is dependent upon it and |
+simultaneously keep the property name to which the buffer array as |
+assigned out of the global namespace and free of the risk of name |
+conflicts and accidental interactions. |
+</p> |
+ |
+<p> |
+The trick here is to create one additional execution context by |
+executing a function expression in-line and have that function |
+expression return an inner function that will be the function that is |
+used by external code. The buffer array is then defined as a local |
+variable of the function expression that is executed in-line. That only |
+happens once so the Array is only created once, but is available to |
+the function that depends on it for repeated use. |
+</p> |
+ |
+<p> |
+The following code creates a function that will return a string of |
+<span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span>, much of which is constant, but those constant character |
+sequences need to be interspersed with variable information provided |
+as parameter to the function call. |
+</p> |
+ |
+<p> |
+A reference to an inner function object is returned from the in-line |
+execution of a function expression and assigned to a global variable |
+so that it can be called as a global function. The buffer array is |
+defined as a local variable in the outer function expression. It is |
+not exposed in the global namespace and does not need to be re-created |
+whenever the function that uses it is called. |
+</p> |
+ |
+<pre> |
+<span class="commentJS">/* A global variable - getImgInPositionedDivHtml - is declared and |
+ assigned the value of an inner function expression returned from |
+ a one-time call to an outer function expression. |
+ |
+ That inner function returns a string of <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> that represents an |
+ absolutely positioned DIV wrapped round an IMG element, such that |
+ all of the variable attribute values are provided as parameters |
+ to the function call:- |
+*/</span> |
+var getImgInPositionedDivHtml = (function(){ |
+ <span class="commentJS">/* The - buffAr - Array is assigned to a local variable of the |
+ outer function expression. It is only created once and that one |
+ instance of the array is available to the inner function so that |
+ it can be used on each execution of that inner function. |
+ |
+ Empty strings are used as placeholders for the date that is to |
+ be inserted into the Array by the inner function:- |
+ */</span> |
+ var buffAr = [ |
+ '<div id="', |
+ '', <span class="commentJS">//index 1, DIV ID attribute</span> |
+ '" style="position:absolute;top:', |
+ '', <span class="commentJS">//index 3, DIV top position</span> |
+ 'px;left:', |
+ '', <span class="commentJS">//index 5, DIV left position</span> |
+ 'px;width:', |
+ '', <span class="commentJS">//index 7, DIV width</span> |
+ 'px;height:', |
+ '', <span class="commentJS">//index 9, DIV height</span> |
+ 'px;overflow:hidden;\"><img src=\"', |
+ '', <span class="commentJS">//index 11, IMG URL</span> |
+ '\" width=\"', |
+ '', <span class="commentJS">//index 13, IMG width</span> |
+ '\" height=\"', |
+ '', <span class="commentJS">//index 15, IMG height</span> |
+ '\" alt=\"', |
+ '', <span class="commentJS">//index 17, IMG alt text</span> |
+ '\"><\/div>' |
+ ]; |
+ <span class="commentJS">/* Return the inner function object that is the result of the |
+ evaluation of a function expression. It is this inner function |
+ object that will be executed on each call to - |
+ getImgInPositionedDivHtml( ... ) -:- |
+ */</span> |
+ return (function(url, id, width, height, top, left, altText){ |
+ <span class="commentJS">/* Assign the various parameters to the corresponding |
+ locations in the buffer array:- |
+ */</span> |
+ buffAr[1] = id; |
+ buffAr[3] = top; |
+ buffAr[5] = left; |
+ buffAr[13] = (buffAr[7] = width); |
+ buffAr[15] = (buffAr[9] = height); |
+ buffAr[11] = url; |
+ buffAr[17] = altText; |
+ <span class="commentJS">/* Return the string created by joining each element in the |
+ array using an empty string (which is the same as just |
+ joining the elements together):- |
+ */</span> |
+ return buffAr.join(''); |
+ }); <span class="commentJS">//:End of inner function expression.</span> |
+})(); |
+<span class="commentJS">/*^^- :The inline execution of the outer function expression. */</span> |
+</pre> |
+ |
+<p> |
+If one function was dependent on one (or several) other functions, but |
+those other functions were not expected to be directly employed by any |
+other code, then the same technique could be used to group those |
+functions with the one that was to be publicly exposed. Making a |
+complex multi-function process into an easily portable and encapsulated |
+unit of code. |
+</p> |
+ |
+<h3><a name="clOtE" id="clOtE">Other Examples</a></h3> |
+ |
+<p> |
+Probably one of the best known applications of closures is |
+<a href="http://www.crockford.com/javascript/private.html">Douglas |
+Crockford's technique for the emulation of private instance variables |
+in ECMAScript objects</a>. Which can be extended to all sorts of |
+structures of <dfn>scope</dfn> contained nested accessibility/visibility, including |
+<a href="http://myweb.tiscali.co.uk/cornford/js_info/private_static.html"> |
+the emulation of private static members for ECMAScript objects</a>. |
+</p> |
+ |
+<p> |
+The possible application of closures are endless, understanding how |
+they work is probably the best guide to realising how they can be |
+used. |
+</p> |
+ |
+<h2 id="clAc">Accidental Closures</h2> |
+ |
+<p> |
+Rendering any inner function accessible outside of the body of the |
+function in which it was created will form a closure. That makes |
+closures very easy to create and one of the consequences is that |
+javascript authors who do not appreciate closures as a language feature |
+can observe the use of inner functions for various tasks and employ |
+inner functions, with no apparent consequences, not realising that |
+closures are being created or what the implications of doing that are. |
+</p> |
+ |
+<p> |
+Accidentally creating closures can have harmful side effects as the |
+following section on the IE memory leak problem describes, but they can |
+also impact of the efficiency of code. It is not the closures |
+themselves, indeed carefully used they can contribute significantly |
+towards the creation of efficient code. It is the use of inner |
+functions that can impact on efficiency. |
+</p> |
+ |
+<p> |
+A common situation is where inner functions are used is as event |
+handlers for DOM elements. For example the following code might be used |
+to add an onclick handler to a link element:- |
+</p> |
+ |
+<pre> |
+<span class="commentJS">/* Define the global variable that is to have its value added to the |
+ - href - of a link as a query string by the following function:- |
+*/</span> |
+var quantaty = 5; |
+<span class="commentJS">/* When a link passed to this function (as the argument to the function |
+ call - linkRef -) an onclick event handler is added to the link that |
+ will add the value of a global variable - quantaty - to the - href - |
+ of that link as a query string, then return true so that the link |
+ will navigate to the resource specified by the - href - which will |
+ by then include the assigned query string:- |
+*/</span> |
+function addGlobalQueryOnClick(linkRef){ |
+ <span class="commentJS">/* If the - linkRef - parameter can be type converted to true |
+ (which it will if it refers to an object):- |
+ */</span> |
+ if(linkRef){ |
+ <span class="commentJS">/* Evaluate a function expression and assign a reference to the |
+ function object that is created by the evaluation of the |
+ function expression to the onclick handler of the link |
+ element:- |
+ */</span> |
+ linkRef.onclick = function(){ |
+ <span class="commentJS">/* This inner function expression adds the query string to |
+ the - href - of the element to which it is attached as |
+ an event handler:- |
+ */</span> |
+ this.href += ('?quantaty='+escape(quantaty)); |
+ return true; |
+ }; |
+ } |
+} |
+</pre> |
+ |
+<p> |
+Whenever the <code>addGlobalQueryOnClick</code> function is called a |
+new inner function is created (and a closure formed by its assignment). |
+From the efficiency point of view that would not be significant if the |
+<code>addGlobalQueryOnClick</code> function was only called once or |
+twice, but if the function was heavily employed many distinct function |
+objects would be created (one for each evaluation of the inner function |
+expression). |
+</p> |
+ |
+<p> |
+The above code is not taking advantage of the fact that inner functions |
+are becoming accessible outside of the function in which they are being |
+created (or the resulting closures). As a result exactly the same effect |
+could be achieved by defining the function that is to be used as the |
+event handler separately and then assigning a reference to that |
+function to the event handling property. Only one function object would |
+be created and all of the elements that use that event handler would |
+share a reference to that one function:- |
+</p> |
+ |
+<pre> |
+<span class="commentJS">/* Define the global variable that is to have its value added to the |
+ - href - of a link as a query string by the following function:- |
+*/</span> |
+var quantaty = 5; |
+ |
+<span class="commentJS">/* When a link passed to this function (as the argument to the function |
+ call - linkRef -) an onclick event handler is added to the link that |
+ will add the value of a global variable - quantaty - to the - href - |
+ of that link as a query string, then return true so that the link |
+ will navigate to the resource specified by the - href - which will |
+ by then include the assigned query string:- |
+*/</span> |
+function addGlobalQueryOnClick(linkRef){ |
+ <span class="commentJS">/* If the - linkRef - parameter can be type converted to true |
+ (which it will if it refers to an object):- |
+ */</span> |
+ if(linkRef){ |
+ <span class="commentJS">/* Assign a reference to a global function to the event |
+ handling property of the link so that it becomes the |
+ element's event handler:- |
+ */</span> |
+ linkRef.onclick = forAddQueryOnClick; |
+ } |
+} |
+<span class="commentJS">/* A global function declaration for a function that is intended to act |
+ as an event handler for a link element, adding the value of a global |
+ variable to the - href - of an element as an event handler:- |
+*/</span> |
+function forAddQueryOnClick(){ |
+ this.href += ('?quantaty='+escape(quantaty)); |
+ return true; |
+} |
+</pre> |
+ |
+<p> |
+As the inner function in the first version is not being used to exploit |
+the closures produced by its use, it would be more efficient not to use |
+an inner function, and thus not repeat the process of creating many |
+essentially identical function objects. |
+</p> |
+ |
+<p> |
+A similar consideration applies to object constructor functions. It is |
+not uncommon to see code similar to the following skeleton constructor:- |
+</p> |
+ |
+ |
+<pre> |
+function ExampleConst(param){ |
+ <span class="commentJS">/* Create methods of the object by evaluating function expressions |
+ and assigning references to the resulting function objects |
+ to the properties of the object being created:- |
+ */</span> |
+ this.method1 = function(){ |
+ ... <span class="commentJS">// method body.</span> |
+ }; |
+ this.method2 = function(){ |
+ ... <span class="commentJS">// method body.</span> |
+ }; |
+ this.method3 = function(){ |
+ ... <span class="commentJS">// method body.</span> |
+ }; |
+ <span class="commentJS">/* Assign the constructor's parameter to a property of the object:- |
+ */</span> |
+ this.publicProp = param; |
+} |
+</pre> |
+ |
+<p> |
+Each time the constructor is used to create an object, with |
+<code>new ExampleConst(n)</code>, a new set of function objects are |
+created to act as its methods. So the more object instances that are |
+created the more function objects are created to go with them. |
+</p> |
+ |
+<p> |
+Douglas Crockford's technique for emulating private members on |
+javascript objects exploits the closure resulting form assigning |
+references to inner function objects to the public properties of a |
+constructed object from within its constructor. But if the methods of |
+an object are not taking advantage of the closure that they will form |
+within the constructor the creation of multiple function objects for |
+each object instantiation will make the instantiation process slower |
+and more resources will be consumed to accommodate the extra function |
+objects created. |
+</p> |
+ |
+<p> |
+In that case it would be more efficient to create the function object |
+once and assign references to them to the corresponding properties of |
+the constructor's <code>prototype</code> so they may be shared by all |
+of the objects created with that constructor:- |
+</p> |
+ |
+<pre> |
+function ExampleConst(param){ |
+ <span class="commentJS">/* Assign the constructor's parameter to a property of the object:- |
+ */</span> |
+ this.publicProp = param; |
+} |
+<span class="commentJS">/* Create methods for the objects by evaluating function expressions |
+ and assigning references to the resulting function objects to the |
+ properties of the constructor's prototype:- |
+*/</span> |
+ExampleConst.prototype.method1 = function(){ |
+ ... <span class="commentJS">// method body.</span> |
+}; |
+ExampleConst.prototype.method2 = function(){ |
+ ... <span class="commentJS">// method body.</span> |
+}; |
+ExampleConst.prototype.method3 = function(){ |
+ ... <span class="commentJS">// method body.</span> |
+}; |
+ |
+</pre> |
+<h2><a name="clMem" id="clMem">The Internet Explorer Memory Leak Problem</a></h2> |
+ |
+<p> |
+The Internet Explorer web browser (verified on versions 4 to 6 (6 is |
+current at the time of writing)) has a fault in its garbage collection |
+system that prevents it from garbage collecting ECMAScript and some |
+host objects if those host objects form part of a "circular" |
+reference. The host objects in question are any DOM Nodes (including |
+the document object and its descendants) and ActiveX objects. If a |
+circular reference is formed including one or more of them, then |
+none of the objects involved will be freed until the browser is closed |
+down, and the memory that they consume will be unavailable to the |
+system until that happens. |
+</p> |
+ |
+<p> |
+A circular reference is when two or more objects refer to each other in |
+a way that can be followed and lead back to the starting point. Such |
+as object 1 has a property that refers to object 2, object 2 has a |
+property that refers to object 3 and object 3 has a property that |
+refers back to object 1. With pure ECMAScript objects as soon as no |
+other objects refer to any of objects 1, 2 or 3 the fact that they only |
+refer to each other is recognised and they are made available for |
+garbage collection. But on Internet Explorer, if any of those objects |
+happen to be a DOM Node or ActiveX object, the garbage collection |
+cannot see that the circular relationship between them is isolated |
+from the rest of the system and free them. Instead they all stay in |
+memory until the browser is closed. |
+</p> |
+ |
+<p> |
+Closures are extremely good at forming circular references. If a |
+function object that forms a closure is assigned as, for example, and |
+event handler on a DOM Node, and a reference to that Node is assigned |
+to one of the Activation/Variable objects in its <dfn>scope chain</dfn> then a |
+circular reference exists. |
+<span class="scopeCh">DOM_Node.onevent -></span> |
+<span class="scopeCh">function_object.[[scope]] -></span> |
+<span class="scopeCh">scope_chain -></span> |
+<span class="scopeCh">Activation_object.nodeRef -></span> |
+<span class="scopeCh">DOM_Node</span>. |
+It is very easy to do, and a bit of browsing around a site that forms |
+such a reference in a piece of code common to each page can consume |
+most of the systems memory (possibly all). |
+</p> |
+ |
+<p> |
+Care can be taken to avoid forming circular references and remedial |
+action can be taken when they cannot otherwise be avoided, such as |
+using IE's onunload event to null event handling function |
+references. Recognising the problem and understanding closures |
+(and their mechanism) is the key to avoiding this problem with IE. |
+</p> |
+ |
+<p id="rToc"> |
+<a href="faq_notes.html#toc">comp.lang.javascript FAQ notes T.O.C.</a> |
+</p> |
+ |
+<ul style="list-style-type:none;margin-top:2.5em;"> |
+ <li>Written by <span class="person">Richard Cornford</span>. March 2004.</li> |
+ <li>With corrections and suggestions by:-<br> |
+ <ul style="list-style-type:none;"> |
+ <li><span class="person">Martin Honnen</span>.</li> |
+ <li><span class="person">Yann-Erwan Perio (Yep)</span>.</li> |
+ <li><span class="person">Lasse Reichstein Nielsen</span>. (<a href="#clDefN">definition of closure</a>)</li> |
+ <li><span class="person">Mike Scirocco</span>.</li> |
+ <li><span class="person">Dr John Stockton</span>.</li> |
+ <li><span class="person">Garrett Smith</span>.</li> |
+ </ul> |
+ </li> |
+</ul> |
+</body> |
+</html> |
/cljs/notes/closures/index.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/notes/notes.css |
=================================================================== |
--- cljs/notes/notes.css (nonexistent) |
+++ cljs/notes/notes.css (revision 2) |
@@ -0,0 +1,34 @@ |
+#contTable { |
+ font-size: 120%; |
+} |
+#contTable, #contTable li dt { |
+ font-weight: bold; |
+} |
+ |
+#contTable dl { |
+ margin-left: 1.1em; |
+ font-size: 86%; |
+} |
+ |
+#contTable dl * { |
+ margin-left: 0; |
+ padding-left: 0; |
+} |
+ |
+#contTable dl dd { |
+ margin-left: 2.2em; |
+} |
+ |
+#contTable li * { |
+ font-weight: normal; |
+} |
+ |
+div { |
+ background: transparent; |
+ border: 0; |
+ padding: 0; |
+} |
+ |
+#faqNav a { |
+ font-weight: 700; |
+} |
/cljs/notes/notes.css |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/notes/code-guidelines/asi.html |
=================================================================== |
--- cljs/notes/code-guidelines/asi.html (nonexistent) |
+++ cljs/notes/code-guidelines/asi.html (revision 2) |
@@ -0,0 +1,152 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" |
+ "http://www.w3.org/TR/html4/strict.dtd"> |
+<html lang="en"> |
+<head> |
+<meta http-equiv="Content-type" content="text/html;charset=UTF-8"> |
+ |
+<link rel="schema.DC" href="http://www.purl.org/dc/elements/1.1/"> |
+ |
+<meta name="DC.title" lang="en" content="Automatic Semicolon Insertion - Unrestricted Productions"> |
+<meta name="DC.date" scheme="W3CDTF" content="2010-05-29"> |
+ |
+<meta name="DC.source" content="http://www.ecma-international.org/publications/standards/Ecma-262.htm"> |
+<meta name="DC.publisher" content="Garrett Smith"> |
+<meta name="DC.Publisher.Address" content="dhtmlkitchen@gmail.com"> |
+<meta name="DCTERMS.audience" content="Programmers, web developers"> |
+<meta name="DC.description" content="How Automatic Semicolon Insertion affects an ECMAScript program."> |
+<meta name="DC.source" content="http://www.ecma-international.org/publications/standards/Ecma-262.htm"> |
+<meta name="DCTERMS.language" scheme="RFC1766" content="en"> |
+<link rel="DCTERMS.isReferencedBy" href="./#asi" > |
+ |
+<meta name="DC.source" content="news:comp.lang.javascript"> |
+ |
+<link href="../../faq.css" rel="stylesheet" type="text/css"> |
+<link href="../notes.css" rel="stylesheet" type="text/css"> |
+<title>Automatic Semicolon Insertion - Unrestricted Productions</title> |
+</head> |
+<body> |
+<h1>Automatic Semicolon Insertion</h1> |
+<p> |
+ Article by Garrett Smith |
+</p> |
+<p> |
+ This document is an addendum to <a href="./#asi" |
+ >Code Guidelines for Rich Internet Application Development</a>. |
+</p> |
+<h2>Unrestricted Productions</h2> |
+<p> |
+ Productions that are not <dfn>restricted</dfn> can be created accidentally where |
+ <abbr title="automatic semicolon insertion">ASI</abbr> has been used. This is often |
+ the result of where the developer forgot to use a |
+ semicolon. Regardless, the problems it creates can occur when the order of <dfn>Statements</dfn> |
+ changes or when line terminators are added or removed, including those that appear in comments. |
+ Where semicolons are needed, it is recommended that they appear explicitly. |
+</p> |
+<ul> |
+ <li> |
+ <dfn>Arguments</dfn> and property access operations can be created accidentally when the |
+ program relies on <abbr title="automatic semicolon insertion">ASI</abbr>. |
+ </li> |
+ <li> |
+ Line terminators in comments affect <abbr title="automatic semicolon insertion">ASI</abbr> but behavior in implementations, |
+ notably JScript, vary. |
+ </li> |
+ </ul> |
+ <h3>Grouping Operator or Arguments?</h3> |
+ <p> |
+ The parentheses following an <dfn>Expression</dfn> |
+ interpreted as <dfn>Arguments</dfn>, implicating the <dfn>Expression</dfn> in |
+ a <dfn>CallExpression</dfn>: |
+ </p> |
+<pre>var MyWidget = function(){ |
+ this.name = "mike"; |
+} |
+/** |
+ * Initialize Widget |
+ */ |
+(function() { |
+ /*...*/ |
+});</pre> |
+ <p> |
+ |
+ The <dfn>FunctionExpression</dfn> that appears on the right hand side of the assignment |
+ to the identifier <code>MyWidget</code> would be called because the parentheses, |
+ which were intended to be a <dfn>Grouping Operator</dfn>, are interpreted as <dfn>Arguments</dfn> |
+ in a <dfn>CallExpression</dfn>, resulting in <code>MyWidget</code> having the value |
+ <code>undefined</code> and <code>window.name</code> getting the value <code>"mike"</code>. |
+ </p> |
+ |
+ <p> |
+ This can be explained by the fact that a program is scanned from left to right, |
+ repeatedly taking the longest possible sequence of characters as the next input element. |
+ Since a <dfn>CallExpression</dfn> is not a <dfn>restricted production</dfn>, the program |
+ would be interpreted as: |
+ </p> |
+ <pre> |
+var MyWidget = function(){ |
+ this.name = "mike"; |
+}(function() {}); |
+</pre> |
+<h3>ArrayLiteral or Property Accessor?</h3> |
+<p> |
+An <dfn>ArrayLiteral</dfn> can be interpreted as property accessor after the |
+removal of a <dfn>restricted production</dfn>. In this case, <dfn>Expression</dfn> <code>g--</code>. |
+</p> |
+<pre> |
+var g = 12 |
+g-- |
+[].slice.call([1,2,3])</pre> |
+<p> |
+The program is interpreted as: |
+</p> |
+<pre> |
+var g = 12<kbd>;</kbd> |
+g--<kbd>;</kbd> |
+[].slice.call([1,2,3]) |
+</pre> |
+<p> |
+When the postfix operator is removed, a <dfn>SyntaxError</dfn> results. Given the input: |
+</p> |
+<pre> |
+var g = 12 |
+--g |
+[].slice.call([1,2,3]) |
+</pre> |
+<p>The program is interpreted as:-</p> |
+<pre> |
+var g = 12; |
+--g[].slice.call([1,2,3]) |
+</pre> |
+<p> |
+- and that program is not valid syntax so it results in a <dfn>SyntaxError</dfn>. |
+</p> |
+<h3>Line Terminators in Comments</h3> |
+<p> |
+ A LineTerminator in any <dfn>MultilineComment</dfn> affects |
+ <abbr title="automatic semicolon insertion">ASI</abbr>. From ECMAScript Edition 5 specification, 5.1.2: |
+</p> |
+<blockquote> |
+<p> |
+ A <dfn>MultiLineComment</dfn> (that is, a comment of the form /*...*/ |
+ regardless of whether it spans more than one line) is likewise simply |
+ discarded if it contains no line terminator; but if a <dfn>MultiLineComment</dfn> |
+ contains one or more line terminators, then it is replaced by a single |
+ line terminator, which becomes part of the stream of input elements |
+ for the syntactic grammar. |
+</p> |
+</blockquote> |
+ |
+<p> |
+ Not all implementations follow rules of whitespace in MultiLineComment. JScript is one |
+ such implementation that does not process a <dfn>MultiLineComment</dfn> that contains |
+ a <dfn>LineTerminator</dfn> as a <dfn>LineTerminator</dfn>. |
+</p> |
+<p> |
+ A program that uses semicolons explicitly avoids such problems and is less |
+ susceptible to behavior changes (including script errors) caused by inadvertent changes in |
+ line terminators and expressions, including those introduced |
+ by build tools (e.g. minficication). |
+</p> |
+ |
+</body> |
+</html> |
/cljs/notes/code-guidelines/asi.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/notes/code-guidelines/index.html |
=================================================================== |
--- cljs/notes/code-guidelines/index.html (nonexistent) |
+++ cljs/notes/code-guidelines/index.html (revision 2) |
@@ -0,0 +1,615 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" |
+ "http://www.w3.org/TR/html4/strict.dtd"> |
+<html lang="en"> |
+<head> |
+<meta http-equiv="Content-type" content="text/html;charset=UTF-8"> |
+<title>Code Guidelines for Rich Internet Application Development</title> |
+ |
+<link rel="schema.DC" href="http://www.purl.org/dc/elements/1.1/"> |
+<meta name="DC.title" lang="en" content="Code Guidlines for Rich Internet Applications"> |
+<meta name="DC.date" scheme="W3CDTF" content="2010-05-29"> |
+<meta name="DC.source" content="http://www.ecma-international.org/publications/standards/Ecma-262.htm"> |
+<meta name="DC.publisher" content="Garrett Smith"> |
+<meta name="DC.Publisher.Address" content="dhtmlkitchen@gmail.com"> |
+<meta name="DCTERMS.audience" content="Programmers, web developers"> |
+<meta name="DC.description" content="Guidlines and Best Practices for javascript (ECMAScript) in web applications."> |
+<meta name="DC.source" content="http://www.ecma-international.org/publications/standards/Ecma-262.htm"> |
+<meta name="DC.source" content="http://www.w3.org/TR/html4/"> |
+ |
+<meta name="DCTERMS.language" scheme="RFC1766" content="en"> |
+<link rel="DCTERMS.isReferencedBy" href="/faq/notes/" > |
+ |
+<meta name="DC.source" content="news:comp.lang.javascript"> |
+ |
+ |
+<link href="../../faq.css" rel="stylesheet" type="text/css"> |
+<link href="../notes.css" rel="stylesheet" type="text/css"> |
+<style type="text/css"> |
+li { |
+ font-weight: bold; |
+} |
+li p, li div, ul ul ul li { |
+ font-weight: normal; |
+} |
+h4 { |
+ margin: .5ex; |
+ font-size: 1em; |
+} |
+</style> |
+ |
+</head> |
+<body> |
+<h1>Code Guidelines for Rich Internet Application Development</h1> |
+<div id="faqNav"> |
+ <a href="../../">FAQ</a> > <a href="../">FAQ Notes</a> |
+</div> |
+<p> |
+By Garrett Smith, with contributions from Asen Bozhilov, RobG, John G Harris, David Mark, and Dmitry Soshnikov. |
+</p> |
+<h2>Abstract</h2> |
+<p> |
+ This document points to the causes of errors and problems related to javascript |
+ for web applications and provides explanation of what to do instead. |
+</p> |
+<p> |
+ When followed, these guidelines can improve the code |
+ stability and maintainability of a Rich Internet Application deployed |
+ across a wide range of web browsers. |
+</p> |
+<p> |
+ For code reviews, this document and the |
+ <a href="../review/">Code Review Guidelines</a> should be read by the code author and code reviewer. |
+</p> |
+<h2>Guidelines</h2> |
+<ul> |
+ <li>Markup |
+ <ul> |
+ <li> |
+ <p>Use valid html <a href="http://validator.w3.org">validator.w3.org</a>.</p> |
+ <p> |
+ Code that uses malformed, nonconforming HTML is expecting nonstandard behavior. |
+ When a web browser encounters a problem in HTML, it must perform error correction. |
+ Since there are no error correction mechanisms defined in HTML 4, browsers |
+ handle the problem in proprietary ways. |
+ </p> |
+ <p> |
+ When the browser parses a document, it creates a DOM representation of it. |
+ If the browser performed error correction when parsing, the outcome is a |
+ different DOM. For an example with a detailed explanation, see: |
+ <a href="http://ln.hixie.ch/?start=1037910467&count=1" |
+ >Tag Soup: How UAs handle <x> <y> </x> </y></a> |
+ and also <a href="http://jibbering.com/faq/notes/detect-browser/#bdValid" |
+ >Avoiding Structural Differences in the Browser DOMs</a>. |
+ </p> |
+ <p> |
+ The W3C validator results either with green <code>PASS</code> or with one or more errors |
+ at which point it is clear that the code is not completed to |
+ standard. |
+ </p> |
+ </li> |
+ <li> |
+ <p>Use standards mode, with HTML <code>DOCTYPE</code> first (neither comments nor xml declaration preceeding it).</p> |
+ </li> |
+ <li> |
+ <p>Reduce the markup to simplest semantic markup necessary.</p> |
+ <p>Simpler code is easier to read.</p> |
+ <p> |
+ More markup means more bytes transferred over the wire, |
+ more parsing for the browser, and a larger DOM for scripts |
+ to traverse. |
+ </p> |
+ </li> |
+ <li><p>Set the HTTP content-type text/html.</p></li> |
+ <li> |
+ <p>Set charset in HTTP or, if using a <code>META</code> tag, as |
+ <a href="http://www.w3.org/TR/html4/charset.html#spec-char-encoding">early as possible</a> |
+ in the <code>HEAD</code>. |
+ </p> |
+ </li> |
+ <li> |
+ <p> |
+ Escape ETAGO delimiter with backwards solidus (backslash). |
+ See also : <a href="http://www.cs.tut.fi/~jkorpela/www/revsol.html" |
+ >The reverse solidus (backslash, <code>\</code>) in Web authoring</a>. |
+ </p> |
+ <p> |
+ A reverse solidus (backslash) should appear before the solidus |
+ symbol in the sequence "</", resulting in "<\/", and not "<" + "/". |
+ <a href="http://www.w3.org/TR/html4/appendix/notes.html#h-B.3.2.1" |
+ >ETAGO in SCRIPT and STYLE</a>. |
+ </p> |
+ </li> |
+ <li> |
+ <p> |
+ Do not use <code>javascript:</code> pseudo protocol. |
+ <a href="../../#javascriptURI">FAQ: I have <a href="javascript:somefunction()"> what ... ?</a> |
+ </p> |
+ </li> |
+ </ul> |
+ <h3>Validation Note</h3> |
+ <p> |
+ The <a href="http://validator.w3.org/docs/help.html#validandconform">W3C |
+ validator does not validate conformance</a>. Conformance errors can |
+ cause problems and must be recognized and corrected. See also: |
+ <a href="http://www.w3.org/TR/html4/appendix/notes.html#notes-invalid-docs" |
+ >Appendix B: Performance, Implementation, and Design Notes: Invalid Documents</a>, |
+ which states <cite>This specification does not define how conforming |
+ user agents handle general error conditions...</cite> |
+ </p> |
+ |
+ <p> |
+ When the code does not do what is wanted of it, it is important to understand |
+ why. The HTML validator can help because it can report HTML errors (and much more quickly |
+ than a tired human eye could). |
+ </p> |
+ |
+ <p> |
+ Poring over a long list of validation errors to find the validation error(s) |
+ that could be related to the code not doing what is wanted of it is error-prone, |
+ time-consuming guesswork. When an HTML error is found, the next task is finding |
+ when that error crept in, why it is there, what other code is relying |
+ on the problematic area, who wrote that other code, where is he now, so a |
+ possible fix can be discussed, etc. Using invalid HTML is a waste of time. |
+ Instead, by always using valid HTML, clear expectations can be made of what |
+ the code should be doing. |
+ </p> |
+ |
+ <p> |
+ Running the W3C validator is a little extra effort that saves a lot of time. |
+ See also: <a href="http://validator.w3.org/docs/why.html">W3C: Why Validate?</a> |
+ </p> |
+ </li> |
+ |
+ <li> |
+ CSS |
+ <ul> |
+ <li> |
+ <p> |
+ Use valid css. (Excepting vendor extensions and css 3 features). |
+ <a href="http://jigsaw.w3.org/css-validator/">http://jigsaw.w3.org/css-validator/</a> |
+ </p> |
+ </li> |
+ <li> |
+ <p> |
+ Class and id selectors should have semantic meaning. See also: |
+ <a href="http://www.w3.org/QA/Tips/goodclassnames">Use class with semantics in mind</a>. |
+ Selectors such as <code>.redButton</code>, <code>#ItalicStatement</code> are meaningless. |
+ Instead, use class and id that represent an object or state. |
+ </p> |
+ Example: |
+ <pre>.errorButton, #warningMessage, .active-panel</pre> |
+ <p> |
+ This makes the code meaningful even when the styles change. |
+ </p> |
+ </li> |
+ </ul> |
+ </li> |
+ <li> |
+ Script: |
+ <ul> |
+ <li>Variables |
+ <ul> |
+ <li> |
+ <p> |
+ Declare variables in the narrowest possible scope, never global. |
+ </p> |
+ </li> |
+ <li> |
+ <p> |
+ Do not assign to undeclared identifiers (do not forget <code>var</code>). |
+ </p> |
+ </li> |
+ <li> |
+ <p> |
+ Give each identifier a meaningful name. |
+ </p> |
+ </li> |
+ </ul> |
+ </li> |
+ <li id="methods">Methods |
+ <ul> |
+ <li> |
+ Avoid initialization routines that loop through the DOM. |
+ Instead, use event delegation and inspect the target (see design |
+ section). |
+ </li> |
+ <li>Avoid methods that do too much or have side effects. Methods should be simple and do one thing.</li> |
+ <li>Avoid long parameter lists. The fewer the better.</li> |
+ <li>Do not include non-localized strings in scripts (excepting developer error messages).</li> |
+ <li>Be clear and consistent with their return type.</li> |
+ <li>Test not only that it succeeds correctly (happy path), |
+ but also that it fails correctly (sad path). </li> |
+ </ul> |
+ </li> |
+ <li id="design">Design |
+ <ul> |
+ <li>Avoid creating and using useless methods, e.g. |
+ <pre>goog.isDef = function(val) { |
+ return val !== undefined; |
+}; |
+</pre> |
+ </li> |
+ <li> |
+ Do not use non-standard or inconsistent ECMAScript methods (<code>substr</code>, |
+ <code>escape</code>, <code>getYear</code>, <code>parseInt</code> with no radix). Instead, use |
+ <code>substring</code>, <code>encodeURIComponent</code>, <code>getFullYear</code>, |
+ and <code>parseInt(<var>s</var>, 10)</code> with a radix, respectively. |
+ </li> |
+ <li> |
+ Do not use non-standard syntax such as "function statement" |
+ (see also: <a href="/faq/#functionStatement">FAQ: What is a function statement?</a> and |
+ <a href="http://yura.thinkweb2.com/named-function-expressions/" |
+ >Named Function Expressions</a>). |
+ </li> |
+ <li> |
+ Consider refactoring a function with conditionals to dynamic dispatch or |
+ function redefinition. |
+ </li> |
+ <li> |
+ Avoid modifying objects you don't own. |
+ <p> |
+ A piece of code that modifies any object it does not own is not |
+ clear to the client of the API where those changes are coming from. |
+ </p> |
+ |
+ <p> |
+ Modifying built-ins has been known to cause forwards-compatibility problems |
+ and conflict with other code. Modifying host objects can result in |
+ javascript errors. |
+ </p> |
+ |
+ <p> |
+ Instead, use another approach. For example, define your own object, possibly hidden |
+ in a closure. |
+ </p> |
+ |
+ <p> |
+ Modifying host objects or host objects' constructors' prototypes with new properties |
+ is unspecified. The practice has been known to be the source of cross-browser problems. |
+ </p> |
+ |
+ <p> |
+ Where DOM host objects are implemented with prototypes, the prototype chain |
+ is implementation-dependent (not specified). The interface-based API design of the |
+ <a href="http://www.w3.org/TR/DOM-Level-2-HTML/">W3C DOM</a> does not forbid a |
+ sub-interface from providing a more specific implementation that could shadow |
+ the a user-defined method of the same name further up in the prototype chain. |
+ </p> |
+ <p> |
+ The W3C DOM does not prevent implementations from creating their own |
+ interfaces. Quite often implementations do create interfaces that are |
+ interwoven through the interface hierarchy. Such interfaces may or may |
+ not be accessible to code. |
+ </p> |
+ </li> |
+ </ul> |
+ </li> |
+ <li> |
+ Strings: |
+ <ul> |
+ <li> |
+ Use efficient string concatenation techniques. Do not repeatedly create |
+ and discard temporary strings. |
+ </li> |
+ <li> |
+ Instead use <code>String.prototype.concat(a, b, c)</code> or |
+ <code>htmlArray.push(a, b, c);</code> |
+ </li> |
+ </ul> |
+ </li> |
+ <li> |
+ Loops: |
+ <ul> |
+ <li> |
+ Avoid chains of identifiers in loop. |
+ Replace a long chain of identifiers with a variable. |
+ </li> |
+ <li> |
+ Do not traverse over elements to modify the style or add an event |
+ callback to each element. |
+ <div> |
+ |
+ <p> |
+ For Styles, replace a loop that applies styles to descendants by |
+ adding a class token to the nearest common ancestor (<a |
+ href="descendant-sel.html">example</a>). |
+ </p> |
+ <ol> |
+ <li> |
+ Add a style rule to the stylesheet with selector text |
+ <code>.special-state .special-descendant-class</code>. |
+ </li> |
+ <li> |
+ In the HTML, for each element to be to dynamically updated, add |
+ the class attribute <code>"special-descendant-class"</code>. |
+ </li> |
+ <li> |
+ In the script, add the class "special-state" to the ancestor |
+ and. |
+ The style rule defined in the stylesheet will be applied to |
+ the descendants with <code>"special-descendant-class"</code>. |
+ </li> |
+ </ol> |
+ <p> |
+ For events, use event delegation. That is, replace a loop that adds a |
+ callback to each element in a collection with a callback on a common ancestor. |
+ </p> |
+ </div> |
+ </li> |
+ </ul> |
+ </li> |
+ <li>Statements: |
+ <ul> |
+ <li> |
+ <p> |
+ Do not use <code>==</code> where strict equality is required. |
+ Where strict equality is required, the strict equality operator <code>===</code> must be used. |
+ The strict equality operator should always be used to compare objects. |
+ </p> |
+ </li> |
+ <li> |
+ <p> |
+ Do not use Boolean conversion of value that may be acceptably falsish, |
+ e.g. <code>if(e.pageX)</code>. |
+ </p> |
+ <p> |
+ Instead check the property using <code>typeof</code>. For example: |
+ <code>if(typeof e.pageX == "number")</code>. |
+ </p> |
+ </li> |
+ <li> |
+ <p> |
+ Do not use useless statements (e.g. <code>typeof it == "array"</code>). In addition to |
+ contributing to code size and runtime performance, useless statements make the |
+ code harder to understand. |
+ </p> |
+ </li> |
+ </ul> |
+ </li> |
+ <li id="regex"> |
+ Regular Expressions |
+ <ul> |
+ <li> |
+ Be simple, but do not match the wrong thing. |
+ A complex regular expression is harder to understand than a simple one. |
+ |
+ <p> |
+ The context of a Regular Expression is as important as what it can match. |
+ A complex regular expression is harder to understand than a simple one. |
+ Simple regular expressions are preferred. It is sometimes acceptable for the |
+ expression to match the wrong thing, just so long as the context in which it |
+ is used precludes or handles that. |
+ </p> |
+ <pre> |
+// Wrong: Matches 137, 138... |
+ARROW_KEY_EXP : /37|38|39|40/; |
+ |
+// Right: matches only arrow keys. |
+ARROW_KEY_EXP : /^(?:37|38|39|40)$/; |
+ |
+// Simple: Can match the wrong thing, but that can be handled. |
+var iso8601Exp = /^\s*([\d]{4})-(\d\d)-(\d\d)\s*$/; |
+</pre> |
+ <p> |
+ Trying to match leap years would be excessively complex. |
+ Instead, the date validation can be addressed where the expression is used. |
+ </p> |
+ <p> |
+ As with functions, test not only that it succeeds correctly, |
+ but also that it fails correctly. |
+ </p> |
+ </li> |
+ </ul> |
+ </li> |
+ <li id="formatting"> |
+ Formatting: |
+ <ul> |
+ <li> |
+ Code should not be formatted with tabs. |
+ Space indentation should be used consistently. |
+ </li> |
+ <li> |
+ Code should be formatted to a maximal line length. For newsgroup code, |
+ it should not exceed 72 chars. |
+ </li> |
+ <li id="asi">Semicolons: |
+ <h4>Semicolons, Newlines, and ASI (Automatic Semicolon Insertion)</h4> |
+ <p> |
+ Avoid mistakes caused by <dfn title="Automatic Semicolon Insertion">ASI</dfn>. |
+ </p> |
+ |
+ <p> |
+ In ECMAScript, line terminators affect how a program is interpreted. This is a design |
+ mistake of the language of which the details are complicated. The following guidelines |
+ can help avoid ASI problems with both <dfn>restricted productions</dfn> and productions that |
+ are not restricted. |
+ </p> |
+ <h5>Line Terminators: Restricted Productions</h5> |
+ |
+ <p> |
+ <dfn>Restricted productions</dfn> include only the postfix operators and the control |
+ statements <code>return</code>, <code>throw</code>, <code>continue</code>, and |
+ <code>break</code>. ASI affects a <dfn>restricted productions</dfn> |
+ when a line terminator is introduced. The following guidelines help avoid that mistake: |
+ </p> |
+ <h5>ASI Guidelines for <dfn>restricted productions</dfn>:</h5> |
+ <ul> |
+ <li> |
+ A postfix <code>++</code> or <code>--</code> operator must appear |
+ on the same line as its operand. |
+ </li> |
+ <li>An Expression in a <code>return</code> or <code>throw</code> statement must |
+ start on the same line as the <code>return</code> or <code>throw</code> token. |
+ </li> |
+ <li> |
+ An Identifier in a <code>break</code> or <code>continue</code> statement |
+ must be on the same line as the <code>break</code> or <code>continue</code> token. |
+ </li> |
+ </ul> |
+ |
+ <h5>Guidelines for Semicolons in Source Code:</h5> |
+ <ul> |
+ <li> |
+ <p> |
+ Don't rely on ASI. Use semicolons explicitly. |
+ </p> |
+ <p> |
+ A program that uses semicolons explicitly is less |
+ susceptible to different interpretation caused by |
+ changes in line terminators and expressions. |
+ </p> |
+ <p> |
+ For more details, please see: <a href="asi.html" |
+ >Automatic Semicolon Insertion : Unrestricted Productions</a> |
+ </p> |
+ </li> |
+ </ul> |
+ <h5>Extraneous Semicolons and The Empty Statement, ;</h5> |
+ <p> |
+ While it is important use semicolons explicitly, where required, |
+ there are cases where a semicolon should not be added. |
+ </p> |
+ <p> |
+ The <dfn>Statement</dfn>s that do not end in semicolon all end in close |
+ curly braces instead. They are : |
+ </p> |
+<pre> |
+Block: |
+ { ... } |
+ |
+SwitchStatement: |
+ switch ( ... ) { ... } |
+ |
+TryStatement: |
+ try ... catch ( ... ) { ... } |
+ try ... finally { ... } |
+</pre> |
+ |
+ <p> |
+ Something that isn't a statement but looks like one: |
+ </p> |
+<pre> |
+Function Declaration: |
+ function x{ ... } |
+</pre> |
+ <p> |
+ A semicolon that immediately follows a FunctionDeclaration |
+ is interpreted as an <dfn>EmptyStatement</dfn>. Useless |
+ statements should be avoided. |
+ </p> |
+ </li> |
+ </ul> |
+ </li> |
+ <li id="dom"> |
+ DOM: |
+ <ul> |
+ <li id="unrelatedInference"> |
+ Do not use poor or unrelated inferences such as <a href="../detect-browser/">browser detection</a> |
+ (see also <a href="../../#detectBrowser">FAQ: How do I detect Opera/Safari/IE?</a>). |
+ <pre>// Unrelated inference: |
+if(typeof window.innerHeight == "number") // it isn't IE |
+// Good inference: |
+if(typeof window.innerHeight == "number") // innerHeight available. |
+ |
+// Unrelated inference based on proprietary XUL feature (Borrowed from MooTools). |
+// See also: Bug 340571 - getBoxObjectFor leaking-onto-the-Web disaster |
+// https://bugzilla.mozilla.org/show_bug.cgi?id=340571 |
+gecko: function(){ |
+ return (document.getBoxObjectFor == undefined) ? false : ((document.getElementsByClassName) ? 19 : 18); |
+} |
+</pre> |
+ </li> |
+ <li> |
+ Use standards W3C DOM approach preferentially and proprietary DOMs as a fallback. |
+ </li> |
+ <li> |
+ If an approach requires several branches for handling browser variance, |
+ look for a different approach that works in all tested browsers. |
+ </li> |
+ <li> |
+ Do not traverse the DOM on page load; do not traverse the DOM |
+ using user-defined css query selector. |
+ </li> |
+ <li> |
+ Instead of traversing the DOM, use Event delegation. |
+ </li> |
+ </ul> |
+ </li> |
+ <li id="hostObjects"> |
+ Host Objects: |
+ <ul> |
+ <li>Operators: |
+ <ul> |
+ <li> |
+ Do not use <code>delete</code> operator with host object This will cause errors in IE, and others: |
+ <pre>delete window.location; //Security error" code: "1000"</pre> |
+ </li> |
+ <li> |
+ Do not add any expando properties (<code>unselectable</code> is safe). |
+ See also: <a href="http://msdn.microsoft.com/en-us/library/ms533747(v=VS.85).aspx" |
+ >msdn expando</a>. |
+ </li> |
+ <li> |
+ Host objects that error upon <code>[[Get]]</code> access are often |
+ <code>ActiveX</code> objects. These include, but are not limited to: |
+ <ul> |
+ <li> |
+ Disconnected nodes whose <code>parentNode</code> is not an element (<code>node.offsetParent</code>). |
+ </li> |
+ <li> |
+ <code>XMLHttpRequest</code> methods (<code>open</code>, <code>send</code>, etc). |
+ </li> |
+ <li> |
+ filters: <code>elem.filters.alpha</code>, <code>elem.style.filters.alpha</code>, etc. |
+ </li> |
+ <li> |
+ <code>document.styleSheets[99999] </code>- Error from <code>[[Get]]</code> for a |
+ nonexistent numeric property of a <code>styleSheets</code> collection. |
+ </li> |
+ <li> |
+ <code>link.href</code> for <code>nntp:</code> links in IE. |
+ </li> |
+ <li> |
+ <code>NodeList</code> in Safari 2 - do not attempt access a |
+ nonexistent property |
+ (e.g. <code>document.childNodes.slice</code>). |
+ </li> |
+ </ul> |
+ </li> |
+ </ul> |
+ </li> |
+ <li>Type conversion |
+ <dl> |
+ <dt><code>[[ToString]]</code></dt> |
+ <dd>Perform string conversion by starting concatenation with a string value. |
+ See <a href="http://groups.google.bg/group/comp.lang.javascript/msg/1528f612e31f09fe" |
+ >Newsgroup message explanation</a>. |
+ </dd> |
+ </dl> |
+ </li> |
+ </ul> |
+ </li> |
+ <li> |
+ Comments: |
+ <ul> |
+ <li> |
+ Avoid too many comments; let the code speak for itself. |
+ </li> |
+ <li> |
+ Avoid comments that are likely to become obsolete or are redundant. |
+ </li> |
+ <li> |
+ Explain <em>why</em>, not <em>what</em>. |
+ Comments should help explain things that are not obvious. |
+ </li> |
+ <li> |
+ Comments should never contain inaccurate statements or terminology, |
+ should never be misleading, and should be well-written. |
+ </li> |
+ </ul> |
+ </li> |
+ </ul> |
+ </li> |
+</ul> |
+</body> |
+</html> |
/cljs/notes/code-guidelines/index.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/notes/code-guidelines/descendant-sel.html |
=================================================================== |
--- cljs/notes/code-guidelines/descendant-sel.html (nonexistent) |
+++ cljs/notes/code-guidelines/descendant-sel.html (revision 2) |
@@ -0,0 +1,102 @@ |
+ <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" |
+ "http://www.w3.org/TR/html4/strict.dtd"> |
+ |
+<html lang="en"> |
+<head> |
+<meta http-equiv="Content-type" content="text/html;charset=UTF-8"> |
+<link rel="Index" href="../"> |
+<title>Toggle Class To Trigger Descendant Selector Rules</title> |
+ |
+<style type="text/css"> |
+/* Make table pretty */ |
+table { |
+ border: 1px solid #8893af; |
+ background: #dfe3ff; |
+ width: 33em; |
+ font-family: verdana, sans-serif; |
+ margin: 12px; |
+} |
+tr { |
+ background: #eef6ff; |
+} |
+ |
+td { |
+ padding: 4px; |
+} |
+ |
+/* The descendant selector trick */ |
+.even .odd-row, .odd tr { |
+ display: none; |
+} |
+ |
+.odd .odd-row { |
+ display: block; |
+ display: table-row; |
+} |
+ |
+.odd-row { |
+ background: #fdfeff; |
+} |
+</style> |
+ |
+<script type="text/javascript"> |
+function showEven() { |
+ var testTable = document.getElementById("testTable"); |
+ testTable.className = "even"; |
+} |
+ |
+function showOdd() { |
+ var testTable = document.getElementById("testTable"); |
+ testTable.className = "odd"; |
+} |
+ |
+function showAll() { |
+ var testTable = document.getElementById("testTable"); |
+ testTable.className = ""; |
+} |
+</script> |
+</head> |
+ |
+<body> |
+<h1>Toggle Class To Trigger Descendant Selector Rules</h1> |
+<h2>Description</h2> |
+<p> |
+ By toggling a class name on the table, the descendant selector is applied and certain rows are shown |
+ and hidden. |
+</p> |
+<h2>Demonstration</h2> |
+<div> |
+ <button onclick="showEven()">showEven()</button> |
+ <button onclick="showOdd()">showOdd()</button> |
+ <button onclick="showAll()">showAll()</button> |
+</div> |
+ |
+<table id="testTable"> |
+ <tr> |
+ <td>even row, even row, even row, even row, even row, even row</td> |
+ </tr> |
+ <tr class="odd-row"> |
+ <td>odd row, odd row, odd row, odd row, odd row, odd row</td> |
+ </tr> |
+ <tr> |
+ <td>even row, even row, even row, even row, even row, even row</td> |
+ </tr> |
+ <tr class="odd-row"> |
+ <td>odd row, odd row, odd row, odd row, odd row, odd row</td> |
+ </tr> |
+ <tr> |
+ <td>even row, even row, even row, even row, even row, even row</td> |
+ </tr> |
+ <tr class="odd-row"> |
+ <td>odd row, odd row, odd row, odd row, odd row, odd row</td> |
+ </tr> |
+ <tr> |
+ <td>even row, even row, even row, even row, even row, even row</td> |
+ </tr> |
+ <tr class="odd-row"> |
+ <td>odd row, odd row, odd row, odd row, odd row, odd row</td> |
+ </tr> |
+</table> |
+</body> |
+ |
+</html> |
/cljs/notes/code-guidelines/descendant-sel.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/notes/review/index.html |
=================================================================== |
--- cljs/notes/review/index.html (nonexistent) |
+++ cljs/notes/review/index.html (revision 2) |
@@ -0,0 +1,105 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" |
+ "http://www.w3.org/TR/html4/strict.dtd"> |
+<html lang="en"> |
+<head> |
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> |
+<title>Code Review Guidelines - comp.lang.javascript</title> |
+<link href="../../faq.css" rel="stylesheet" type="text/css"> |
+<link href="../notes.css" rel="stylesheet" type="text/css"> |
+</head> |
+<body> |
+<h1>Code Review Guidelines</h1> |
+<div id="faqNav"> |
+ <a href="../../">FAQ</a> > <a href="../">FAQ Notes</a> |
+</div> |
+<p> |
+ Article by Garrett Smith |
+</p> |
+<p> |
+Peer code review is where software developers review each others' |
+development code. |
+</p> |
+ |
+<h2>Benefits</h2> |
+<p> |
+The number one benefit to code reviews is code quality. Code reviews make the code |
+better. Here are some other benefits: |
+</p> |
+ |
+<ul> |
+ <li> |
+ Spreads understanding about the code being reviewed. |
+ </li> |
+ <li> |
+ Helps find bugs before they get to QA and avoids QA churn. |
+ </li> |
+ <li> |
+ Helps identify potential problems, bad practices, or maldesign. |
+ </li> |
+ <li> |
+ Preparation for review will require the code author to check his |
+ code against the <a href="../code-guidelines/">code guidelines</a> and |
+ clean it up (bugs fixed prior to review). |
+ </li> |
+ |
+ <li> |
+ Encourages collaboration. |
+ </li> |
+ |
+ <li> |
+ Keeps code cleaner and more maintainable. |
+ </li> |
+</ul> |
+<h2>How to perform the Review</h2> |
+<p> |
+Take your time understand the problem and how it is addressed in the solution. |
+</p> |
+ |
+<p> |
+Focus on a small piece at a time. |
+</p> |
+ |
+<p> |
+A code review should be objective and should state actual problems. |
+Saying "the code is bad" is not a helpful review. Instead, explain |
+the problem clearly. If the problem is severe, then say why. |
+</p> |
+ |
+<h2>Preparation of Reviewed Code</h2> |
+<p> |
+This section is for the the reviewee (the person whose code is being reviewed). |
+</p> |
+ |
+<p> |
+The reviewee should prepare for a code review by following the |
+the <a href="../code-guidelines/">code guidelines</a>. |
+</p> |
+ |
+<h3>Posting Code for Review and Code Reviews</h3> |
+<p> |
+When posting code to the newsgroup, it is important to make sure |
+to transmit it such that it can be easily read and understood. |
+</p> |
+ |
+<ul> |
+ <li>Format the code to 72 char width. </li> |
+ |
+ <li>Replace any spaces in the source code with tabs.</li> |
+ |
+ <li>Post small sections at a time. |
+ <p>By focusing carefully on small |
+ sections, the code review can find more bugs. The reviewer may want to |
+ spend an hour reviewing the code, then come back to re-review his notes |
+ and comments for another hour. |
+ </p> |
+ </li> |
+</ul> |
+ |
+<h3>Rebuttals</h3> |
+<p> |
+The reveiwee may challenge a criticism and, if the challenge cannot be |
+rebutted, the criticism shall be withdrawn. |
+</p> |
+ |
+</body> |
+</html> |
/cljs/notes/review/index.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/notes/form-access/index.html |
=================================================================== |
--- cljs/notes/form-access/index.html (nonexistent) |
+++ cljs/notes/form-access/index.html (revision 2) |
@@ -0,0 +1,729 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" |
+ "http://www.w3.org/TR/html4/strict.dtd"> |
+<html lang="en"> |
+<head><title>Referencing Forms and Form Controls</title> |
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> |
+<link href="../../faq.css" rel="stylesheet" type="text/css"> |
+<link href="../notes.css" rel="stylesheet" type="text/css"> |
+<style type="text/css"> |
+.commentJS { |
+ background-color: #FFFFCC; |
+ color: #004800; |
+} |
+P CODE { |
+ background-color: #FFFFDD; |
+ color: #000000; |
+ padding: 0ex; |
+ margin: 0ex; |
+} |
+</style> |
+</head> |
+<body> |
+ |
+<h1 id="faHead">Referencing Forms and Form Controls</h1> |
+<div id="faqNav"> |
+ <a href="../../">FAQ</a> > <a href="../">FAQ Notes</a> |
+</div> |
+ |
+<ul> |
+ <li><a href="#faInt">Introduction</a> |
+ <ul> |
+ <li><a href="#faInF">Forms</a></li> |
+ <li><a href="#faInC">Form Controls</a></li> |
+ </ul> |
+ </li> |
+ <li><a href="#faShrt">Shortcut Accessors</a></li> |
+ <li><a href="#faComMis">The Most Common Mistake</a></li> |
+ <li><a href="#faAnon">Anonymous Form References</a></li> |
+ <li><a href="#faBut">Radio Button and Other Control Collections</a></li> |
+ <li><a href="#faEff">Efficient use of Form Accessors</a></li> |
+</ul> |
+ |
+<h2 id="faInt">Introduction</h2> |
+<h3 id="faInF">Forms</h3> |
+<p id="faInF_1"> |
+When the W3C defined the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> DOM specification much of what they included |
+represented a formalisation of existing browser behaviour. In particular they |
+defined "convenience" properties on the <code>HTMLDocument</code> |
+interface that reproduce document level collections common in preceding |
+browsers. Of specific interest here is the <code>document.forms</code> |
+collection, which makes all of the <code>FORM</code> elements on a page |
+available as (zero based) indexed members of the collection. Allowing, |
+for example, the second <code>FORM</code> element on a page to be |
+referenced as:- |
+</p> |
+ |
+<pre id="faInF_ex1"> |
+var formElement = document.forms[1]; |
+</pre> |
+ |
+<p id="faInF_2"> |
+<span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> (but not necessarily XHTML) <code>FORM</code> elements are allowed |
+<code>NAME</code> attributes and the <code>document.forms</code> collection |
+also makes <code>FORM</code> elements with <code>NAME</code> attributes |
+available as named members, under a property name that corresponds with |
+value of the <code>NAME</code> attribute. So given a form with the |
+attribute <code>name="myForm"</code> the form can be referenced |
+as:- |
+</p> |
+ |
+<pre id="faInF_ex2"> |
+var formElement = document.forms.myForm; |
+ |
+<span class="commentJS">/* - or - */</span> |
+ |
+var formElement = document.forms["myForm"]; |
+ |
+<span class="commentJS">/* The latter, bracket notation, does not impose the same restrictions |
+ on the character sequence used for the name as is imposed by the |
+ preceding dot notation, which is restricted to only using character |
+ sequences that would fulfill the ECMAScript definition of an |
+ identifier. |
+ |
+ Bracket notation is often preferred when accessing form elements as |
+ it helps to document itself by making it clear in the source code |
+ which property names originate in the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> rather than the DOM. |
+*/</span> |
+</pre> |
+ |
+<p id="faInF_3"> |
+The <code>document.forms</code> collection had exhibited this behaviour |
+in all of the preceding browsers that implemented it (which included |
+all the browsers that understood what a form was) and as a result |
+represents the most cross-browser method of accessing <code>FORM</code> |
+elements. It is both W3C <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> DOM standard compliant and |
+back-compatible with pre-existing browsers. |
+</p> |
+ |
+<p id="faInF_4"> |
+The W3C went on to require <code>FORM</code> elements with |
+<code>ID</code> attributes to also be made available as named properties |
+of the <code>document.forms</code> collection. That represented a |
+formalisation of behaviour already exhibited in IE 4 but not by |
+Netscape 4 (and earlier). Referencing <code>ID</code>ed <code>FORM</code> |
+elements as named properties of the <code>document.forms</code> collection |
+should work reliably in all W3C <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> DOM compliant browsers but some |
+back-compatibility will be sacrificed if <code>ID</code>s are used instead |
+of <code>NAME</code>s (though not nearly as much as would be lost if |
+<code>ID</code>ed form elements were referenced using the |
+<code>document.getElementById</code> method). |
+</p> |
+ |
+<p id="faInF_5"> |
+When writing <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> that conforms to a DTD that allows <code>FORM</code> |
+elements to have <code>NAME</code> attributes it is possible to also give |
+the <code>FORM</code> element an <code>ID</code> attribute that corresponds |
+with its <code>NAME</code> attribute (so long as the <code>ID</code> is |
+unique on the page). The form will appear as a member of the |
+<code>document.forms</code> collection under a property name that |
+corresponds with the value of the <code>NAME</code> and <code>ID</code> |
+attributes (as they are identical). |
+</p> |
+ |
+<h3 id="faInC">Form Controls</h3> |
+ |
+<p id="faInC_1"> |
+Traditionally browsers that implemented the <code>document.forms</code> |
+collection also made the controls within a form available as a |
+collection accessible as a property of the <code>FORM</code> element |
+under the name <code>elements</code>. The W3C <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> DOM also formalised |
+this collection in the <code>HTMLFormElement</code> interface. |
+Controls within a form can be referenced as integer indexed members of |
+that collection:- |
+</p> |
+ |
+<pre id="faInC_ex1"> |
+var formElement = document.forms["myForm"]; |
+var controlElement = formElement.elements[2]; <span class="commentJS">//Third control in the form.</span> |
+</pre> |
+ |
+<p id="faInC_2"> |
+Controlls with <code>NAME</code> attributes are again made available as |
+named properties of the collection. So a control with |
+<code>name="myControl"</code> can be referenced as:- |
+</p> |
+ |
+<pre id="faInC_ex2"> |
+var controlElement = formElement.elements["myControl"]; |
+</pre> |
+ |
+<p id="faInC_3"> |
+Again the W3C also specified that controls with <code>ID</code> |
+attributes should be made available as named members of the |
+elements collection under their <code>ID</code>s (with the same |
+implications for back-compatibility with really ancient browsers). |
+All official (x)<span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> DTDs allow form controls to have |
+<code>NAME</code> attributes because without a <code>NAME</code> |
+attribute the value of the control cannot be sent as a |
+name/value pair when the form is submitted. |
+</p> |
+ |
+<h2 id="faShrt">Shortcut Accessors</h2> |
+ |
+<p id="faShrt_1"> |
+In addition to making named <code>FORM</code> elements available |
+as named properties of the <code>document.forms</code> collection |
+web browsers also make them available as named properties of the |
+<code>document</code> object. So:- |
+</p> |
+ |
+<pre id="faShrt_ex1"> |
+var formElement = document.myForm; |
+</pre> |
+ |
+<p id="faShrt_2"> |
+-will reference the same FORM element as:- |
+</p> |
+ |
+<pre id="faShrt_ex2"> |
+var formElement = document.forms.myForm; |
+</pre> |
+ |
+<p id="faShrt_3"> |
+And the same is true using bracket notation:- |
+</p> |
+ |
+<pre id="faShrt_ex3"> |
+var formElement = document["myForm"]; |
+ |
+<span class="commentJS">/* instead of:- */ </span> |
+ |
+var formElement = document.forms["myForm"]; |
+</pre> |
+ |
+<p id="faShrt_4"> |
+The W3C did not include this shortcut in the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> DOM specifications |
+so code that uses it cannot be described as standards compliant and, |
+while nobody has been able to name an <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> browser where the shortcut |
+accessors do not work when referencing named <code>FORM</code> |
+elements, it would still be possible for a future standards compliant |
+browser not to support the shortcut accessors. |
+</p> |
+ |
+<p id="faShrt_5"> |
+<code>FORM</code> elements that only have <code>ID</code> attributes |
+cannot be accessed as properties of the <code>document</code> object |
+under a property name that corresponds with their <code>ID</code> |
+attributes. While by W3C <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> DOM specification (but not necessarily |
+on older browsers) <code>ID</code>ed forms are made available as named |
+properties of the <code>document.forms</code> collections under a |
+property name that corresponds with the <code>ID</code>. |
+</p> |
+ |
+<p id="faShrt_6"> |
+Form controls can be referenced as named properties of the |
+<code>FORM</code> element that contains them with a shortcut accessor:- |
+</p> |
+ |
+<pre id="faShrt_ex4"> |
+var formControl = formElement.myControl; |
+ |
+<span class="commentJS">/* instead of :- */</span> |
+ |
+var formControl = fromElement.elements.myControl; |
+</pre> |
+ |
+<p id="faShrt_7"> |
+But in the case of form controls, elements with <code>ID</code> |
+attributes may be available as properties of the <code>FORM</code> |
+element under a property name that corresponds with their |
+<code>ID</code> (at least on more recent browsers). |
+</p> |
+ |
+<p id="faShrt_8"> |
+The main argument in favour of using shortcut accessors (apart from the |
+reduced amount of typing) is that they are resolved fractionally quicker |
+than accessors that employ the <code>forms</code> and |
+<code>elements</code> collections. That follows from the fact that fewer |
+object references need to be resolved before the reference to the element |
+of interest is returned. |
+</p> |
+ |
+<p id="faShrt_9"> |
+While arguments against the shortcut accessors point out that named image, |
+embed and other elements are also made available as named properties of |
+the <code>document</code> object, making it ambiguous when reading the |
+source code whether the shortcut accessor is referring to a form or some |
+other named property of the <code>document</code> object. When a |
+<code>FORM</code> element is referenced as a member of the |
+<code>document.forms</code> collection, or a control as a member of the |
+<code>elements</code> collection, there can be no doubt while reading |
+the source code as to the type of element that is the subject of the |
+reference. |
+</p> |
+ |
+<h2 id="faComMis">The Most Common Mistake</h2> |
+ |
+<p id="faComMis_1"> |
+The most common mistake made when defining the form <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> that a script |
+will interact with follows from the existence of the shortcut accessors |
+for form controls. It is to give the control a <code>NAME</code> (or |
+possibly <code>ID</code>) that corresponds with an existing property of |
+<code>FORM</code> elements. And the most common example of that is an |
+<code>INPUT</code> element of <code>type="submit"</code> with |
+the <code>NAME</code> "submit". Because the named controls are |
+made available as named properties of the <code>FORM</code> element this |
+<code>INPUT</code> element is made available under the property name |
+<code>"submit"</code>. Unfortunately <code>FORM</code> elements |
+already have a property with the name <code>"submit"</code>, it |
+is the <code>submit</code> method that can be used to submit the form |
+with a script. The misguided choice of name for the <code>INPUT</code> |
+element effectively renders the form's <code>submit</code> method |
+unscriptable. And the same is true for all controls with names that |
+correspond any with existing <code>FORM</code> element properties. |
+</p> |
+ |
+<p id="faComMis_2"> |
+Because ECMAScript is case sensitive it may only be necessary to |
+capitalise the name of the <code>INPUT</code> element to avoid the |
+conflict. However, it would probably be safest to adopt a naming |
+convention for form controls that ensured that they do not |
+correspond with existing properties of the <code>FORM</code> elements |
+regardless of case. Especially as theW3C <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> specification implies |
+that referring to named properties of collections can be case |
+insensitive in <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> DOMs. In reality I don't know of any |
+implementations in which it is but it would be better to err on the side |
+of caution. |
+</p> |
+ |
+<p id="faComMis_3"> |
+Another naming conflict that should be avoided would arise if named form |
+controls had names that correspond with the string representations of |
+integers, such as <code>name="1"</code> as they will almost |
+certainly result in inconsistent results (across browsers) when being |
+referenced because the controls are already available by integer index |
+and it would become unclear which control was being referenced by |
+accessors such as <code>formElement.elements[1]</code> or |
+<code>formElement.elements["1"]</code> (by the ECMAScript |
+specification the preceding two property accessors are equivalent). |
+Unless the control with the name <code>"1"</code> also |
+happened to be the control with the index 1. This problem would also |
+apply to <code>FORM</code> elements within the <code>document.forms</code> |
+collection. |
+</p> |
+ |
+<p id="faComMis_4"> |
+Generally it is best to only give form controls names that cannot |
+conflict with existing properties of <code>FORM</code> elements |
+and <code>FORM</code> elements names that cannot conflict with |
+existing properties of the <code>document.forms</code> collection |
+or the <code>document</code> object. |
+</p> |
+ |
+<h2 id="faAnon">Anonymous Form References</h2> |
+ |
+<p id="faAnon_1"> |
+Because <code>FORM</code> elements are available as integer indexed |
+member of the <code>document.forms</code> collection it is not |
+necessary to know the name of a form (or for the form to have a |
+name) to acquire a reference to it. While being able to refer to a |
+form anonymously with its index might seem like a good approach |
+towards making more general/flexible functions for form validation |
+and the like, in practice referring to forms by their index actually |
+makes code less flexible and harder to maintain. As soon as the |
+number or layout of forms on a page is changed their indexes also |
+change, requiring that all of the references by index be located |
+and altered. |
+</p> |
+ |
+<p id="faAnon_2"> |
+One method of avoiding having to know the name of a <code>FORM</code> |
+element within a function that is to act upon a form is to pass a |
+reference to the form object as an argument in the function call. |
+This is easiest achieved from the code provided as the value for |
+an event handling attribute because that code is used by the browser |
+to create an event handling function that is assigned as a method of |
+the element to which it is attached. And in any function executed as |
+a method of an object the <code>this</code> keyword is a reference to |
+the object with which the execution of the method is associated. The |
+most common need to anonymously pass a reference to a <code>FORM</code> |
+element is as an argument to a form validation function in the |
+onsubmit handler of the form. In that case the event handling function |
+is a method of the <code>FORM</code> element so the <code>this</code> |
+keyword refers to the form directly:- |
+</p> |
+ |
+<pre id="faAnon_ex1"> |
+function validateForm(formRef){ |
+ <span class="commentJS">/* Use the reference to the form passed as the formal |
+ parameter - formRef - to acquire a reference to the form |
+ control with the name "textField": |
+ */</span> |
+ var el = formRef && formRef.elements["textField"]; |
+ <span class="commentJS">/* If the control reference exists return its value property |
+ converted to a boolean value (false if empty, true otherwise) |
+ else return true so the form is submitted and the server can |
+ do the validation: |
+ */</span> |
+ return !el || Boolean(el.value); |
+} |
+... |
+<form action="http://example.com/somePage.asp" |
+ onsubmit="return validateForm(this);"> |
+ <input type="text" name="textField" value=""> |
+ <input type="submit" name="Submit_Button" value="Submit"> |
+</form> |
+</pre> |
+ |
+<p id="faAnon_3"> |
+Because the above function receives the reference to the form that it |
+is to validate as an argument when it is called it can also be used |
+with any number of other forms. Although in the case of the above |
+function each of those forms would need to contain a field called |
+<code>"textField"</code>, but that string name could also be |
+passed as an argument, making the function more general. |
+</p> |
+ |
+<p id="faAnon_4"> |
+Form control objects all have a property named |
+<code>"form"</code> that holds a reference to the |
+<code>FORM</code> element that contains them. As a result the event |
+handling functions attached to form controls can pass an anonymous |
+reference to the form that contains them as <code>this.form</code>. |
+Obviously a function called from an event handler on a control can |
+be passes an anonymous reference to the control itself as |
+<code>this</code>. |
+</p> |
+ |
+<h2 id="faBut">Radio Button and Other Control Collections</h2> |
+ |
+<p id="faBut_1"> |
+Radio button controls work to provide a selection of one item of many |
+when each of the radio button alternatives has the same |
+<code>NAME</code> attribute. But it is also possible to give other types |
+of control the same <code>NAME</code> attribute. |
+</p> |
+ |
+<p id="faBut_2"> |
+When controls that share the same <code>NAME</code> attribute they can |
+still be accessed as integer indexed members of the <code>FORM</code> |
+element's <code>elements</code> collection but when the member of the |
+<code>elements</code> collection is accessed using the <code>NAME</code> |
+attribute value as a property name browsers return a collection all of |
+the elements with the corresponding NAME attributes. So given the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span>:- |
+</p> |
+ |
+<pre id="faBut_ex1"> |
+<form name="testForm" action="http://example.com/somePage.jsp"> |
+ <ul style="list-style-type:none;"> |
+ <li><input type="radio" name="radioSet" value="R1">option 1</li> |
+ <li><input type="radio" name="radioSet" value="R2">option 2</li> |
+ <li><input type="radio" name="radioSet" value="R3">option 3</li> |
+ <li><input type="radio" name="radioSet" value="R4">option 4</li> |
+ </ul> |
+ <input type="submit" name="Submit_Button" value="Send"> |
+</form> |
+</pre> |
+ |
+<p id="faBut_3"> |
+A property accessor referring to the member of the <code>FORM</code>'s |
+<code>elements</code> collection by the property name |
+<code>"radioSet"</code> will not return a reference to any one |
+of the named radio buttons but instead returns a collection of all of the |
+like-named radio controls. |
+</p> |
+ |
+<p id="faBut_4"> |
+The individual radio buttons within that collection are referred to as |
+integer indexed members of that collection. So to find the button that |
+is checked one might loop through all of the members of the collection |
+of like-named radio buttons and copy a reference to the button with its |
+<code>checked</code> property set to boolean <code>true</code>. |
+</p> |
+ |
+ |
+<pre id="faBut_ex2"> |
+var radioCollection, checkedButton; |
+var frm = document.forms["testForm"]; |
+if(frm){ |
+ radioCollection = frm.elements["radioSet"]; |
+ if(radioCollection){ |
+ <span class="commentJS">/* The collection of like-named radio buttons has a length |
+ property and that is used to limit a for loop:- |
+ */</span> |
+ for(var c = 0;c < radioCollection.length;c++){ |
+ <span class="commentJS">/* The individual radio buttons are accessed as indexed |
+ members of the collection using the loop counter - c |
+ - from the for loop: |
+ */</span> |
+ if(radioCollection[c].checked){ |
+ <span class="commentJS">/* When a radio button element is found with its |
+ checked property set to boolean true a reference |
+ to that element is assigned to the local variable |
+ - checkedButton - and the loop is terminated with |
+ the - break - statement as only one button in a set |
+ of like-named radio buttons will be checked at a |
+ time, so any remaining buttons in the collection |
+ must have checked properties set to false: |
+ */</span> |
+ checkedButton = radioCollection[c]; |
+ break; |
+ } |
+ } |
+ if(checkedButton){ |
+ <span class="commentJS">/* Do something with the reference to the checked radio |
+ button (if any). |
+ */</span> |
+ ... |
+ } |
+ } |
+} |
+</pre> |
+ |
+<p id="faBut_5"> |
+It is not unusual when a form is generated by a server-side script that |
+some forms may have one or more like-named controls. If there is only |
+one control inserted in the form then accessing a member of the |
+<code>elements</code> collection with its name will return a reference |
+to that one control, but if there are multiple elements the returned |
+reference will be to a collection of such controls. While it may be |
+possible to branch client-side code that wants to interact with those |
+controls to handle the two alternatives it adds an unnecessary |
+maintenance burden to do so. |
+</p> |
+ |
+<p id="faBut_6"> |
+As handling a returned collection usually involves looping through that |
+collection the simplest way of implementing the client-side code to |
+deal with both collections and individual controls being returned by |
+named properties of the <code>elements</code> collection is to |
+normalise the references to individual controls so that they can be |
+handled as if they were a collection. Looping through a collection |
+involves using the <code>length</code> property of the collection to |
+limit the loop statement and accessing the controls within the |
+collection by integer index. This is exactly the way in which code |
+would loop through the elements of an <code>Array</code>. To allow a |
+script to handle both possibilities with the same code the return of |
+a reference to an individual control could be detected and then that |
+reference used to create a one-element <code>Array</code>. Subsequent |
+code would then treat the <code>Array</code> as if it was a collection and |
+loop through it, but as there is only one element the loop body would |
+only be executed once. |
+</p> |
+ |
+<pre id="faBut_ex3"> |
+var radioCollection, checkedButton; |
+var frm = document.forms["testForm"]; |
+if(frm){ |
+ radioCollection = frm.elements["radioSet"]; |
+ if(radioCollection){ |
+ <span class="commentJS">/* But the returned reference might not be a collection in this |
+ case. Instead it may be a reference to just one control if |
+ there is only one in this form with the name "radioSet". |
+ If it is a reference to an individual control it is going to |
+ be necessary to normalise it. Because radio button controls |
+ do not have - length - properties and collections do that is |
+ the property that is going to be tested: |
+ */</span> |
+ if(typeof radioCollection.length != "number"){ |
+ <span class="commentJS">/* The length property is not a number so this cannot be a |
+ collection and must be normalised so that the following |
+ loop statement can handle it correctly. Normalisation is |
+ done by making a reference to the control currently |
+ referred to by the - radioCollection - local variable |
+ into the first (and only) element of a new Array object |
+ and then assigning a reference to that array to the - |
+ radioCollection - local variable: |
+ */</span> |
+ radioCollection = [radioCollection]; |
+ } |
+ <span class="commentJS">/* The execution of the body of the - for - loop is limited by |
+ the - length - property of the collection/Array. |
+ */</span> |
+ for(var c = 0;c < radioCollection.length;c++){ |
+ <span class="commentJS">/* The individual radio buttons are accessed as indexed |
+ members of the collection/Array using the loop counter |
+ - c - from the for loop: |
+ */</span> |
+ if(radioCollection[c].cheked){ |
+ checkedButton = radioCollection[c]; |
+ break; |
+ } |
+ } |
+ if(checkedButton){ |
+ <span class="commentJS">/* do something with the reference to the checked radio |
+ button (if any). |
+ */</span> |
+ ... |
+ } |
+ } |
+} |
+</pre> |
+ |
+<p id="faBut_7"> |
+While it is normal for radio button controls to be like-named it is |
+also possible for all other controls to be included in a form with |
+multiple controls of the same type and like names. The same |
+referencing techniques can be used with any type of control (even |
+mixed types with like-names, though that is almost never done). But |
+deciding whether a reference needs to be normalised by making it into |
+the only element of an <code>Array</code> by testing the |
+<code>length</code> property of that reference to see if it doesn't |
+exist will not work with <code>SELECT</code> elements as they have |
+a <code>length</code> property of their own. It also would not help |
+to be testing some other characteristic of a collection, such as their |
+<code>item</code> method, as <code>SELECT</code> elements usually have |
+all of the methods and properties of a collection as they are |
+implemented as collections of <code>OPTION</code> elements. |
+</p> |
+ |
+<p id="faBut_8"> |
+Turning the problem around and testing a returned reference to see if |
+it has the characteristics of a <code>SELECT</code> element (such as |
+an <code>options</code> property) would be better but some collection |
+implementations have all of the properties and methods of the first |
+element within that collection as well as the properties and methods |
+of a collection (e.g. on IceBrowser 5). That means that it would not be |
+easy to distinguish a collection of <code>SELECT</code> controls |
+from an individual <code>SELECT</code> control. However, a more |
+elaborate test might go:- |
+</p> |
+ |
+<pre id="faBut_ex4"> |
+<span class="commentJS">/* Normalise a reference that may be an individual from control |
+ (including SELECT elements) or may be a collection of controls |
+ into a form that can be handled in a - for - loop controlled with |
+ its - length - property and accessed by integer index. |
+*/</span> |
+if((typeof contrlCollection.length != "number")|| <span class="commentJS">//no length propety:</span> |
+ <span class="commentJS">/* or:- */</span> |
+ ((contrlCollection.options)&& <span class="commentJS">//it has an options colleciton and:</span> |
+ ((!contrlCollection[0])|| <span class="commentJS">//no object at index 0 - not a collection</span> |
+ <span class="commentJS">/* or:- */</span> |
+ (contrlCollection[0] == contrlCollection.options[0])))){ |
+ <span class="commentJS">/* The object at index 0 in contrlCollection is the same object |
+ as is at index 0 in contrlCollection.options so this must be |
+ an individual SELECT element not a collection of them because a |
+ collection of SELECT elements would not have an OPTION element |
+ at index zero. |
+ */</span> |
+ contrlCollection = [contrlCollection]; |
+} |
+</pre> |
+ |
+<h2 id="faEff">Efficient use of Form Accessors</h2> |
+ |
+<p id="faEff_1"> |
+Code that interacts with <code>FORM</code> elements and controls |
+through the <code>document.forms</code> collection and the form's |
+<code>elements</code> collection usually does not do enough work to |
+make the efficiency of the code significant. But with large forms with |
+many controls an inefficiently coded validation function (or some other |
+interaction, like keeping running totals) can negatively impact on the |
+user's experience. It can also be argued that considering the |
+efficiency of implementation is a worthwhile habit even when it would |
+make no perceivable difference. |
+</p> |
+ |
+<p id="faEff_2"> |
+A significant aspect of the efficient coding of form interacting code |
+is the re-resolving of references to various objects. This trivial |
+example code copies the values of 5 <code>INPUT</code> elements to |
+local variables:- |
+</p> |
+ |
+<pre id="faEff_ex1"> |
+var txt1 = document.forms["formName"].elements["field1"].value; |
+var txt2 = document.forms["formName"].elements["field2"].value; |
+var txt3 = document.forms["formName"].elements["field3"].value; |
+var txt4 = document.forms["formName"].elements["field4"].value; |
+var txt5 = document.forms["formName"].elements["field5"].value; |
+</pre> |
+ |
+<p id="faEff_3"> |
+The shortcut accessors require the resolution of fewer object |
+references:- |
+</p> |
+ |
+<pre id="faEff_ex2"> |
+var txt1 = document["formName"]["field1"].value; |
+var txt2 = document["formName"]["field2"].value; |
+var txt3 = document["formName"]["field3"].value; |
+var txt4 = document["formName"]["field4"].value; |
+var txt5 = document["formName"]["field5"].value; |
+</pre> |
+ |
+<p id="faEff_4"> |
+But their use still involves re-resolving the form object each time a |
+form control is accessed. It would be unnecessary to re-resolve this |
+reference if a reference to the form was assigned to a local variable:- |
+</p> |
+ |
+<pre id="faEff_ex3"> |
+<span class="commentJS">/* Assign a reference to the form object to the local variable - frm - |
+ and then make subsequent control references relative to that local |
+ variable: |
+*/</span> |
+var frm = document.forms["formName"]; |
+var txt1 = frm.elements["field1"].value; |
+var txt2 = frm.elements["field2"].value; |
+var txt3 = frm.elements["field3"].value; |
+var txt4 = frm.elements["field4"].value; |
+var txt5 = frm.elements["field5"].value; |
+</pre> |
+ |
+<p id="faEff_5"> |
+The effect would be much the same as when a reference to the form |
+object has been passed to a function and control references are |
+accessed relative to the parameter holding the form reference. |
+</p> |
+ |
+<p id="faEff_6"> |
+It is still not optimum to be re-resolving the <code>elements</code> |
+collection, and it is practical to assign a reference to that object |
+to a local variable instead of a reference to the form object:- |
+</p> |
+ |
+<pre id="faEff_ex4"> |
+<span class="commentJS">/* Assign a reference to the form's elements collection to the local |
+ variable - frmEls - and then make subsequent control references |
+ relative to that local variable: |
+*/</span> |
+var frmEls = document.forms["formName"].elements; |
+var txt1 = frmEls["field1"].value; |
+var txt2 = frmEls["field2"].value; |
+var txt3 = frmEls["field3"].value; |
+var txt4 = frmEls["field4"].value; |
+var txt5 = frmEls["field5"].value; |
+</pre> |
+ |
+<p id="faEff_7"> |
+With the original long form accessor the resolution starts with |
+resolving the <code>"document"</code> identifier. The |
+identifier is first looked for among the local variables of the |
+function (as a named property of the internal |
+"Variable" object, by ECMA specification), |
+when it is not found the scope chain is searched, object by object |
+down the chain, for a property with the corresponding name. When the |
+scope resolution for <code>"document"</code> gets to the |
+global object (at the end of the scope chain) it will find a property |
+called <code>"document"</code>, a reference to the |
+<code>document</code> object, and the first identifier in the accessor |
+will have been resolved. The next identifier is |
+<code>"forms"</code> and that is located as a property of the |
+<code>document</code>. Then the <code>"formName"</code> |
+property is identified in the <code>forms</code> collection. Next the |
+<code>"elements"</code> property of the form is located, |
+followed by the control name in that object and finally the |
+<code>"value"</code> property of the control is returned. |
+</p> |
+ |
+<p id="faEff_8"> |
+When a reference to the <code>elements</code> collection is assigned to |
+a local variable the first identifier in the property accessor is |
+identified as that local variable, the control name is identified as a |
+property of the <code>elements</code> collection referenced and the |
+<code>"value"</code> property of the control is returned. |
+</p> |
+ |
+<p id="faEff_9"> |
+Obviously there is a big difference in the amount of work involved in |
+acquiring the <code>value</code> of the control in each case. That |
+difference will not be that significant if only a couple of values are |
+accessed, but even with as few as half a dozen control property |
+accesses the second approach will obviously be much more efficient, |
+and with increasing numbers of controls the difference could easily |
+become apparent to the user. |
+</p> |
+</body> |
+</html> |
/cljs/notes/form-access/index.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/notes/posting/index.html |
=================================================================== |
--- cljs/notes/posting/index.html (nonexistent) |
+++ cljs/notes/posting/index.html (revision 2) |
@@ -0,0 +1,1209 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" |
+"http://www.w3.org/TR/html4/strict.dtd"> |
+<html lang="en"> |
+<head> |
+<title>Notes on the comp.lang.javascript FAQ</title> |
+<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> |
+<link href="../../faq.css" rel="stylesheet" type="text/css"> |
+<link href="../notes.css" rel="stylesheet" type="text/css"> |
+<meta name="ROBOTS" content="NOINDEX, NOFOLLOW"> |
+<style type="text/css"> |
+.resourceList LI { |
+ margin-bottom: 0.8em; |
+} |
+</style> |
+</head> |
+<body> |
+ |
+<h1>Posting Questions and Replies to comp.lang.javascript</h1> |
+<div id="faqNav"> |
+ <a href="../../">FAQ</a> > <a href="../">FAQ Notes</a> |
+ |
+</div> |
+<ul> |
+ <li><a href="#ps1Intro">Introduction</a></li> |
+ <li><a href="#ps1Lang">Posting Language</a></li> |
+ <li><a href="#ps1OToc">On and Off Topic Posting</a></li> |
+ <li><a href="#ps1Txt">Plain-Text Only</a></li> |
+ <li><a href="#ps1Post">Interleaved Posting, Bottom Posting and Not Top Posting.</a> |
+ <ul> |
+ <li><a href="#ps1InBPost">Interleaved Posting, Bottom Posting</a></li> |
+ <li><a href="#ps1TopPs">Top Posting (don't)</a></li> |
+ </ul> |
+ </li> |
+ <li><a href="#ps1Trim">What to Trim</a></li> |
+ <li><a href="#ps1Marg">Margins and Line Wrapping</a> |
+ <ul> |
+ <li><a href="#ps1Mar">Margins</a></li> |
+ <li><a href="#ps1Lw">Line Wrapping</a></li> |
+ <li><a href="#ps1LwQu">Line Wrapping in Quoted Material</a></li> |
+ </ul> |
+ </li> |
+ <li><a href="#ps1Code">General Code Postings, and when to use a URL</a></li> |
+ <!-- <li><a href="#ps1Proof">Proof-read your message</a></li> --> |
+ <li><a href="#ps1Quest">Well Asked Questions Get the Best Answers</a> |
+ <ul> |
+ <li><a href="#ps1QSub">Appropriate Use of the Subject Header</a></li> |
+ <li><a href="#ps1QRes">Doing Your Own Research</a></li> |
+ <li><a href="#ps1DontWork">"It doesn't work"</a></li> |
+ <li><a href="#ps1CntX">Explain the Whole Context</a></li> |
+ <li><a href="#ps1PR">Proof-Read your Questions</a></li> |
+ </ul> |
+ </li> |
+ <!-- <li><a href="#ps1notHD">comp.lang.javascript is Not a Helpdesk</a></li> --> |
+ <li><a href="#ps1AddR">Additional Reading</a></li> |
+</ul> |
+ |
+<h2 id="ps1Intro">Introduction</h2> |
+<h3>Social Behavior</h3> |
+ |
+<p> |
+There may be several reasons for making posts to comp.lang.javascirpt |
+but all valid reasons would be intended to elicit responses, preferably |
+including responses form the many experienced and knowledgeable |
+regular contributors to the group. The direction of communication is |
+always one-to-many, which places the onus on the composer of a message |
+to consider the many in their audience above any personal preferences. |
+It is always in the best interest |
+of someone posting to the group to recognise that the people whose |
+responses will be of most value to them may have an attitude toward |
+their behaviour on the group, and to try to ensure that it will not be |
+a bad attitude. |
+</p> |
+ |
+<p> |
+It is also always in the best interest of any poster to the group to do |
+everything within their power to behave in a way that makes it quick |
+and easy for the people they expect to answer their questions to read and follow |
+their posts, understand their questions and problems and comprehend and |
+test posted code. The people with the best answers are the most likely |
+to be busy; too busy to be interested in unraveling a badly expressed |
+problem from a mass of incomprehensibly formatted code amid a |
+conversation that is hard to follow. |
+</p> |
+ |
+<p id="ps1Into_3"> |
+Usenet has been around for a long time now and has developed various |
+conventions of its own. Conventions that have evolved to make |
+communicating in the medium as easy and efficient as possible. They |
+are not necessarily adhered to on all groups but where they are |
+recognised they are definitely preferred. And comp.lang.javascript is |
+a group where most of the regulars recognise many Usenet conventions |
+and so the FAQ outlines them. This document is intended to provide |
+additional detail on the subject. |
+</p> |
+ |
+<p id="ps1Into_4"> |
+Following those conventions and additionally posting with a |
+consideration of the other points made on this page related more |
+specifically to posting in comp.lang.javascript, will maximise the |
+potential for any questions asked and posts made to elicit a useful |
+response. At least in part because they make it quicker and easier for |
+those interested in offering help to do so. |
+</p> |
+ |
+<h2 id="ps1Lang">Posting Language</h2> |
+ |
+<p id="ps1Lang_1"> |
+comp.lang.javascript is the international javascript group. There are |
+language specific javascript groups that could be expected to be |
+carried by news servers within the countries concerned. There is, |
+however, no English language specific javascript group so |
+comp.lang.javascript serves that audience. As a result the vast |
+majority of the conversation within the group is in English, and |
+anyone with a javascript interest but incapable of reading/writing any |
+language but English would choose comp.lang.javascript to read and post |
+in. But there are no rules that say that English is the only language |
+that is to be used. |
+</p> |
+ |
+<p id="ps1Lang_2"> |
+As an international group, comp.lang.javascript has contributors form |
+around the world, many of whom speak/read/write English as a second or |
+third (+) language. So a post made in any other language will stand a |
+chance of falling within the linguistic capabilities of someone. But |
+posts in English should be understandable to everyone, including those |
+for whom English is their only language, and thus receive the most |
+attention. |
+</p> |
+ |
+<p id="ps1Lang_3"> |
+Machine translation into English (and sometimes less skilled human |
+translation) sometimes does not produce results that can be |
+understood/followed by English speakers. When a bad translation into |
+English is the only option it might be better for a poster to precede |
+it with a version in their native language. (Faced with a post in a |
+language that is not understood it is natural to scroll down to see |
+if there is any accompanying javascript code that might explain the |
+problem; a following English translation would be discovered along |
+the way). A reader of the group who understands the language used |
+may be able to contribute improvements to the English translation even |
+if they cannot directly address the question raised. |
+</p> |
+ |
+<p id="ps1Lang_4"> |
+However, even though the most common language used in postings to |
+comp.lang.javascript is English, the fact that the group is |
+international and that English should not be expected to be the first |
+language of contributors to the group means that the English used |
+should be formally correct (to the best of the posters ability). |
+Normal English sentence structure should be observed, particularly in |
+terms of capitalisation (which serves to aid reading for everyone). But |
+above all, shorthand abbreviations should not be used, no matter how |
+common they may be in English speaking cultures, as they would not |
+normally be part of the teaching of English as a foreign language. This |
+applies especially to text-message shorthand as they are very much a |
+product of local culture and circumstances in a way that is not |
+relevant to Usenet as a medium or appropriate to an international |
+newsgroup. |
+</p> |
+ |
+<p id="ps1Lang_5"> |
+In the context of an international forum it is also probably best to |
+avoid references that may be ambiguous outside of a national context. |
+Date formats are an obvious example, with the ISO 8601 <code>YYYY-MM-DD</code> format |
+being more appropriate than any preferred local form. Also, references |
+to national bodies by acronym alone will not necessarily convey |
+sufficient meaning to an international audience. |
+</p> |
+ |
+<h2 id="ps1OToc">On and Off Topic Posting</h2> |
+ |
+<p id="ps1OToc_1"> |
+ECMA 262 is the formal specification for ECMAScript, the |
+standard adopted by javascript implementations and thus the |
+specification for javascript. |
+</p> |
+ |
+<h3>ECMAScript and Browsers</h3> |
+<p id="ps1OToc_2"> |
+As comp.lang.javascript deals with ECMAScript and ECMAScript was |
+designed as a general scripting language for scripting any object |
+model, questions relating to any application of ECMAScript are |
+appropriate. The group has a general bias towards the use of |
+ECMAScript in web browsers in an Internet context, and questions |
+asked without additional qualification will tend to be assumed to |
+be related to that environment and context. As a result it is a |
+very good idea for questions asked that are not related to that |
+default context; Intranet, other hosts, OS automation, etc., to |
+include details of that context. |
+</p> |
+ |
+<h3 id="ps1OToc_3">Javascript (not Java)</h3> |
+<p> |
+Because of the name "JavaScript" being applied to the |
+language early in its existence there is often confusion between |
+javascript and the Java programming language. The two are distinct |
+and very different languages. Questions relating to Java programming, |
+Java Applets, Java Server Pages (JSP), etc., would be better asked in |
+comp.lang.java.* groups. Only the use of ECMAScript to interact with, |
+say, Java Applets would be on topic, and then the questions should |
+relate to the ECMAScript aspect of the problem. |
+</p> |
+ |
+<h3 id="ps1OToc_4">Other Languages</h3> |
+<p> |
+Questions relating exclusively to other scripting languages, |
+ mark-up languages ((x)<span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span>) and style sheets |
+(<span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span>, XSL) are off topic and should be addressed to more |
+appropriate newsgroups. |
+</p> |
+ |
+<h3 id="ps1OToc_5">The FAQ</h3> |
+<p> |
+The comp.lang.javascript newsgroup may also validly become its own |
+subject, particularly the content and maintenance of the FAQ resources. |
+But as a subject that is most appropriately raised and discussed by |
+the individuals who invest their time in the group rather than |
+passers-by. |
+</p> |
+ |
+<h3 id="ps1OToc_6">Usenet Behavior (don't)</h3> |
+<p> |
+Usenet, and particularly appropriate behaviour on and for Usenet, is |
+also often raised. This is largely unwelcome but inevitable. Hopefully |
+this document should contribute to a reduction in that noise by stating |
+the group's attitude towards Usenet postings in greater detail than can |
+be accommodated in the FAQ proper. |
+</p> |
+ |
+<h3 id="ps1OToc_7">Spam (don't)</h3> |
+<p> |
+Other things that are off topic for the group include obvious things |
+like pyramid and get rich quick schemes, commercial advertising (with |
+some rare exceptions mentioned below), job adverts, spurious |
+invitations to visit web sites and anything else that might be |
+reasonably regarded as spam. |
+</p> |
+ |
+<h3>Announcements</h3> |
+<p id="ps1OToc_8"> |
+Announcements of product releases and events of particular relevance |
+to javascript are welcome but, for products no more often than once |
+pre major release, and for events preferably only once and certainly |
+not more often than at two month intervals leading up to the event. |
+Be aware that product announcements (particularly commercial |
+javascript) are likely to attract reviews, which should not be |
+expected to be uncritical. |
+</p> |
+ |
+<h2 id="ps1Txt">Plain-Text Only</h2> |
+ |
+<p id="ps1Txt_1"> |
+Messages are posted in plain-text. There is no requirement for Usenet |
+newsreader software to recognise, support or display any other |
+content type, such as <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span>, and it is felt that messages posted to |
+comp.lang.javascript should be available to any and all newsreader |
+software. Any form of attachments are also ruled out. |
+</p> |
+ |
+<p id="ps1Txt_2"> |
+It has also been observed that while most of the world may be happy |
+to use the newsreader bundled with their operating system, experts in |
+various aspects of computing will often go out and acquire software |
+that they believe superior for the task they have for it. Meaning that |
+the people best equipped to offer help in the group are also the people |
+least likely to be using the newsreader that you are familiar with. |
+The expectation should be that others are using software that conforms |
+to the applicable standards and not that they are using software with |
+any particular set of additional or "enhanced" features, no |
+matter how common they may seem. Plain-text posts will be readable by |
+everyone, other content types may be subject to more comment on the |
+inappropriateness of the content type than answers intended to address |
+the question raised. |
+</p> |
+ |
+<h2 id="ps1Post">Interleaved Posting, Bottom Posting and Not Top Posting</h2> |
+ |
+<h3 id="ps1InBPost">Interleaved Posting, Bottom Posting</h3> |
+ |
+<p id="ps1InBPost_1"> |
+The posting style in messages intended as responses to other messages |
+is an area where a long established pattern of behaviour has been |
+recognised as most appropriate for the medium and become an established |
+convention. |
+</p> |
+ |
+<p id="ps1InBPost_2"> |
+Material quoted from the previous message is attributed to its author |
+and indented with a marker character (usually >). It is trimmed down |
+to just sufficient to provide the context in which the response is made |
+(marking the fact that an edit has been made with one of several |
+common notations, such as: <snip>, [snip], [ ... ], etc.) and |
+the responding text is placed <em>below</em> the quoted material |
+to which it is responding, separated from it by a blank line. |
+</p> |
+ |
+<p id="ps1InBPost_3"> |
+If the response addresses several points from the previous message |
+then the parts of the quoted text providing the context for each |
+point are separated by the responses to each point. Producing an |
+interleaved post. If the quoted material is in one block then the |
+response text goes after it at the bottom. Producing a bottom post. |
+</p> |
+ |
+<p id="ps1InBPost_4"> |
+It is not possible to distinguish between bottom posting and an |
+interleaved post that is only responding to one point in the previous |
+message. Personally, I prefer interleaved responses but neither will |
+result in an adverse reaction. The important points are that quoted |
+material should be trimmed to the minimum that provides sufficient |
+context and that responses should follow that quoted material. |
+The conversation, and its chronological sequence, flows in the normal |
+direction of reading; top to bottom. |
+</p> |
+ |
+<p id="ps1InBPost_5"> |
+Failing to quote any of the preceding message is not necessarily |
+wrong, so long as the text posted makes sense without the preceding |
+message, for example, by summarising the points being responded to. |
+But generally it is easier to provide the context for a response with |
+a quoted snippet. But responses need to have a context. |
+</p> |
+ |
+<h3 id="ps1TopPs">Top Posting (don't)</h3> |
+ |
+<p id="ps1TopPs_1"> |
+Top posting is placing the response above the quoted material that is |
+being responded to. The chronological sequence of conversation becomes |
+the reverse of the normal top to bottom reading sequence and, without |
+additional text summarising the points being responded to, it is |
+difficult to determine exactly which points such a reply relates to. |
+</p> |
+ |
+<p id="ps1TopPs_2"> |
+The worst possible style of response posting is top posting over a full |
+verbatim quote of the previous message, but even placing a response |
+above a trimmed quote is wrong. It renders the conversational aspects |
+of a response backwards, requiring people to scroll up and down to |
+reconstruct the context of the response and generally making it hard |
+work to understand the message. The answers come before the questions |
+and the comments precede their subjects. |
+</p> |
+ |
+<p id="ps1TopPs_3"> |
+People do attempt to justify top posting. A common excuse made by top |
+posters is that their newsreader places the cursor at the top of the |
+message so that is the natural place to write the reply. That excuse |
+is worthless as newsreader software does not dictate the style of |
+posting and a cursor that starts at the top of a post does not have |
+to stay there. Indeed it should not be expected to stay there, as the |
+first responsibility of the respondent is to trim the quoted material |
+down to just what is necessary to provide context for their response. |
+A process that may reasonably be achieved by moving down through the |
+quoted material deleting whatever is unneeded and marking those edits. |
+And having done that the cursor will be at or near the bottom. |
+</p> |
+ |
+<p id="ps1TopPs_4"> |
+The other common excuse for top posting is that avoids excessive |
+scrolling in order to find the response. The need for excessive |
+scrolling in an interleaved or bottom posted message is most likely |
+an indicator that the quoted material has not been suitably, or |
+sufficiently, trimmed. But a top posters apparent desire to avoid |
+scrolling is of no value to the regular users of Usenet who are |
+accustomed to interleaved/bottom posting. They may take the top |
+post as a preamble and still scroll down to see if any specific |
+points have been responded to, not discovering that hey have wasted |
+their time until they get to the bottom. A very short top post, |
+without a blank line separating it from the following attribution |
+line, may easily be missed by someone expecting the quoted material |
+to come first, meaning that they do not discover where to look until |
+they have scrolled to the bottom, and then they need to back scroll |
+to the top. The perception is wrong, top posting results in much more |
+unnecessary scrolling than it avoids, and that misperception impacts on |
+regular user of Usenet; the very people whose help and co-operation is |
+being sought. |
+</p> |
+ |
+<p id="ps1TopPs_5"> |
+<strong>Never top post to comp.lang.javascript</strong>. There is an |
+established convention in posting styles on Usenet, and |
+comp.lang.javascript. It is most efficient for everyone if newcomers |
+follow that convention even if it seems strange to do so at first. In |
+the long run it makes life easier for everyone, and the sooner that is |
+recognised the less likelihood there is of being taken for a fool. |
+</p> |
+ |
+<h2 id="ps1Trim">What to Trim</h2> |
+ |
+<p id="ps1Trim_1"> |
+As a general guide, quoted material should almost never exceed the |
+text posted in response. Exceptions might occur when both consist |
+of exactly one line or sentence, or maybe a short code block that |
+only needs a one line comment. |
+</p> |
+ |
+<p id="ps1Trim_2"> |
+Deciding what to trim is a matter of judgment and takes a bit of |
+practice to get right. There are few hard and fast rules and the best |
+general advice has got to be to observe the behaviour of others |
+positing to the group. |
+</p> |
+ |
+<p id="ps1Trim_3"> |
+It is necessary to preserve the context in |
+which a response is made but some things can be trimmed automatically: |
+Signatures (if present); the section at the end of a post (and they |
+should always, and only, be at the end, no matter where any individual |
+newsreader may try to insert them) which starts with a separator |
+consisting of "dash dash space newline(aka return)" on a |
+line of its own, followed by material that is not directly |
+related to the post but may be of more general interest or related |
+to the individual who makes the post, should <strong>always</strong> |
+be trimmed from quoted material. It is never normally relevant to a |
+posted response, but even if a signature is being directly commented |
+upon it is vital to remove the signature separator at least, and best |
+to trim anything it contains that is not being commented upon. |
+</p> |
+ |
+<p id="ps1Trim_4"> |
+In comp.lang.javascript there is rarely much point in quoting |
+javascript code that is not being directly commented upon or |
+corrected. The indenting character (and possible line wrapping) |
+renders any quoted code syntactically invalid so anyone wanting |
+to use the code will have to go back to the message in which it |
+originally appeared anyway. That would certainly apply to a post |
+wishing to thank someone who had provided a complete scripted |
+demonstration for their efforts. |
+</p> |
+ |
+<p id="ps1Trim_5"> |
+No matter what gets trimmed the material that stays should not be |
+altered in terms of spelling, words used and their order, etc. A |
+quote should be a quote not an interpretation. |
+</p> |
+ |
+<h2 id="ps1Marg">Margins and Line Wrapping</h2> |
+<h3 id="ps1Mar">Margins</h3> |
+ |
+<p id="ps1Mar_1"> |
+A line in a plane text Usenet post could be quite long, and some |
+newsreaders would automatically wrap that line to the window in |
+which it was being displayed. Others would provide horizontal scroll |
+bars (usually undesirable) and yet others may not be able to access |
+characters beyond the 80<sup>th</sup> (unlikely these days). There |
+are no rules for handling excessively long lines but Usenet is old |
+and has lived through the time when 80 character wide displays were |
+commonplace. Along the way it became the convention that Usenet posts |
+should have lines no longer than between 70 and 80 characters. And |
+that avoids the need for any specified requirement in the handling of |
+long lines by newsreader software. Lines in that range are unlikely to |
+need to be wrapped for display and will not normally generate |
+horizontal scroll bars. It is also the case that humans generally |
+(and sometimes strongly) prefer to read text that is no more than about |
+80 character per line. |
+</p> |
+ |
+<p id="ps1Mar_2"> |
+It is widely recommended that newsreader software should be configured |
+to automatically wrap at about 72 characters when posting, which works |
+well for posted text but can be problematic for posting long URLs and |
+particularly in our context, posted source code. Others suggest that |
+software should not be allowed to wrap posted code at all and that the |
+poster should always do it manually. In either case it is the |
+individual composing the post that is responsible for, and should be in |
+control of, the wrapping of the content to ensure that it is suitable |
+for posting to the group. |
+</p> |
+ |
+<h3 id="ps1Lw">Line Wrapping</h3> |
+ |
+<p id="ps1Lw_1"> |
+Most URLs are less than 72 character long anyway but some, such as |
+references to Usenet articles in the archives at groups.google.com, |
+are longer. Some newsreader software is smart enough to recognise a |
+URL and not apply its default margin settings to them but in any event |
+delimiting them with "<URL:" at the beginning and |
+">" at the end (preferably with the URL separated from |
+the delimiters with spaces) should be sufficient to indicate to a |
+reader that a line wrapped URL will need some remedial action. |
+</p> |
+ |
+<p id="ps1Lw_2"> |
+Restricting margins to 72 characters usually does not need to affect |
+the functionality of posted code either. Allowing a newsreader to |
+line wrap posted code as it sees fit will usually render that code |
+faulty (and difficult to read) and that will make it difficult for |
+a reader to differentiate between problems within the original code |
+and problems arising form line wrapping. |
+</p> |
+ |
+<h3 id="ps1Lw_3">Code Reformatting</h3> |
+<p> |
+Javascript (ECMAScript) is extremely tolerant of white space (including |
+line breaks) within its source code. There are in fact only a couple of |
+places where white space characters are not allowed. For example, a |
+line break may not be placed between the <code>return</code> keyword |
+and any expression that is to be returned. As a result it is almost |
+always possible to spread a line of javascript that would exceed the |
+newsreaders wrapping margin across two or more lines without affecting |
+its functionality or syntactic correctness. |
+</p> |
+ |
+<p id="ps1Lw_4"> |
+One of the main reasons that Javascript is so tolerant of white space |
+is to allow the structure of the source code (how the code is laid out |
+in a text editor/post) to convey additional meaning (usually related to |
+structure of the code/function/program) and maximise clarity for human |
+readers. The breaking of long lines of source code across several lines |
+should be done in a way that does not detract from the clarity of the |
+code. |
+</p> |
+ |
+<h4 id="ps1Lw_5">Blocks</h4> |
+<p> |
+The main source code structuring consideration that adds clarity is |
+block indenting. A block is defined with curly brackets <code>{</code> |
+and <code>}</code> and represents a block statement (which may contain |
+zero or more other statements). It is normal to indent the statements |
+within a block by one tab character, though that tab is usually set to |
+4 or fewer spaces (two spaces is frequently recommended) width as the |
+normal default 8 spaces width is a bit |
+too deep for most practical uses. However, <em>tab character should not be |
+used for indention in Usenet posts at all</em> as newsreader default tab |
+settings may often be 8 characters but may also be zero characters, |
+defeating the purpose indentation in posted code entirely. Good text |
+editors will usually offer a facility to convert tabs to any number of |
+spaces, which can be used to prepare code for posting. Indenting in |
+code posted to Usenet should be done with space characters. 4 or fewer |
+(two is often recommended) per level of indentation. |
+</p> |
+ |
+<p id="ps1Lw_6"> |
+There are various common styles of block indenting, of which I prefer |
+to leave the opening <code>{</code> at the end of the control statement |
+(on the same line) and list the block contents as one statement per |
+line, indented by 4 <em>or fewer</em> spaces, with the closing |
+<code>}</code> on a new line indented so that it lines up vertically |
+with the start of the control statement, e.g.:- |
+</p> |
+ |
+<pre id="ps1Lw_ex1"> |
+function doSomething(oArea){ |
+ var nArea = oArea.nWidth * oArea.nHeight; |
+ var result = true; |
+ if(!nArea){ |
+ removeRegion(oArea); |
+ result = false; |
+ }else if(oArea.nWidth < oArea.nHeight){ |
+ result = oArea.reShape(nArea); |
+ } |
+ return result; |
+} |
+ |
+<span class="commentJS">/* The same function may also be commonly formatted:- */</span> |
+ |
+function doSomething(oArea) |
+{ |
+ var nArea = oArea.nWidth * oArea.nHeight; |
+ var result = true; |
+ if(!nArea) |
+ { |
+ removeRegion(oArea); |
+ result = false; |
+ } |
+ else if(oArea.nWidth < oArea.nHeight) |
+ { |
+ result = oArea.reShape(nArea); |
+ } |
+ return result; |
+} |
+ |
+<span class="commentJS">/* -or:- */</span> |
+ |
+function doSomething(oArea) |
+ { |
+ var nArea = oArea.nWidth * oArea.nHeight; |
+ var result = true; |
+ if(!nArea) |
+ { |
+ removeRegion(oArea); |
+ result = false; |
+ } |
+ else if(oArea.nWidth < oArea.nHeight) |
+ { |
+ result = oArea.reShape(nArea); |
+ } |
+ return result; |
+ } |
+</pre> |
+ |
+<p id="ps1Lw_7"> |
+It is not that important which style of block indenting is used, |
+everyone has their own preferred style, but it is important that |
+<em>a</em> style of block indenting is used in code posted to the |
+group. In all cases the indenting serves to make the structure of |
+the function apparent in the structure of the source code. It is |
+an aid to human readers of the code and saves a great deal of time |
+for anyone attempting to offer help and so needing to understand |
+the code. |
+</p> |
+ |
+<p id="ps1Lw_8"> |
+Sometimes the line wrapping problem can be avoided by reducing the |
+number of space characters by which the blocks are indented. However, |
+if a statement must be broken across several lines |
+it could be indented to a different level than it's own start, and it |
+could also be indented at a different level to its block contents (if |
+any). If block indenting is at, say, 4 space intervals then indenting a |
+broken line at 1 to 3 characters should serve to make it clear that |
+it is indenting separate from the general block structure of the |
+code, e.g.:- |
+</p> |
+ |
+<pre id="ps1Lw_ex2"> |
+function getRootElement_OrDefault(deflt){ |
+ if((typeof document.compatMode == "string")&& |
+ (document.compatMode.indexOf("CSS") != -1)&& |
+ (document.documentElement)){ <span class="commentJS">//<< broken statement</span> |
+ return document.documentElement; |
+ }else if(document.body){ |
+ return document.body; |
+ }else{ |
+ return deflt; |
+ } |
+} |
+ |
+</pre> |
+ |
+<p id="ps1Lw_9"> |
+Another alternative for formatting statements broken across lines |
+might be to disregard the indenting on the left and line the code |
+that belongs to the broken statement up on the right hand side. |
+e.g.:- |
+</p> |
+ |
+<pre id="ps1Lw_ex3"> |
+this.position = function(){ |
+ var twiceSize; |
+ if(--delay <= 0){ |
+ step(); |
+ if(((z+=fv) >= planeDepth)|| |
+ ((dy+dm) > windowCenterY)|| |
+ ((dx+dm) > windowCenterX)|| |
+ (v < 0)){ <span class="commentJS">//right aligned broken statement</span> |
+ this.reset(); |
+ step(); |
+ } |
+ div.top = (sy+(py*dy)-dm)+cssUnitsOrZero; |
+ div.left = (sx+(px*dx)-dm)+cssUnitsOrZero; |
+ divClip.height = (twiceSize = (dm << 1)+cssUnitsOrZero); |
+ divClip.width = twiceSize; |
+ } |
+ next.position(); |
+}; |
+</pre> |
+ |
+<p id="ps1Lw_10"> |
+Thus the ability to insert line breaks liberally throughout javascript |
+source code allows almost all code to be formatted in a fully |
+functional, well structured and clear way within the restricted |
+margins appropriate in posts to comp.lang.javascript. Efforts put into |
+preparing posted code to be clear and comprehensible to its Usenet |
+audience will be rewarded. But it is important to start any formatting |
+required with the actual code in use, rather than attempting to |
+re-type it, in order not to introduce errors that are not present in |
+the original and so have nothing to do with the original problem. |
+Having prepared the formatting of the code to suite Usenet it is |
+important to re-test it to ensure that it is still as functional, that |
+no errors have been introduced and that it still exhibits whatever |
+behaviour it was that motivated the post in the first place. |
+</p> |
+ |
+<h3 id="ps1LwQu">Line Wrapping in Quoted Material</h3> |
+ |
+<p id="ps1LwQu_1"> |
+If a news post has been wrapped at, say, 72 characters and it is |
+responded to then the indenting character used to mark quoted material |
+will add to the length of that line. Maybe pushing it over the length |
+at which the reply will be wrapped. The result, if posted without |
+adjustment, may look something like this:- |
+</p> |
+ |
+<pre id="ps1LwQu_ex1"> |
+An example OP wrote: |
+> A long line of text quoted from the previous post, that was wrapped |
+at |
+> 72 characters in that post but has been extended to 74 characters |
+long |
+> lines because of the addition of the indenting characters that mark |
+it |
+> as a quotation, but has been re-wrapped to 72 characters in the |
+posted |
+> follow-up that is quoting it. |
+ |
+The comment posted in response to the material quoted above. Originally |
+wrapped in the response at 72 characters. |
+</pre> |
+ |
+<p id="ps1LwQu_2"> |
+The effect is that the words "at", "long", |
+"it" and "posted" are no |
+longer marked as part of the quotation but instead appear to be badly |
+formatted and meaningless comments on that quoted material. Which has |
+itself gained the appearance of being incompetently trimmed. The effect |
+escalates with additional responses, loosing more meaning and becoming |
+less and less clear as to whom any particular part of the text is |
+attributable. |
+</p> |
+ |
+<pre id="ps1LwQu_ex2"> |
+The First Responder wrote: |
+> An example OP wrote: |
+>> The First Responder wrote: |
+>>> An example OP wrote: |
+>>>> A long line of text quoted from the previous post, that was |
+wrapped |
+>>> at |
+>>>> 72 characters in that post but has been extended to 74 characters |
+>>> long |
+>>>> lines because of the addition of the indenting characters that |
+mark |
+>>> it |
+>>>> as a quotation, but has been re-wrapped to 72 characters in the |
+>>> posted |
+>>>> follow-up that is quoting it. |
+>>> |
+>>> The comment posted in response to the material quoted above. |
+>> Originally |
+>>> wrapped in the response at 72 characters. |
+> |
+>> This response is the OP's reply to the comments on the original |
+>> post. It quoted the previous posts in full and was wrapped at 72 |
+>> characters. |
+> |
+>And the original responder added this. |
+ |
+The conversation ended with the OP thanking the responder for their |
+comments. (but who said what?) |
+</pre> |
+ |
+<p id="ps1LwQu_3"> |
+The solution is to be aware that this may happen and re-wrap that |
+quoted material so that it is not effected by the automatic line |
+wrapping when a post is sent, or to increase the wrapping margins by |
+the number of characters inserted to mark a quotation (so long as the |
+result does not exceed 80 characters). Some newsreader software can |
+handle this automatically, and add on software exists for other |
+products (such as OE), but ultimately the responsibility for properly |
+marking and attributing quoted material belongs with the individual |
+making the post. |
+</p> |
+ |
+<p id="ps1LwQu_4"> |
+If the two had taken the effect of the progressive lengthening of lines |
+in quoted material into account the result would have looked like |
+this:- |
+</p> |
+ |
+<pre id="ps1LwQu_ex3"> |
+The First Responder wrote: |
+> An example OP wrote: |
+>> The First Responder wrote: |
+>>> An example OP wrote: |
+>>>> A long line of text quoted from the previous post, that was |
+>>>> wrapped at 72 characters in that post but has been extended to 74 |
+>>>> characters long lines because of the addition of the indenting |
+>>>> characters that mark it as a quotation, but has been re-wrapped to |
+>>>> 72 characters in the posted follow-up that is quoting it. |
+>>> |
+>>> The comment posted in response to the material quoted above. |
+>>> Originally wrapped in the response at 72 characters. |
+> |
+>> This response is the OP's reply to the comments on the original |
+>> post. It quoted the previous posts in full and was wrapped at 72 |
+>> characters. |
+> |
+>And the original responder added this. |
+ |
+The conversation ended with the OP thanking the responder for their |
+comments. |
+</pre> |
+ |
+<p id="ps1LwQu_5"> |
+It would have been clear form the number of quote indicating characters |
+who exactly had said what and the quoted material would have been |
+easier to read and understand. Though in practice there probably should |
+have been much more trimming along the way as the whole conversation |
+would probably not have been needed to show the context of each |
+response. |
+</p> |
+ |
+ |
+<h2 id="ps1Code">General Code Postings, and when to use a URL</h2> |
+ |
+<p id="ps1Code_1"> |
+Often a question cannot usefully be answered without being accompanied |
+with javascript source code. Even a very detailed explanation of a |
+process will not tend to narrow the possibilities down to just one |
+method, and deciding whether a reported effect is due to a |
+characteristic of an execution environment or code that is taking the |
+wrong approach cannot be done without seeing the source code. |
+</p> |
+ |
+<p id="ps1Code_2"> |
+In some cases small snippets of code, say an individual function's |
+definition, might be sufficient. Though it is usually necessary to know |
+how such a function is being called and what arguments it is using. But |
+ideally questions should be accompanied by an easily testable example |
+that demonstrates the characteristics that provoked the question. |
+</p> |
+ |
+<p id="ps1Code_3"> |
+Easily testable because there is no better aid to debugging than being |
+able to reproduce a problem. Time spent turning a snippet of code into |
+testable web page (or whatever) is not rewarded if the results do not |
+exhibit the problem described. And asking many people to repeat that |
+process when it could have been done by the questioner once, in a way |
+that guaranteed a demonstration of the problem, is not a good use of |
+the group or the time of its participants. |
+</p> |
+ |
+<p id="ps1Code_4"> |
+However, posting the entire source code of a web page that happens to |
+include the problematic script is rarely the answer. For one thing web |
+pages often import <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span>, other script files and graphics (the latter |
+simply could not be posted to the group). But web pages also often |
+consist of large amounts of <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span>, which would require careful |
+re-wrapping to fit within the posting margins and be left correct, and |
+much of the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> would be irrelevant to the post. |
+</p> |
+ |
+<p id="ps1Code_5"> |
+There is also the question of bandwidth in transmission and capacity in |
+storage. Every post is stored, at least for a time, on every news server |
+carrying the group world wide and usually also on the hard disk of |
+everyone who reads the group. And to get from server to server, and |
+eventually to the many readers, it must be transmitted, consuming |
+bandwidth related to the size of the post. The more irrelevant |
+information that any post contains the more those resources are wasted |
+(this is also a reason for appropriate trimming of quoted material). |
+</p> |
+ |
+<p id="ps1Code_6"> |
+The comp.lang.javascript FAQ makes the injunction that posting code of |
+more than 500 lines is unacceptable. That is the theoretical upper |
+limit that should never be exceeded, but a post of even half that |
+length would have to be exceptional. |
+</p> |
+ |
+<p id="ps1Code_7"> |
+The easiest way of demonstrating a problem in context without posting |
+excessive amounts of code and <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> is to make a page that exhibits the |
+problem available online and post the URL of that page along with the |
+question. Possibly accompanied by a snippet of the code highlighting |
+the suspected cause. |
+</p> |
+ |
+<p id="ps1Code_8"> |
+The circumstances under which making a page that demonstrates the |
+problem available online is advisable are, whenever that page is |
+interacting within a frameset, or whenever images play a significant |
+part in a problem. As those circumstances are time consuming to |
+reproduce from posted code and cannot always be recreated for testing. |
+But any request to have people examine excessive amounts of code |
+and/or <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> should also be made available on line instead of in a post. |
+</p> |
+ |
+<p id="ps1Code_9"> |
+Unfortunately not all participants in the group are viewing Usenet in a |
+way that makes easily following a URL to an example page viable. Often |
+downloading new Usenet posts as a batch and then viewing them off line. |
+Re-connecting to view an example page is not always desirable (due to |
+local conditions, slow modem connections and potential associated |
+expense) and can be unrewarding if the page viewed is a mush of <abbr title="What You See Is What You Get">WYSIWYG</abbr> |
+generated bloated <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span>-like noise. Where it takes a considerable time |
+to even locate the cause of what may still turn out to be a trivial |
+problem. |
+</p> |
+ |
+<p id="ps1Code_10"> |
+Then again there are people using the group who much prefer examples to |
+be available online. Either way what is not wanted is for questions to |
+be asked without making the corresponding code available in some way, |
+or the posting of excessive amounts of code. |
+</p> |
+ |
+<p id="ps1Code_11"> |
+A good compromise, and a valuable debugging technique, is the creation |
+of a demonstration test-case page. A page containing no more than |
+sufficient <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> and javascript to allow others to reproduce the problem |
+and see the relevant code without anything extraneous. Such a test-case |
+page would almost always be short enough to post with the question |
+(properly formatted) and could additionally be made available online for |
+the convenience of those that would prefer to use a URL to load it |
+directly into a browser for testing. |
+</p> |
+ |
+<p id="ps1Code_12"> |
+Creating such a test-case page can be valuable in itself as attempting |
+to reduce a problem from a larger context to an isolated demonstration |
+will often reveal the cause of that problem along the way. The act of |
+cutting out what initially seems irrelevant often reveals that the |
+problem in fact results form an unexpected interaction with something |
+that was assumed to be unconnected. And if the problem can be |
+demonstrated in isolation then it is relatively easy for readers of the |
+question to reproduce the problem and identify its cause, resulting in |
+less discussion of superfluous issues and usually a quicker resolution |
+of the question. |
+</p> |
+ |
+<p id="ps1Code_13"> |
+It is very important to test test-case pages prior to posting them to |
+ensure that they do indeed exhibit the characteristic that motivated |
+the question. At least if you want to be taken seriously in future. And |
+when such a test-case is posted to the group it should be formatted and |
+indented to facilitate the essayist reading of the code and testing by |
+no more than copying the page into a text editor and saving it locally |
+as a <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> file. |
+</p> |
+ |
+ |
+<h2 id="ps1Quest">Well Asked Questions Get the Best Answers</h2> |
+ |
+<p id="ps1Quest_1"> |
+Beyond any considerations of posting style and formatting, the quality |
+of questions asked has a considerable impact upon the number and |
+quality of answers given, and the time taken to elicit a useful |
+response. Vague questions are likely to be answered with requests for |
+clarification. Terse general questions are likely to elicit yes or no |
+answers (often both). And questions that have been asked, and well |
+answered, before (especially frequently or in the recent past) are as |
+likely as not to be ignored. |
+</p> |
+ |
+<p id="ps1Quest_2"> |
+When asking a question it would almost always be a good idea to put |
+yourself in the position of the reader of the question, read it back to |
+yourself and ask yourself; Does this question actually ask what I |
+want to know, and is it sufficiently clear and detailed to elicit that |
+answer? |
+</p> |
+ |
+<p id="ps1Quest_3"> |
+The following is a short list of recurring features of badly asked |
+questions:- |
+</p> |
+ |
+ |
+<h3 id="ps1QSub">Appropriate Use of the Subject Header</h3> |
+ |
+<p id="ps1QSub_1"> |
+Another Usenet convention holds that the Subject header should not be |
+expected to be available to a reader of any message. While it is |
+unlikely that there are any newsreaders currently in use in which the |
+user is not presented with the Subject header, it remains |
+inappropriate to ask a question in the subject header (or to assume |
+that its contents will provide supplementary information about a |
+question) and doing so is as likely to invoke a lesson in Usenet |
+etiquette as an answer to the question. But a question is not really |
+a subject anyway. The subject should describe what the question is |
+in relation to, and is useful for archive searching and |
+categorisation rather than as a means of communication. |
+</p> |
+ |
+<p id="ps1QSub_2"> |
+Any question asked should always appear in the body of the post, and in |
+a form that does not assume the availability of the Subject header to |
+the reader. |
+</p> |
+ |
+<p id="ps1QSub_3"> |
+The Subject header should also not be wasted. Placing "please |
+help" and the like in the subject header is unwelcome and |
+counterproductive. Take the opportunity to construct a Subject |
+header that states the type of the problem, what it relates to. |
+Subject headers that state the real subject will attract the |
+attention of people with a special interest in that subject, |
+exactly those people best able to offer help. |
+</p> |
+ |
+<h3 id="ps1QRes">Doing Your Own Research</h3> |
+ |
+<p id="ps1QRes_1"> |
+Many questions, at least the questions literally asked, could quickly |
+be answered with a little research, and the chances are that regulars |
+on the group know how easily those answers could have been found with |
+a little effort. The group is not intended to be a vending machine for |
+trivial information about javascript, that wouldn't be an interesting |
+group to participate in. |
+</p> |
+ |
+<p id="ps1QRes_2"> |
+On the other hand, evidence that some effort has been put into |
+researching a problem before asking a question tends to be looked upon |
+kindly (though claiming to have exhausted all lines of research when that |
+is obviously not the case would have the opposite effect). |
+</p> |
+ |
+<p id="ps1QRes_3"> |
+The obvious first place to look for answers is in |
+<a href="../clj_faq.html">the group's FAQ</a>. That will |
+mean reading all of the FAQ because the answers to some problems (or |
+sufficient clues to those answers) will be found within the answers to |
+seemingly unrelated questions, or the resources linked to from the FAQ. |
+That in itself is a fairly big task, but if not undertaken will just |
+result in questions being answered with references back to the FAQ. |
+There is also a Usenet convention that whenever a newsgroup |
+(particularly technical groups) provides a FAQ resource, that FQA should |
+be read by anyone wishing to post to the group <em>prior</em> to making |
+their first post. So reading the FAQ is <em>not optional</em> anyway. |
+</p> |
+ |
+<p id="ps1QRes_4"> |
+The Internet provides a massive resource for researching virtually any |
+question, and particularly questions relating to computing. Search |
+engines are the primary research tool and among those Google search is |
+extremely useful. But when a question relates to javascript in a way |
+that indicates that it may be suitable to be asked on |
+comp.lang.javascript the best place to research the question is |
+<a href="http://groups.google.com/groups?q=comp.lang.javascript"> |
+groups.google.com</a>, as that resource holds a searchable archive of |
+almost all postings ever made to the group. There is an |
+<a href="http://groups.google.com/advanced_group_search?group=comp.lang.javascript"> |
+"Advanced Search" page</a>, where entering |
+"comp.lang.javascript" in the Newsgroup field and suitable keywords |
+in the other fields provided will return all messages posted to the group |
+that match the search criteria. As most questions will have been asked |
+before many answers can be obtained from the groups.google.com archives. |
+But be aware of the date of posts found as the archive goes back to |
+1996 and some things have changed over the intervening years. |
+</p> |
+ |
+<p id="ps1QRes_5"> |
+Reading back over recent posts to the group, for a minimum of a week |
+and preferably more than a month will avoid the need to re-ask a |
+question that has been asked and answered in recent memory. Not all |
+news servers will hold all messages over that period so |
+<a href="http://groups.google.com/groups?q=comp.lang.javascript"> |
+the group archives at groups.google.com</a> can be useful in this |
+respect also. |
+</p> |
+ |
+<h3 id="ps1DontWork">"It doesn't work"</h3> |
+ |
+<p id="ps1DontWork_1"> |
+People don't tend to question code that |
+does exactly what they want it to do. Sometimes they may ask how it |
+does exactly what they want but generally it is superfluous to state |
+that code that does not address a situation doesn't work. |
+</p> |
+ |
+<p id="ps1DontWork_2"> |
+To start with computer code always does exactly what is asked of it, |
+that is the nature of computers. So it does "work", it is |
+just that it doesn't do what is wanted of it. And that is a problem |
+because code that does not do something that is wanted of it cannot |
+itself explain what that something was. |
+</p> |
+ |
+<p id="ps1DontWork_3"> |
+It is the task of a human designer to decide what is wanted form code, |
+to specify the task. The reader of a question can do no more than |
+guess as to the task unless the questioner explains the specification |
+for the code, and that specification needs to be specific. That |
+information is needed when assessing what would qualify as |
+"works" in the context of the question. |
+</p> |
+ |
+<p id="ps1DontWork_4"> |
+But in addition to knowing what would qualify as working it is also |
+necessary to know in what way code is failing to work. There is a big |
+difference between code that appears to do nothing when executed, code |
+that does something undesirable in addition to what is expected of it |
+and code that does something else entirely. |
+</p> |
+ |
+<p id="ps1DontWork_5"> |
+Instead of stating the self-evident "It doesn't work", the |
+posters of questions should attempt to provide answers to:- |
+</p> |
+ |
+<dl id="ps1DontWork_df"> |
+ <dt id="ps1DontWork_p1">1. What you have done?</dt> |
+ |
+ <dd id="ps1DontWork_d1">Providing access the code (possibly in the form of a test |
+ case), explaining the steps required to initiate the |
+ undesirable effect and the environments (usually web |
+ browsers) where the problem has been observed, so that it |
+ can be reproduced and tested. |
+ <dd> |
+ |
+ <dt id="ps1DontWork_p2">2. What you expected to happen?</dt> |
+ |
+ <dd id="ps1DontWork_d2">Both specifically in the case of the code under discussion and |
+ generally with regard to the design specification. |
+ <dd> |
+ |
+ <dt id="ps1DontWork_p3">3. What really happened?</dt> |
+ |
+ <dd id="ps1DontWork_d3">What was observed to happen and any error messaged generated. |
+ So that when (and if) the problem is reproduced in testing it |
+ is possible to identify it as the effect under discussion. |
+ <dd> |
+</dl> |
+ |
+<h3 id="ps1CntX">Explain the Whole Context</h3> |
+ |
+<p id="ps1CntX_1"> |
+The context in which a question is asked or a problem exists is very |
+important to the type of answers given or solutions proposed. Beyond |
+the obvious required details such as the execution host(s), scripts |
+used and how they are used, There are details like whether a project |
+is for the Internet or an Intranet. Because on comp.lang.javascript |
+the default assumption is that the context will be browser scripting |
+for the Internet, many approaches/solutions are ruled out, but some may |
+be completely reasonable and practical in the more restricted context |
+of a company Intranet (or on more controlled hosts such as the windows |
+scripting host or server-side javascript). |
+</p> |
+ |
+<p id="ps1CntX_2"> |
+There have been many occasions where many answers to questions have |
+stressed the unsuitability of particular approaches to use on the |
+Internet only for the original questioner to respond by explaining |
+that they don't apply because their context is an Intranet. That |
+wastes the time of everyone who composed a response to the original |
+question; if they had been in possession of the real context from the |
+outset they could have got on with proposing/discussing solutions that |
+were appropriate, or moved on to something more interesting. |
+</p> |
+ |
+<p id="ps1CntX_3"> |
+But the full context of a question goes beyond such details and answers |
+the question: why? Often a question will be asking about a particular |
+approach that, to the questioner, is a perceived solution to a problem. |
+The answer to the question why would explain what that problem is, and |
+knowing what that problem is will allow respondents to assess the |
+suitability of the approach at addressing the problem and possibly |
+suggest other, and superior, solutions. There is very little that is |
+genuinely new and unique, whatever the wider problem is the chances are |
+that someone will be familiar with it and be in a position to identify |
+the best solution (even if that is just confirming that the proposed |
+solution is the best available). Questions raised on the group should |
+always include the answer to the question: why? |
+</p> |
+ |
+<h3 id="ps1PR">Proof-Read your Questions</h3> |
+ |
+<p id="ps1PR_1"> |
+Proof-read your message two or three times before posting. Ensure that |
+it is as error free as possible and does convey the question and |
+provide all of the necessary information in a way that will not be |
+subject to misinterpretation. |
+</p> |
+ |
+<!-- <h2><a name="ps1notHD" id="ps1notHD">comp.lang.javascript is Not a Helpdesk</a></h2> |
+ |
+<p id="ps1notHD_1"> |
+The comp.lang.javascript newsgroup is a discussion forum on the subject |
+of ECMAScript (javascript). It is not a helpdesk and its participants |
+make their contributions voluntarily in their own time and with their |
+own resources for whatever reasons they see fit. Just because the |
+majority of the discussion starts with someone posting a question, |
+often asking for help with some aspect of javascript, does not mean |
+that anyone should have any expectation of receiving any help or |
+assistance from any ensuing discussion. So, although help and |
+assistance is often (if not usually) offered during the following |
+discussion, that is just a positive side effect of the group and not |
+its reason for existing. |
+</p> |
+ |
+<p id="ps1notHD_2"> |
+The real benefit of the group goes to its regular participants, who, |
+in participating in the discussion, attempting to address the diverse |
+situations and problems raised and exposing their code to critical |
+public scrutiny, get to hone their code authoring and script design |
+skills and knowledge with the active assistance and critical feed-back |
+of their peers. |
+</p> |
+ |
+<p id="ps1notHD_3"> |
+The whole process would not work as well if people did not post |
+questions relating to a diversity of problem situations to the group |
+in the hope of getting some assistance, and people would never do that |
+if there were not a good chance of actually getting assistance. But the |
+people posting such questions need to remember that they have no right |
+to assistance, and cannot demand, or even expect it. Instead, wanting |
+to take advantage of the potentially beneficial side effect of the |
+existence of the group, they should encourage the group to give them |
+assistance, by making doing so as easy and convenient as possible. The |
+preceding document is intended to make it as clear as possible how to |
+go about achieving that aim. |
+</p> --> |
+ |
+<h2 id="ps1AddR">Additional Reading</h2> |
+ |
+<ul class="resourceList" id="ps1AddR_l"> |
+ <li><a href="http://www.cs.tut.fi/~jkorpela/usenet/dont.html">The seven don'ts of Usenet<br>http://www.cs.tut.fi/~jkorpela/usenet/dont.html</a></li> |
+ <li><a href="http://oakroadsystems.com/genl/unice.htm">Playing Nice on Usenet<br>http://oakroadsystems.com/genl/unice.htm</a></li> |
+ <li><a href="http://www.netmeister.org/news/learn2quote2.html">How do I quote correctly in Usenet? - Quoting and Answering<br>http://www.netmeister.org/news/learn2quote2.html</a></li> |
+ <li><a href="http://www.xs4all.nl/%7ewijnands/nnq/nquote.html">Quoting Style in Newsgroup Postings<br>http://www.xs4all.nl/%7ewijnands/nnq/nquote.html </a></li> |
+ <li><a href="http://www.cs.tut.fi/~jkorpela/usenet/xpost.html">Why and how to crosspost<br>http://www.cs.tut.fi/~jkorpela/usenet/xpost.html</a></li> |
+ <li><a href="http://kb.indiana.edu/data/affn.html?cust=12244">How can I post a message to more than one Usenet newsgroup?<br>http://kb.indiana.edu/data/affn.html?cust=12244</a></li> |
+ <li><a href="http://catb.org/%7Eesr/faqs/smart-questions.html">How To Ask Questions The Smart Way<br>http://catb.org/%7Eesr/faqs/smart-questions.html</a></li> |
+ <li><a href="http://www.chiark.greenend.org.uk/~sgtatham/bugs.html">How to Report Bugs Effectively<br>http://www.chiark.greenend.org.uk/~sgtatham/bugs.html</a></li> |
+</ul> |
+</body> |
+</html> |
/cljs/notes/posting/index.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/notes/type-conversion/index.html |
=================================================================== |
--- cljs/notes/type-conversion/index.html (nonexistent) |
+++ cljs/notes/type-conversion/index.html (revision 2) |
@@ -0,0 +1,1319 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" |
+"http://www.w3.org/TR/html4/strict.dtd"> |
+<html lang="en"> |
+<head> |
+ <title>Javascript Type-Conversion</title> |
+ <meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> |
+<link href="../../faq.css" rel="stylesheet" type="text/css"> |
+<link href="../notes.css" rel="stylesheet" type="text/css"> |
+<style type="text/css"> |
+td { |
+ text-align:center; |
+} |
+pre.st { |
+ background-color:#EEEEFF; |
+ margin:0px; |
+ padding:0px; |
+ text-align:left; |
+ border:0px none #EEEEFF; |
+} |
+caption { |
+ font-weight:bold; |
+} |
+th, td { |
+ vertical-align:baseline; |
+ background-color:#EEEEFF; |
+ color:#000000; |
+ white-space:nowrap; |
+ padding:2px |
+} |
+.true { |
+ color:#003444; |
+ background-color:#E0FFE0; |
+} |
+.false { |
+ color:#003444; |
+ background-color:#FFE0E0; |
+} |
+table { |
+ margin:1em 2.5em; |
+} |
+ </style> |
+ </head> |
+ <body> |
+ |
+<h1>Javascript Type-Conversion</h1> |
+<div id="faqNav"> |
+ <a href="/faq/">FAQ</a> > <a href="/faq/notes/">FAQ Notes</a> |
+</div> |
+ |
+<ul> |
+ <li><a href="#tcInt">Introduction</a></li> |
+ <li><a href="#tcBool">Converting to Boolean</a></li> |
+ <li><a href="#tcString">Converting to String</a></li> |
+ <li><a href="#tcNumber">Converting to Number</a></li> |
+ <li><a href="#tcParse">Parsing to Number</a> |
+ <ul> |
+ <li><a href="#tcParseFl">parseFloat</a></li> |
+ <li><a href="#tcParseIn">parseInt</a></li> |
+ <li><a href="#tcPrIntRx">parseInt with a radix argument</a></li> |
+ </ul> |
+ </li> |
+ <li><a href="#tcToInt32">ToInt32</a></li> |
+ <li><a href="#tcUserIn">Converting User Input</a> |
+ <ul> |
+ <li><a href="#tcRegEx">Regular expression examples</a></li> |
+ </ul> |
+ </li> |
+</ul> |
+ |
+<h2 id="tcInt">Introduction</h2> |
+ |
+<p id="tcInt_1"> |
+Javascript (ECMAScript) is a loosely typed language. That does not mean |
+that it has no data types just that the value of a variable or a Javascript |
+object property does not need to have a particular type of value assigned |
+to it, or that it should always hold the same type of value. Javascript |
+also freely type-converts values into a type suitable for (or required by) |
+the context of their use. |
+</p> |
+ |
+<p id="tcInt_2"> |
+Javascript being loosely typed and willing to type-convert still does not |
+save the programmer from needing to think about the actual type of values |
+that they are dealing with. A very common error in browser scripting, for |
+example, is to read the value property of a form control into which the |
+user is expected to type a number and then add that value to another |
+number. Because the value properties of form controls are strings (even if |
+the character sequence they contain represents a number) the attempt to |
+add that string to a value, even if that value happens to be a number, |
+results in the second value being type-converted into a string and |
+concatenated to the end of the first string value from the from control. |
+</p> |
+ |
+<p id="tcInt_3"> |
+That problem arises from the dual nature of the <code>+</code> operator |
+used for both numeric addition and string concatenation. With which the |
+nature of the operation performed is determined by the context, where |
+only if both operands are numbers to start with will the <code>+</code> |
+operator perform addition. Otherwise it converts all of its operands to |
+strings and does concatenation. |
+</p> |
+ |
+<p id="tcInt_4"> |
+The following discussion is illustrated with Javascript generated tables |
+of values resulting from the conversion operations. The headers of those |
+tables display the values as represented in the Javascript source code |
+used rather than their internal representation. So, for example |
+<code>123e-2</code> as a number was the character sequence typed into |
+the source code, the interpreter reads that and generates the |
+number value 1.23 from it for internal use. The various values used for |
+the tests have been chosen to illustrate aspects of type |
+converting, those aspects may not apply to all of the tables presented. |
+However, all of the test values are included in all of the tables (except |
+where no type converting occurs) for full comparison. The bodies of the |
+tables list the results of the various type conversion operations. |
+</p> |
+ |
+<p id="tcInt_5"> |
+If you are accepting/using this page's <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> style suggestions the type |
+of the values at various stages is illustrated by the colour of the text |
+used. The following key shows those type/colour relationships, they are |
+derived from the string values returned by the <code>typeof</code> |
+operator (which returns <code>"object"</code> |
+for the <code>null</code> type when in reality <code>null</code> is |
+distinct from objects). |
+</p> |
+ |
+<table id="tcInt_key"> |
+ <tbody> |
+ <tr><th>Key</th></tr> |
+ <tr><td class="st">string</td></tr> |
+ <tr><td class="nm">number</td></tr> |
+ <tr><td class="bl">boolean</td></tr> |
+ <tr><td class="ob">object</td></tr> |
+ <tr><td class="fn" style="text-align:center;">function</td></tr> |
+ <tr><td class="ob">null</td></tr> |
+ <tr><td class="un">undefined</td></tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcInt_6"> |
+The boolean values of results also have a coloured background to highlight |
+ <code>true</code> or <code>false</code>. |
+</p> |
+ |
+<h2 id="tcBool">Converting to Boolean</h2> |
+ |
+<p id="tcBool_1"> |
+When evaluating the expression of an <code>if</code> statement the Javascript |
+interpreter will type-convert the result of that expression to boolean |
+in order to make its decision. Also various operators internally |
+type-convert their operands to boolean in order to determine what |
+action to take. These include the logical operators like AND |
+(<code>&&</code>), OR (<code>||</code>) and NOT (<code>!</code>). The NOT |
+operator type-converts its operand to boolean and if that value is |
+boolean true it returns false and if false it returns true. As the |
+result of a NOT operation is a boolean value that is the inverse of |
+the type-converted true-ness of its operand, two NOT operations |
+together will return a boolean value that is equivalent to the result |
+of type-converting the operand to boolean:- |
+</p> |
+ |
+<pre id="tcBool_ex1"> |
+var boolValue = !!x; |
+</pre> |
+ |
+<p id="tcBool_2"> |
+That technique has been used to generate the following tables. |
+</p> |
+ |
+<p id="tcBool_3"> |
+An alternative method of generating a boolean value that represents |
+the type-converted true-ness of a value is to pass that value to |
+the <code>Boolean</code> constructor called as a function:- |
+</p> |
+ |
+<pre id="tcBool_ex2"> |
+var boolValue = Boolean(x); |
+</pre> |
+ |
+<table> |
+ <caption>Double NOT (!!col) : Numeric Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="nm">-1.6</th> |
+ <th class="nm">-0</th> |
+ <th class="nm">+0</th> |
+ <th class="nm">1</th> |
+ <th class="nm">1.6</th> |
+ <th class="nm">8</th> |
+ <th class="nm">16</th> |
+ <th class="nm">16.8</th> |
+ <th class="nm">123e-2</th> |
+ <th class="nm">-Infinity</th> |
+ <th class="nm">+Infinity</th> |
+ <th class="nm">NaN</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>!!col</th> |
+ <td class="true">true</td> |
+ <td class="false">false</td> |
+ <td class="false">false</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="false">false</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcBool_4"> |
+When numbers are converted to boolean, zero becomes false and all other |
+numbers are true. With the excepting of the special numeric value |
+<code>NaN</code> (Not a Number) which is used when another type is |
+converted to a number but that conversion does not result in a |
+meaningful number. <code>NaN</code> is always false. The values of |
+positive and negative infinity, while not finite numbers, are non-zero |
+numeric values and always type-convert to boolean <code>true</code>. |
+</p> |
+ |
+<table> |
+ <caption>Double NOT (!!col) : String Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="st">""<br>(empty<br>string)</th> |
+ <th class="st">"-1.6"</th> |
+ <th class="st">"0"</th> |
+ <th class="st">"1"</th> |
+ <th class="st">"1.6"</th> |
+ <th class="st">"8"</th> |
+ <th class="st">"16"</th> |
+ <th class="st">"16.8"</th> |
+ <th class="st">"123e-2"</th> |
+ <th class="st">"010"<br>(Octal)</th> |
+ <th class="st">"0x10"<br>(Hex)</th> |
+ <th class="st">"0xFF"<br>(Hex)</th> |
+ <th class="st">"-010"</th> |
+ <th class="st">"-0x10"</th> |
+ <th class="st">"xx"</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>!!col</th> |
+ <td class="false">false</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcBool_5"> |
+Type conversion rules are even simpler for string to boolean conversion |
+as all non-empty strings always become true and empty strings become |
+false. |
+</p> |
+ |
+<table> |
+ <caption>Double NOT (!!col) : Other Values</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="un">undefined</th> |
+ <th class="ob">null</th> |
+ <th class="bl">true</th> |
+ <th class="bl">false</th> |
+ <th class="ob">new Object()</th> |
+ <th class="fn">function(){<br> return;<br>}</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>!!col</th> |
+ <td class="false">false</td> |
+ <td class="false">false</td> |
+ <td class="true">true</td> |
+ <td class="false">false</td> |
+ <td class="true">true</td> |
+ <td class="true">true</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcBool_6"> |
+For the other types, <code>undefined</code> and <code>null</code> are |
+converted to false, boolean values are not converted and objects and |
+functions are always true. |
+</p> |
+ |
+<p id="tcBool_7"> |
+This is the most valuable aspect of type-converting to boolean as it |
+allows a script to distinguish between properties in an environment |
+that may be undefined or may refer to an object. Treating an undefined |
+(or null) value as if it was an object will produce errors. So when |
+there is a doubt (as there usually is where web browsers are concerned) |
+then code can avoid generating errors by wrapping the code that wants |
+to access an object in an <code>if</code> test. Supplying the suspect |
+reference to the object as the expression. The expression will be type |
+converted to boolean and result in <code>false</code> if the object |
+does not exist and <code>true</code> if it does. |
+</p> |
+ |
+<pre id="tcBool_ex3"> |
+if(document.documentElement){ |
+ scrollX = document.documentElement.scrollLeft; |
+} |
+</pre> |
+ |
+<p id="tcBool_8"> |
+The double NOT operation also allows the setting of boolean flags that |
+can be used to indicate the presence of various objects:- |
+</p> |
+ |
+<pre id="tcBool_ex4"> |
+var hasDocEl = !!document.documentElement; |
+... |
+if(hasDocEl){ |
+ scrollX = document.documentElement.scrollLeft; |
+} |
+</pre> |
+ |
+<h2 id="tcString">Converting to String</h2> |
+ |
+<p id="tcString_1"> |
+As mentioned above, type conversion to a string most often results |
+from the action of the + operator whenever one of its operators in |
+not a number. The easiest way of getting the string that results |
+from type-conversion is to concatenate a value to an empty string. |
+That technique has been used to generate the following tables. |
+</p> |
+ |
+<p id="tcString_2"> |
+An alternative method of converting a value into a string is to |
+pass it as an argument to the <code>String</code> constructor |
+called as a function:- |
+</p> |
+ |
+<pre id="tcString_ex1"> |
+var stringValue = String(x); |
+</pre> |
+ |
+<table> |
+ <caption>type-convert to string ("" + col) : Numeric Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="nm">-1.6</th> |
+ <th class="nm">-0</th> |
+ <th class="nm">+0</th> |
+ <th class="nm">1</th> |
+ <th class="nm">1.6</th> |
+ <th class="nm">8</th> |
+ <th class="nm">16</th> |
+ <th class="nm">16.8</th> |
+ <th class="nm">123e-2</th> |
+ <th class="nm">-Infinity</th> |
+ <th class="nm">+Infinity</th> |
+ <th class="nm">NaN</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>"" + col</th> |
+ <td class="st">-1.6</td> |
+ <td class="st">0</td> |
+ <td class="st">0</td> |
+ <td class="st">1</td> |
+ <td class="st">1.6</td> |
+ <td class="st">8</td> |
+ <td class="st">16</td> |
+ <td class="st">16.8</td> |
+ <td class="st">1.23</td> |
+ <td class="st">-Infinity</td> |
+ <td class="st">Infinity</td> |
+ <td class="st">NaN</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcString_3"> |
+Notice that the number generated from the source code <code>123e-2</code> |
+has resulted in the string <code>"1.23"</code> because that is |
+the string representation of the internal number created from the source |
+code. However, Javascript's internal number representations take the form |
+of IEEE double precision floating point numbers and that means that they |
+cannot represent all numbers with precision. The results of mathematical |
+operations may only produce close approximations and when they are |
+converted to strings the string represents the approximation and may be |
+unexpected and undesirable. It is often necessary to use custom functions |
+to generate string representations of numbers in an acceptable format, |
+the type-conversion mechanism is rarely suited to generating numeric output |
+intended for presentation. |
+</p> |
+ |
+<table> |
+ <caption>type-convert to string ("" + col) : Other Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="un">undefined</th> |
+ <th class="ob">null</th> |
+ <th class="bl">true</th> |
+ <th class="bl">false</th> |
+ <th class="ob">new Object()</th> |
+ <th class="fn">function(){<br> return;<br>}</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>"" + col</th> |
+ <td class="st">undefined</td> |
+ <td class="st">null</td> |
+ <td class="st">true</td> |
+ <td class="st">false</td> |
+ <td class="st">[object Object]</td> |
+ <td><pre class="st">function(){ |
+ return; |
+}</pre></td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcString_4"> |
+When objects or functions are type-converted to strings their |
+<code>toString</code> method is called. These default to |
+<code>Object.prototype.toString</code> and |
+<code>Function.prototype.toString</code> but may be overloaded |
+with a function assigned to a "toString" property of |
+the object/function. Type-converting a function to a string does |
+not necessarily result in the function's source code. The behaviour |
+of <code>Function.prototype.toString</code> is implementation |
+depended and varies quite a lot, as do the results from |
+"host objects" and methods (the objects and methods |
+provided by the environment, such as DOM elements). |
+</p> |
+ |
+<h2 id="tcNumber">Converting to Number</h2> |
+ |
+<p id="tcNumber_1"> |
+Converting values to numbers, especially strings to numbers, is an |
+extremely common requirement and many methods can be used. Any |
+mathematical operator except the concatenation/addition operator |
+will force type-conversion. So conversion of a string to a number |
+might entail performing a mathematical operation on the string |
+representation of the number that would not affect the resulting |
+number, such as subtracting zero or multiplying by one. |
+</p> |
+ |
+<pre id="tcNumber_ex1"> |
+var numValue = stringValue - 0; |
+<span class="commentJS">/* or */</span> |
+var numValue = stringValue * 1; |
+<span class="commentJS">/* or */</span> |
+var numValue = stringValue / 1; |
+</pre> |
+ |
+<p id="tcNumber_2"> |
+However, the unary <code>+</code> operator also type-converts its |
+operand to a number and because it does not do any additional |
+mathematical operations it is the fastest method for type-converting |
+a string into a number. |
+</p> |
+ |
+<p id="tcNumber_2b"> |
+Incidentally, the unary <code>-</code> (minus) operator also |
+type-converts its operand (if necessary) in addition to |
+subsequently negating its value. |
+</p> |
+ |
+<pre id="tcNumber_ex2"> |
+var numValue = (+stringValue); |
+ |
+<span class="commentJS">/* The preceding unary + expression has been parenthesised. That is |
+ unnecessary but is often felt to make the code easier to comprehend |
+ and make it clear which operations are being applied. Especially |
+ avoiding confusion with pre and post increment and addition |
+ operations. Compare:- |
+ |
+var n = anyNumVar++ + +stringVar + ++anotherNumVar; |
+ |
+ - with - |
+ |
+var n = (anyNumVar++) + (+stringVar) + (++anotherNumVar); |
+ ^^ ^ ^^ |
+ (post increment) + (unary plus) + (pre increment) |
+*/</span> |
+</pre> |
+ |
+<p id="tcNumber_3"> |
+While unary <code>+</code> is the fastest method for converting a |
+string to a number a final method is available that uses the |
+Javascript type-conversion algorithms. The <code>Number</code> |
+constructor can be called with the string value as its argument |
+and its return value is a number representing the result of the |
+type-conversion. |
+</p> |
+ |
+<pre id="tcNumber_ex3"> |
+var numValue = Number(stringValue); |
+</pre> |
+ |
+<p id="tcNumber_4"> |
+The Number constructor is the slowest of the type-converting |
+methods but when speed is not an overriding consideration its |
+use does produce the clearest source code. |
+</p> |
+ |
+<p id="tcNumber_5"> |
+The following tables show the results of type-conversion to a number using |
+the unary <code>+</code> operator. Though all of the preceding |
+alternative method produce the same results as they all use exactly the |
+same algorithm to do the conversion. |
+</p> |
+ |
+<table> |
+ <caption>type-convert to number (+col) : String Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="st">""<br>(empty<br>string)</th> |
+ <th class="st">"-1.6"</th> |
+ <th class="st">"0"</th> |
+ <th class="st">"1"</th> |
+ <th class="st">"1.6"</th> |
+ <th class="st">"8"</th> |
+ <th class="st">"16"</th> |
+ <th class="st">"16.8"</th> |
+ <th class="st">"123e-2"</th> |
+ <th class="st">"010"<br>(Octal)</th> |
+ <th class="st">"0x10"<br>(Hex)</th> |
+ <th class="st">"0xFF"<br>(Hex)</th> |
+ <th class="st">"-010"</th> |
+ <th class="st">"-0x10"</th> |
+ <th class="st">"xx"</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>+col</th> |
+ <td class="nm">0</td> |
+ <td class="nm">-1.6</td> |
+ <td class="nm">0</td> |
+ <td class="nm">1</td> |
+ <td class="nm">1.6</td> |
+ <td class="nm">8</td> |
+ <td class="nm">16</td> |
+ <td class="nm">16.8</td> |
+ <td class="nm">1.23</td> |
+ <td class="nm">10</td> |
+ <td class="nm">16</td> |
+ <td class="nm">255</td> |
+ <td class="nm">-10</td> |
+ <td class="nm">NaN</td> |
+ <td class="nm">NaN</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcNumber_6"> |
+The important considerations when converting strings to numbers with |
+the type-converting methods is the results from strings that do not |
+represent numbers. The empty string is converted into the number zero, |
+depending on the application this can be harmless or disastrous, but |
+it is important to be aware that it is going to happen. In other |
+contexts strings that follow the Javascript format for octal number |
+(leading zero) can be problematic but type conversion treats them |
+as base 10 anyway. However, strings that follow the format for |
+hexadecimal numbers (leading <code>0x</code> or <code>0X</code>) |
+are read as hexadecimal. Strings that cannot be read as a number |
+type-convert to <code>NaN</code>, which can be tested for with |
+the <code>isNaN</code> function. Strings representing numbers in an |
+exponential format (<code>"123e-2"</code>) are understood |
+along with leading minus signs. |
+</p> |
+ |
+<table> |
+ <caption>type-convert to number (+col) : Other Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="un">undefined</th> |
+ <th class="ob">null</th> |
+ <th class="bl">true</th> |
+ <th class="bl">false</th> |
+ <th class="ob">new Object()</th> |
+ <th class="fn">function(){<br> return;<br>}</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>+col</th> |
+ <td class="nm">NaN</td> |
+ <td class="nm">0</td> |
+ <td class="nm">1</td> |
+ <td class="nm">0</td> |
+ <td class="nm">NaN</td> |
+ <td class="nm">NaN</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcNumber_7"> |
+Objects and functions always type-convert to <code>NaN</code> numbers, as do |
+<code>undefined</code> values but it is worth noting that <code>null</code> |
+type-converts to zero. Probably because it is being type-converted to boolean |
+first and then to number and, as is clear from the boolean results |
+above, <code>null</code> would become boolean <code>false</code> which |
+would then become numeric zero. There is almost no need to type convert |
+these types of values into numbers. How they convert is only really |
+relevant to a consideration of the accidental result of converting a |
+value that is expected to be a string but actually turns out to be one |
+of these (and/or performing an mathematical operation with one of these as an operand). |
+</p> |
+ |
+<h2 id="tcParse">Parsing to Number</h2> |
+ |
+<p id="tcParse_1"> |
+An alternative method of converting a string into a number is to use |
+one of the global functions designed to parse a string and return a |
+number. The <code>parseFloat</code> function accepts a string argument |
+and returns a floating point number resulting from parsing that string. |
+Non-string arguments are first type-converted to a string as described |
+above. |
+</p> |
+ |
+<p id="tcParse_2"> |
+The string parsing functions read the string character by character until |
+they encounter a character that cannot be part of the number, at which |
+point they stop and return a number based on the characters that they |
+have seen that can be part of the number. This feature of their action |
+can be usefully exploited, for example, given a string representing a |
+<span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> length value such as <code>"34.5em"</code> |
+<code>parseFloat</code> would be able to ignore the <code>"em"</code> |
+because those characters cannot be combined with the preceding set to |
+produce a valid number. The returned number would be 34.5, the numeric |
+part of the <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> string stripped of its units. |
+</p> |
+ |
+<h3 id="tcParseFl">parseFloat</h3> |
+ |
+<table> |
+ <caption>parseFloat(col) : String Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="st">""<br>(empty<br>string)</th> |
+ <th class="st">"-1.6"</th> |
+ <th class="st">"0"</th> |
+ <th class="st">"1"</th> |
+ <th class="st">"1.6"</th> |
+ <th class="st">"8"</th> |
+ <th class="st">"16"</th> |
+ <th class="st">"16.8"</th> |
+ <th class="st">"123e-2"</th> |
+ <th class="st">"010"<br>(Octal)</th> |
+ <th class="st">"0x10"<br>(Hex)</th> |
+ <th class="st">"0xFF"<br>(Hex)</th> |
+ <th class="st">"-010"</th> |
+ <th class="st">"-0x10"</th> |
+ <th class="st">"xx"</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>parseFloat(col)</th> |
+ <td class="nm">NaN</td> |
+ <td class="nm">-1.6</td> |
+ <td class="nm">0</td> |
+ <td class="nm">1</td> |
+ <td class="nm">1.6</td> |
+ <td class="nm">8</td> |
+ <td class="nm">16</td> |
+ <td class="nm">16.8</td> |
+ <td class="nm">1.23</td> |
+ <td class="nm">10</td> |
+ <td class="nm">0</td> |
+ <td class="nm">0</td> |
+ <td class="nm">-10</td> |
+ <td class="nm">0</td> |
+ <td class="nm">NaN</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcParseFl_1"> |
+With <code>parseFloat</code> empty strings return <code>NaN </code> |
+along with strings that cannot be subject to numeric interpretation. |
+The exponential format is understood and the leading zero in the |
+octal format does not hinder the string's interpretation as a |
+decimal number. Hexadecimal strings are interpreted as the number |
+zero because the following <code>"x"</code> cannot be |
+interpreted as part of a number so parsing stops after the leading zero. |
+</p> |
+ |
+<table> |
+ <caption>parseFloat(col) : Other Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="un">undefined</th> |
+ <th class="ob">null</th> |
+ <th class="bl">true</th> |
+ <th class="bl">false</th> |
+ <th class="ob">new Object()</th> |
+ <th class="fn">function(){<br> return;<br>}</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>parseFloat(col)</th> |
+ <td class="nm">NaN</td> |
+ <td class="nm">NaN</td> |
+ <td class="nm">NaN</td> |
+ <td class="nm">NaN</td> |
+ <td class="nm">NaN</td> |
+ <td class="nm">NaN</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcParseFl_2"> |
+Non-string values are first converted into a string that is employed |
+by <code>parseFloat</code>. As that type-conversion to a string would |
+not normally result in a string that could be interpreted as a number |
+the result is <code>NaN</code>. Objects and functions may have custom |
+<code>toString</code> methods that may return strings that could be |
+interpreted as numbers but that would be an unusual requirement. |
+</p> |
+ |
+<h3 id="tcParseIn">parseInt</h3> |
+ |
+<p id="tcParseIn_1"> |
+The <code>parseInt</code> function works in a similar way to |
+<code>parseFloat</code> except that it is trying to interpret its |
+string argument into an integer and as a result recognises fewer |
+character as possible candidates to be part of that number. |
+</p> |
+ |
+<p id="tcParseIn_2"> |
+<code>parseInt</code> is occasionally used as a means of turning a |
+floating point number into an integer. It is very ill suited to that |
+task because if its argument is of numeric type it will first be |
+converted into a string and then parsed as a number, very inefficient. |
+This can produce very wrong results with numbers such as |
+<code>2e-200</code>, for which the next smaller integer is zero, but |
+with which <code>parseInt</code> returns <code>2</code>. Also, because |
+of the number format used by javascript, numbers are often represented |
+by near approximations. So, for example, 1/2 + 1/3 + 1/6 = |
+0.9999999999999999, which isn't quite one and parseInt would return |
+zero if asked to act on the result of the operation. |
+</p> |
+ |
+<p id="tcParseIn_3"> |
+For rounding |
+numbers to integers one of <code>Math.round</code>, <code>Math.ceil</code> |
+and <code>Math.floor</code> are preferable, and for a desired result |
+that can be expressed as a 32 bit signed integer the bitwise operation |
+described below might also suit. |
+</p> |
+ |
+<table> |
+ <caption>parseInt(col) : Numeric Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="nm">-1.6</th> |
+ <th class="nm">-0</th> |
+ <th class="nm">+0</th> |
+ <th class="nm">1</th> |
+ <th class="nm">1.6</th> |
+ <th class="nm">8</th> |
+ <th class="nm">16</th> |
+ <th class="nm">16.8</th> |
+ <th class="nm">123e-2</th> |
+ <th class="nm">-Infinity</th> |
+ <th class="nm">+Infinity</th> |
+ <th class="nm">NaN</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>parseInt(col)</th> |
+ <td class="nm">-1</td> |
+ <td class="nm">0</td> |
+ <td class="nm">0</td> |
+ <td class="nm">1</td> |
+ <td class="nm">1</td> |
+ <td class="nm">8</td> |
+ <td class="nm">16</td> |
+ <td class="nm">16</td> |
+ <td class="nm">1</td> |
+ <td class="nm">NaN</td> |
+ <td class="nm">NaN</td> |
+ <td class="nm">NaN</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcParseIn_4"> |
+When it is acting on number the effect of the initial type-conversion |
+of the argument to a string is evident in the results. Note that the |
+value <code>123e-2</code> is internally the number <code>1.23</code> |
+and that type converts into the string <code>"1.23"</code>, |
+so that entry in the table above might look odd but it is correct. |
+</p> |
+ |
+<table> |
+ <caption>parseInt(col) : String Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="st">""<br>(empty<br>string)</th> |
+ <th class="st">"-1.6"</th> |
+ <th class="st">"0"</th> |
+ <th class="st">"1"</th> |
+ <th class="st">"1.6"</th> |
+ <th class="st">"8"</th> |
+ <th class="st">"16"</th> |
+ <th class="st">"16.8"</th> |
+ <th class="st">"123e-2"</th> |
+ <th class="st">"010"<br>(Octal)</th> |
+ <th class="st">"0x10"<br>(Hex)</th> |
+ <th class="st">"0xFF"<br>(Hex)</th> |
+ <th class="st">"-010"</th> |
+ <th class="st">"-0x10"</th> |
+ <th class="st">"xx"</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>parseInt(col)</th> |
+ <td class="nm">NaN</td> |
+ <td class="nm">-1</td> |
+ <td class="nm">0</td> |
+ <td class="nm">1</td> |
+ <td class="nm">1</td> |
+ <td class="nm">8</td> |
+ <td class="nm">16</td> |
+ <td class="nm">16</td> |
+ <td class="nm">123</td> |
+ <td class="nm">8</td> |
+ <td class="nm">16</td> |
+ <td class="nm">255</td> |
+ <td class="nm">-8</td> |
+ <td class="nm">-16</td> |
+ <td class="nm">NaN</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcParseIn_5"> |
+Strings in octal and hexadecimal number formats do represent integers |
+and <code>parseInt</code> is capable of interpreting them in accordance |
+with the rules for Javascript source code, even when they have leading |
+minus signs. |
+</p> |
+ |
+<table> |
+ <caption>parseInt(col) : Other Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="un">undefined</th> |
+ <th class="ob">null</th> |
+ <th class="bl">true</th> |
+ <th class="bl">false</th> |
+ <th class="ob">new Object()</th> |
+ <th class="fn">function(){<br> return;<br>}</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>parseInt(col)</th> |
+ <td class="nm">NaN</td> |
+ <td class="nm">NaN</td> |
+ <td class="nm">NaN</td> |
+ <td class="nm">NaN</td> |
+ <td class="nm">NaN</td> |
+ <td class="nm">NaN</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcParseIn_6"> |
+As <code>parseInt</code> type-converts its non-string arguments to |
+strings it always produces the same results for <code>boolean</code>, |
+<code>null</code>, <code>undefined</code>, object and function |
+arguments as <code>parseFloat</code> (assuming objects and functions |
+do not have custom <code>toString</code> methods). |
+</p> |
+ |
+<h3 id="tcPrIntRx">parseInt with a radix argument</h3> |
+ |
+<p id="tcPrIntRx_1"> |
+It is rarely desirable to allow <code>parseInt</code> to deduce the |
+base in which the number is represented from the string as leading zeros are |
+rarely intended to indicate data in octal format (particularly with |
+user input). To deal with this problem <code>parseInt</code> recognises |
+a second, radix, argument that can be used to specify the base in which the |
+string is to be interpreted. Specifying a second argument of 10 causes |
+<code>parseInt</code> to interpret the strings as only base 10. |
+</p> |
+ |
+<table> |
+ <caption>parseInt(col, 10) : String Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="st">""<br>(empty<br>string)</th> |
+ <th class="st">"-1.6"</th> |
+ <th class="st">"0"</th> |
+ <th class="st">"1"</th> |
+ <th class="st">"1.6"</th> |
+ <th class="st">"8"</th> |
+ <th class="st">"16"</th> |
+ <th class="st">"16.8"</th> |
+ <th class="st">"123e-2"</th> |
+ <th class="st">"010"<br>(Octal)</th> |
+ <th class="st">"0x10"<br>(Hex)</th> |
+ <th class="st">"0xFF"<br>(Hex)</th> |
+ <th class="st">"-010"</th> |
+ <th class="st">"-0x10"</th> |
+ <th class="st">"xx"</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>parseInt(col, 10)</th> |
+ <td class="nm">NaN</td> |
+ <td class="nm">-1</td> |
+ <td class="nm">0</td> |
+ <td class="nm">1</td> |
+ <td class="nm">1</td> |
+ <td class="nm">8</td> |
+ <td class="nm">16</td> |
+ <td class="nm">16</td> |
+ <td class="nm">123</td> |
+ <td class="nm">10</td> |
+ <td class="nm">0</td> |
+ <td class="nm">0</td> |
+ <td class="nm">-10</td> |
+ <td class="nm">0</td> |
+ <td class="nm">NaN</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcPrIntRx_2"> |
+The string in octal format is now interpreted as base 10 and the |
+hexadecimal strings can now only be zero as parsing has to stop |
+when the <code>"x"</code> is encountered. |
+</p> |
+ |
+<p id="tcPrIntRx_3"> |
+Number bases 2 to 36 can be used with <code>parseInt</code>. The |
+following is base 16. |
+</p> |
+ |
+<table> |
+ <caption>parseInt(col, 16) : String Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="st">""<br>(empty<br>string)</th> |
+ <th class="st">"-1.6"</th> |
+ <th class="st">"0"</th> |
+ <th class="st">"1"</th> |
+ <th class="st">"1.6"</th> |
+ <th class="st">"8"</th> |
+ <th class="st">"16"</th> |
+ <th class="st">"16.8"</th> |
+ <th class="st">"123e-2"</th> |
+ <th class="st">"010"<br>(Octal)</th> |
+ <th class="st">"0x10"<br>(Hex)</th> |
+ <th class="st">"0xFF"<br>(Hex)</th> |
+ <th class="st">"-010"</th> |
+ <th class="st">"-0x10"</th> |
+ <th class="st">"xx"</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>parseInt(col, 16)</th> |
+ <td class="nm">NaN</td> |
+ <td class="nm">-1</td> |
+ <td class="nm">0</td> |
+ <td class="nm">1</td> |
+ <td class="nm">1</td> |
+ <td class="nm">8</td> |
+ <td class="nm">22</td> |
+ <td class="nm">22</td> |
+ <td class="nm">4670</td> |
+ <td class="nm">16</td> |
+ <td class="nm">16</td> |
+ <td class="nm">255</td> |
+ <td class="nm">-16</td> |
+ <td class="nm">-16</td> |
+ <td class="nm">NaN</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcPrIntRx_4"> |
+The hexadecimal <code>0x</code> format is recognised again with the |
+base 16 interpretation. |
+</p> |
+ |
+<p id="tcPrIntRx_5"> |
+Finally base 3:- |
+</p> |
+ |
+<table> |
+ <caption>parseInt(col, 3) : Numeric Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="nm">-1.6</th> |
+ <th class="nm">-0</th> |
+ <th class="nm">+0</th> |
+ <th class="nm">1</th> |
+ <th class="nm">1.6</th> |
+ <th class="nm">8</th> |
+ <th class="nm">16</th> |
+ <th class="nm">16.8</th> |
+ <th class="nm">123e-2</th> |
+ <th class="nm">-Infinity</th> |
+ <th class="nm">+Infinity</th> |
+ <th class="nm">NaN</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>parseInt(col, 3)</th> |
+ <td class="nm">-1</td> |
+ <td class="nm">0</td> |
+ <td class="nm">0</td> |
+ <td class="nm">1</td> |
+ <td class="nm">1</td> |
+ <td class="nm">NaN</td> |
+ <td class="nm">1</td> |
+ <td class="nm">1</td> |
+ <td class="nm">1</td> |
+ <td class="nm">NaN</td> |
+ <td class="nm">NaN</td> |
+ <td class="nm">NaN</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcPrIntRx_6"> |
+The consequences of the type-converting of numeric arguments to |
+strings is evident again. The number <code>8</code> is coming out |
+as <code>NaN</code> because the <code>"8"</code> character |
+cannot be interpreted as base 3, leaving an empty sequence of |
+acceptable characters and producing the same result as an empty string. |
+</p> |
+ |
+<table> |
+ <caption>parseInt(col, 3) : String Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="st">""<br>(empty<br>string)</th> |
+ <th class="st">"-1.6"</th> |
+ <th class="st">"0"</th> |
+ <th class="st">"1"</th> |
+ <th class="st">"1.6"</th> |
+ <th class="st">"8"</th> |
+ <th class="st">"16"</th> |
+ <th class="st">"16.8"</th> |
+ <th class="st">"123e-2"</th> |
+ <th class="st">"010"<br>(Octal)</th> |
+ <th class="st">"0x10"<br>(Hex)</th> |
+ <th class="st">"0xFF"<br>(Hex)</th> |
+ <th class="st">"-010"</th> |
+ <th class="st">"-0x10"</th> |
+ <th class="st">"xx"</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>parseInt(col, 3)</th> |
+ <td class="nm">NaN</td> |
+ <td class="nm">-1</td> |
+ <td class="nm">0</td> |
+ <td class="nm">1</td> |
+ <td class="nm">1</td> |
+ <td class="nm">NaN</td> |
+ <td class="nm">1</td> |
+ <td class="nm">1</td> |
+ <td class="nm">5</td> |
+ <td class="nm">3</td> |
+ <td class="nm">0</td> |
+ <td class="nm">0</td> |
+ <td class="nm">-3</td> |
+ <td class="nm">0</td> |
+ <td class="nm">NaN</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<h2 id="tcToInt32">ToInt32</h2> |
+ |
+<p id="tcToInt32_1"> |
+<code>ToInt32</code> is an <em>internal</em> function only available to the |
+Javascript implementation and cannot be called directly from scripts |
+in the way that <code>parseInt</code> can. It is a bit unusual to mention it in |
+connection with converting Javascript values to numbers but it can |
+be used in a limited set of circumstances. The bitwise operators such |
+as bitwise OR (<code>|</code>) and bitwise AND (<code>&</code>) operate on |
+numbers so they type-convert their operands to numbers. However, they |
+also only operate on 32 bit signed integers so given the (possibly |
+type-converted) numeric value they call the <em>internal</em> |
+<code>ToInt32</code> function with that number as its argument and |
+use the returned value as their operand. That returned value is always |
+a 32 bit signed integer. |
+</p> |
+ |
+<p id="tcToInt32_2"> |
+The effect can be like <code>parseInt</code> combined with type-converting |
+to numbers. While the result is limited in range to 32 bits, it is |
+<em>always</em> numeric and never <code>NaN</code>, or ± |
+<code>Infinity</code>. |
+</p> |
+ |
+<p id="tcToInt32_3"> |
+As with using mathematical operators in operations that have no effect on |
+the value of any resulting number it is possible to perform a bitwise |
+operation that will not affect the value returned from the call to |
+<code>ToInt32</code>. The tables below were generated using a bitwise |
+OR zero operation. |
+</p> |
+ |
+<table> |
+ <caption> ToInt32 (col|0) : Numeric Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="nm">-1.6</th> |
+ <th class="nm">-0</th> |
+ <th class="nm">+0</th> |
+ <th class="nm">1</th> |
+ <th class="nm">1.6</th> |
+ <th class="nm">8</th> |
+ <th class="nm">16</th> |
+ <th class="nm">16.8</th> |
+ <th class="nm">123e-2</th> |
+ <th class="nm">-Infinity</th> |
+ <th class="nm">+Infinity</th> |
+ <th class="nm">NaN</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>col|0</th> |
+ <td class="nm">-1</td> |
+ <td class="nm">0</td> |
+ <td class="nm">0</td> |
+ <td class="nm">1</td> |
+ <td class="nm">1</td> |
+ <td class="nm">8</td> |
+ <td class="nm">16</td> |
+ <td class="nm">16</td> |
+ <td class="nm">1</td> |
+ <td class="nm">0</td> |
+ <td class="nm">0</td> |
+ <td class="nm">0</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcToInt32_4"> |
+<code>NaN</code> and ±<code>Infinity</code> become zero and |
+floating point values are <em>truncated</em> to integers. |
+</p> |
+ |
+<table> |
+ <caption> ToInt32 (col|0) : String Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="st">""<br>(empty<br>string)</th> |
+ <th class="st">"-1.6"</th> |
+ <th class="st">"0"</th> |
+ <th class="st">"1"</th> |
+ <th class="st">"1.6"</th> |
+ <th class="st">"8"</th> |
+ <th class="st">"16"</th> |
+ <th class="st">"16.8"</th> |
+ <th class="st">"123e-2"</th> |
+ <th class="st">"010"<br>(Octal)</th> |
+ <th class="st">"0x10"<br>(Hex)</th> |
+ <th class="st">"0xFF"<br>(Hex)</th> |
+ <th class="st">"-010"</th> |
+ <th class="st">"-0x10"</th> |
+ <th class="st">"xx"</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>col|0</th> |
+ <td class="nm">0</td> |
+ <td class="nm">-1</td> |
+ <td class="nm">0</td> |
+ <td class="nm">1</td> |
+ <td class="nm">1</td> |
+ <td class="nm">8</td> |
+ <td class="nm">16</td> |
+ <td class="nm">16</td> |
+ <td class="nm">1</td> |
+ <td class="nm">10</td> |
+ <td class="nm">16</td> |
+ <td class="nm">255</td> |
+ <td class="nm">-10</td> |
+ <td class="nm">0</td> |
+ <td class="nm">0</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcToInt32_5"> |
+String values that would type-convert to <code>NaN</code> are returned |
+as zero from <code>ToInt32</code>. |
+</p> |
+ |
+<table> |
+ <caption> ToInt32 (col|0) : Other Values.</caption> |
+ <thead> |
+ <tr> |
+ <th></th> |
+ <th class="un">undefined</th> |
+ <th class="ob">null</th> |
+ <th class="bl">true</th> |
+ <th class="bl">false</th> |
+ <th class="ob">new Object()</th> |
+ <th class="fn">function(){<br> return;<br>}</th> |
+ </tr> |
+ </thead> |
+ <tbody> |
+ <tr> |
+ <th>col|0</th> |
+ <td class="nm">0</td> |
+ <td class="nm">0</td> |
+ <td class="nm">1</td> |
+ <td class="nm">0</td> |
+ <td class="nm">0</td> |
+ <td class="nm">0</td> |
+ </tr> |
+ </tbody> |
+</table> |
+ |
+<p id="tcToInt32_6"> |
+Even <code>undefined</code>, objects and functions are converted to zero value |
+numbers by this operation. Note though that boolean <code>true</code> is |
+converted to the number 1. |
+</p> |
+ |
+ |
+<h2 id="tcUserIn">Converting User Input</h2> |
+ |
+<p id="tcUserIn_1"> |
+Most of the mechanisms for getting input from the user, |
+<code><input type="text"></code> and |
+<code>prompt</code> for example, provide their results in the form |
+of strings. If the user is expected to input a number they still |
+might enter anything (at the least they may just make a typo). If |
+the string needs to be converted into a number for later operations |
+one of the methods mentioned above can be chosen based on what best |
+suits the nature of the input expected but some of the results |
+generated with erroneous input may be difficult to detect and handle. |
+</p> |
+ |
+<p id="tcUserIn_2"> |
+Prior to converting a string to a number it may be advantageous |
+to use a Regular Expression to test the contents of the string |
+to ensure that they conform to an acceptable format. That would |
+serve to eliminate some of the string values that may otherwise |
+suffer from the quirks of the string to number converting |
+processes when applied to unexpected string values. |
+</p> |
+ |
+ |
+<h3 id="tcRegEx">Regular expression examples</h3> |
+ |
+<pre id="tcRegExEm"> |
+/^\d+$/ <span class="commentJS">//All-digit</span> |
+/^\s*[-+]?\d+\s*$/ <span class="commentJS">//Unbroken Signed integer & spaces</span> |
+/^\d{1,5}$/ <span class="commentJS">//1 to 5 digits</span> |
+/^\d+\.\d\d$/ <span class="commentJS">//Money</span> |
+/^\d+(\.\d{2})$/ <span class="commentJS">//Money</span> |
+/^\d{1,3}(,\d\d\d)*\.\d\d$/ <span class="commentJS">//comma-separated money - 12,432.57</span> |
+ |
+ <span class="commentJS">// optional comma-separated money - 12,432.57 or 12432.57</span> |
+/^\d{1,3}(,\d\d\d)*\.\d\d$|^\d+\.\d\d$/ |
+ |
+</pre> |
+</body> |
+</html> |
/cljs/notes/type-conversion/index.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/notes/detect-browser/index.html |
=================================================================== |
--- cljs/notes/detect-browser/index.html (nonexistent) |
+++ cljs/notes/detect-browser/index.html (revision 2) |
@@ -0,0 +1,1413 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" |
+ "http://www.w3.org/TR/html4/strict.dtd"> |
+<html lang="en"> |
+<head> |
+<title>Browser Detection (and What to Do Instead)</title> |
+<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> |
+<link href="../../faq.css" rel="stylesheet" type="text/css"> |
+<link href="../notes.css" rel="stylesheet" type="text/css"> |
+<style type="text/css"> |
+.tip { |
+ border: 1px solid #ccc; |
+ padding: 1ex; |
+ background: #fcfcfc; |
+ font-size: 90%; |
+} |
+</style> |
+</head> |
+<body> |
+<h1 id="bdTop">Browser Detection (and What to Do Instead)</h1> |
+<div id="faqNav"> |
+ <a href="../../">FAQ</a> > <a href="../">FAQ Notes</a> |
+</div> |
+<p> |
+By Richard Cornford, edited by Garrett Smith |
+</p> |
+<ul> |
+ <li><a href="#bdIntro">Introduction</a></li> |
+ <li><a href="#bdValid">Avoiding Structural Differences in the Browser DOMs</a></li> |
+ <li><a href="#bdDif">Browsers Differences</a></li> |
+ <li><a href="#bdFailS">Failed Strategies: Browser Detecting</a> |
+ <ul> |
+ <li><a href="#bdUAS">Assumptions Based on navigator.userAgent</a></li> |
+ <li><a href="#bdOI">Assumptions Based on DOM Objects: Object inference</a></li> |
+ </ul> |
+ </li> |
+ <li><a href="#bdFD">A Strategy That Works: Object/Feature Detecting.</a> |
+ <ul> |
+ <li><a href="#bdGEID">Example 1: IDed Element Retrieval</a></li> |
+ <li><a href="#bdScroll">Example 2: Scroll Values</a></li> |
+ <li><a href="#bdReplace">Example 3: String.prototype.replace</a></li> |
+ </ul> |
+ </li> |
+ <li><a href="#bdDesPb">The Javascript Design Problem</a></li> |
+ |
+</ul> |
+ |
+<h2 id="bdIntro">Introduction</h2> |
+ |
+<p id="bdIntro_1"> |
+Under normal circumstances computer programs are written for a known |
+environment. The programmer knows what to expect; which APIs will be |
+available, how they will behave and so on. Java is an ideal example |
+of this, providing a theoretically consistent set of APIs and language |
+features across all Java Virtual Machine (JVM) implementations. But |
+this is also true in most other circumstances. The programmer of C++ |
+for the Windows operating system will know what MFC classes are |
+available and how to program them. Their expectations will be |
+rewarded, if they posses the required knowledge. |
+</p> |
+ |
+<p id="bdIntro_2"> |
+Client side javascript for the Internet, on the other hand, has the |
+possibly unique problem of having to be authored with no specific |
+knowledge of the environment in which it will be executed. The |
+client side environment will usually be a web browser and web |
+browsers do tend to have many common features (and increasingly |
+standardised features) but the author cannot know which version of |
+which browser will be making any HTTP request (or |
+whether it is a browser at all). It is not even possible to tell in |
+advance whether the User Agent will be capable of executing |
+javascript; all of those that can include a user configurable option |
+to disable it anyway. |
+</p> |
+ |
+<p id="bdIntro_3"> |
+Javascript authors for the Internet must realise that they are dealing |
+with the unknown and that any, and all, scripts will fail to execute |
+somewhere. The challenge is to get the most from your javascript when |
+it is available but to cope with their failure in a meaningful way. |
+</p> |
+ |
+<p id="bdIntro_4"> |
+I once read a description of a variant on the game of chess, played |
+at military academies. Two players sit at separate boards set up with |
+only their own pieces, out of sight of each other, and a referee |
+supervises the game. Each player makes their move in turn and the |
+referee is responsible for informing them how the other's move impacts |
+on their own pieces and how the other's disposition of pieces impact |
+on their intended move. The player is informed only when one of their |
+own pieces is taken, when one of their moves is affected by |
+interacting with one of their opponents pieces (i.e. a player may want |
+to move a bishop across the board but the referee may inform them that |
+their move was stopped four squares early when the bishop took a pawn |
+from the other side) and when one of their opponents pieces is |
+sitting on a square adjacent to one of their own. |
+</p> |
+ |
+<p id="bdIntro_5"> |
+The game is used to teach battlefield strategy. To win a player must |
+probe and test to deduce his opponent's disposition, while planing and |
+executing a response that will achieve the desired checkmate. It is |
+this sort of strategy that needs to be added to the normal programming |
+problems in order that javascript may cope with its unknown execution |
+environment, with the significant difference that the strategy, its |
+tests and all of the paths of execution must be fully planed out before |
+the code can even starts executing. |
+</p> |
+ |
+<h2 id="bdValid">Avoiding Structural Differences in the Browser DOMs</h2> |
+ |
+<p id="bdValid_1"> |
+While the point of this article is to introduce techniques for handling |
+the differences between web browsers and their DOM implementations it |
+is also possible to avoid some types of differences especially related |
+to the structure of the DOM that is being scripted. |
+</p> |
+ |
+<p id="bdValid_2"> |
+If I was asked to recommend one action most likely to promote the |
+authoring of cross-browser scripts it would be: <strong><em>Start |
+from a basis of valid <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language" |
+>HTML</abbr></span></em></strong>.</p> |
+ |
+<p id="bdValid_3"> |
+Browsers presented with invalid <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> will usually attempt to error |
+correct it in order to do the best possible job of displaying it. |
+Some browsers, particularly IE, are tolerant of all sorts of strange |
+formulations of mark-up. Valid <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> has a tree-like structure, elements |
+may completely contain others but they cannot overlap, and there are |
+rules about which elements may appear in which contexts. The DOM that |
+is to be scripted also has a tree-like structure and there is a very |
+simple relationship between the tree-like structure of valid <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> and |
+the DOM constructed from it. So any browser presented with valid <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> |
+will be able to directly translate that <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> into a corresponding DOM |
+using well specified rules, resulting in a DOM that is of predictable |
+and consistent structure on all of the browsers that can build a DOM. |
+</p> |
+ |
+<p id="bdValid_4"> |
+Invalid <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> will not translate as naturally into a DOM, or even a |
+tree-like structure. If the browser is going to build a DOM with the |
+source provided it is going to have to apply error correcting rules |
+and attempt to build the best DOM it can. But the error correcting |
+rules are not standardised, not even published. So different browsers |
+have no choice but apply different rules and that directly results in |
+the building of DOMs with different (and in extremes, radically |
+different) structures. |
+</p> |
+ |
+<p id="bdValid_5"> |
+As a result, using invalid <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> directly produces differences in the |
+DOMs produced by different browsers. No matter how good the application |
+of techniques for dealing with the differences between browsers, it |
+does not make sense to do anything that will provoke more differences |
+than are unavoidable. |
+</p> |
+ |
+<p id="bdValid_6"> |
+The authoring of invalid <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span>, justified because "It works in |
+browser XYZ", gives the authors of accompanying scripts the |
+impression that cross-browser scripting is harder than it is. If they |
+had started with valid <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> they would never have encountered any of |
+the structural inconsistencies that invalid <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> can provoke. |
+</p> |
+ |
+<h2 id="bdDif">Browsers Differences</h2> |
+ |
+<p id="bdDif_1"> |
+As browsers have evolved they have offered more features to javascript. |
+Different manufactures have adopted the features of other browsers, |
+while adding new features, that may in turn have been adopted by (or |
+will be adopted by) their competitors. Various sets of common features |
+have emerged and some have been formalised by the W3C into a sequence |
+of standard DOM specifications. Along the way an increasing number of |
+javascript capable browsers have emerged. In addition to desktop PC |
+browsers, javascript capable browsers exist for a whole range of |
+devices; PDAs, mobile telephones (Microwave ovens, refrigerators). |
+</p> |
+ |
+<p id="bdDif_2"> |
+Unfortunately it is the case that the browsers on the smaller devices |
+cannot offer the range of features available to a desktop PC and even |
+as the technology improves and features are added to the smaller |
+browsers the problem will not improve as browsers will become available |
+on a wider range of devices while the desktop PC browsers will continue |
+to march ahead of them. |
+</p> |
+ |
+<p id="bdDif_3"> |
+Over the years various strategies have been attempted to tackle this |
+problem and some have failed miserably. |
+</p> |
+ |
+<h2 id="bdFailS">Failed Strategies: Browser Detecting</h2> |
+ |
+<h3 id="bdUAS">Assumptions Based on navigator.userAgent</h3> |
+ |
+<p id="bdUAS_1"> |
+One of the most popular strategies for handling the differences between |
+web browsers was browser detecting based on the User Agent string. |
+Browsers possessing a <code>navigator</code> object also provide a |
+property of that object: <code>navigator.userAgent</code> containing a |
+string that (in theory) identifies the browser. Its application went |
+something like:- |
+</p> |
+ |
+<pre id="bdUAS_ex1"> |
+<span class="commentJS">/* Warning: never use this script, or any script based on, or resembling, it. |
+*/</span> |
+var userAgent = self.navigator.userAgent; |
+var appName = self.navigator.appName; |
+var isOpera = false; |
+var isOpera5 = false; |
+var isOpera6p = false; |
+var isIE = false; |
+var isIE4 = false; |
+var isIE5p = false; |
+var isMozilla1p = false; |
+var isNet4 = false; |
+var isNet5p = false; |
+var operaVersion = 0; |
+var ieVersion = 0; |
+var appVersion = self.navigator.appVersion; |
+var brSet = false; |
+ |
+function brSetup(){ |
+ for(var c = 3;c < appVersion.length;c++){ |
+ var chr = appVersion.charAt(c); |
+ if(isNaN(chr)){ |
+ appVersion = appVersion.substring(0, c); |
+ break; |
+ } |
+ } |
+ if((userAgent.indexOf('webtv') < 0) && |
+ (userAgent.indexOf('hotjava') < 0)){ |
+ if(userAgent.indexOf('Opera') >= 0){ |
+ var ind = (userAgent.indexOf('Opera')+6); |
+ if(((ind+1) < userAgent.length)&&(ind >= 6)){ |
+ isOpera = true; |
+ var bsVersion = parseInt(userAgent.substring(ind, ind+1)); |
+ if(!isNaN(bsVersion)){ |
+ operaVersion = bsVersion; |
+ if(operaVersion >= 6){ |
+ isOpera6p = true; |
+ }else if(operaVersion >= 5){ |
+ isOpera5 = true; |
+ } |
+ } |
+ } |
+ }else if(appName.indexOf('Microsoft Internet Explorer') >= 0){ |
+ var ind = (userAgent.indexOf('MSIE')+5); |
+ if(((ind+1) < userAgent.length)&&(ind >= 5)){ |
+ isIE = true; |
+ var bsVersion = parseInt(userAgent.substring(ind, ind+1)); |
+ if(!isNaN(bsVersion)){ |
+ ieVersion = bsVersion; |
+ if(ieVersion >= 5){ |
+ isIE5p = true; |
+ }else if(ieVersion >= 4){ |
+ isIE4 = true; |
+ } |
+ } |
+ } |
+ }else if(appName.indexOf('Netscape') >= 0){ |
+ if((self.navigator.vendor)&& |
+ (self.navigator.vendor.indexOf('Netscape') >= 0)&& |
+ (userAgent.indexOf('Gecko') >= 0)){ |
+ isNet5p = true; |
+ }else if((userAgent.indexOf('Netscape') < 0)&& |
+ (userAgent.indexOf('Gecko') >= 0)&& |
+ (appVersion >= 5)){ |
+ isMozilla1p = true; |
+ }else if((appVersion < 5)&& |
+ (userAgent.indexOf('compatible') < 0)){ |
+ isNet4 = true; |
+ } |
+ } |
+ } |
+ brSet = true; |
+} |
+</pre> |
+ |
+<p id="bdUAS_2"> |
+This version also uses some other properties of the |
+<code>navigator</code> object; <code>appName</code> and |
+<code>appVersion</code>. |
+</p> |
+ |
+<p id="bdUAS_3"> |
+Superficially this type of script seems to be saying quite a lot about |
+what browser is executing the script. Knowing that the |
+<code>isIE5p</code> variable is boolean <code>true</code> seems to be |
+a reasonable indicator that the browser in question is Internet |
+Explorer Version 5 or above and from that all of the available features |
+on the IE 5+ DOM could be assumed to exist. |
+</p> |
+ |
+<p id="bdUAS_4"> |
+Unfortunately, if this type of script ever was an effective determiner |
+of the browser type, it is not now. The first problem is that you cannot |
+write this type of script to take into account all web browsers. The |
+script above is only interested in Internet Explorer, Netscape and |
+(some) Mozilla derived browsers and Opera. Any other browser will not |
+be identified, and that will include a number of W3C DOM conforming |
+fully dynamic visual browsers quite capable of delivering on even quite |
+demanding code. |
+</p> |
+ |
+<p id="bdUAS_5"> |
+The second problem is that scripts like this one, and server-side |
+counter-parts (reading the HTTP User Agent header) were used to |
+<em>exclude</em> browsers that did not fall into a set of browsers |
+known to the author, regardless of whether those browsers were |
+capable of displaying the offending site or not. |
+</p> |
+ |
+<p id="bdUAS_6"> |
+As more browsers were written, their authors discovered that if they |
+honestly reported their type and version in their User Agent string |
+they would likely be excluded from sites that they would |
+otherwise be quite capable of displaying. To get around this problem |
+browsers began spoofing the more popular versions, sending HTTP User |
+Agent headers, and reporting <code>navigator.userAgent</code> strings, |
+that were indistinguishable from, say, IE. |
+</p> |
+ |
+<p id="bdUAS_7"> |
+As a result, when the above script reports <code>isIE5p</code> as true, it is |
+possible that the browser that is executing the script is one of |
+numerous current browsers. Many of those browsers support sufficient |
+features found on IE5+ to allow most scripts to execute but the |
+trueness of <code>isIE5p</code> is not a valid indicator that the |
+browser will support <em>all</em> of the IE 5+ DOM. |
+</p> |
+ |
+<p id="bdUAS_8"> |
+Now you might decide that a browser that lies about its identity |
+deserves what it gets (though they started lying in order to make |
+themselves usable in the face of near-sighted <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> and script authors) |
+but is worth bearing in mind that the IE 5 |
+<code>navigator.userAgent</code> string is: |
+<code>"Mozilla/4.0 (compatible; MSIE 5.01; Windows NT)"</code>. |
+IE 5 is in fact spoofing Netscape 4, and Microsoft started to do that |
+for precisely the same reasons that motivate many current browsers to |
+send User Agent headers, and report <code>navigator.userAgent</code> |
+strings that are indistinguishable form those of Microsoft browsers. |
+</p> |
+ |
+<p id="bdUAS_9"> |
+No browser manufacture wants (or ever has wanted) their browser to be |
+needlessly excluded from displaying a web site that it is perfectly |
+capable of handling just because the author of that site does not |
+know it by name. And to prevent that they have followed Microsoft and |
+taken action that has rendered the <code>userAgent</code> string (and |
+the HTTP User Agent header) meaningless. |
+</p> |
+ |
+<p id="bdUAS_10"> |
+We are now at a point where the contents of the User Agent strings |
+bear no relationship at all to the capabilities and features of the |
+browser that is reporting it. The situation has gone so far that a |
+number of javascript experts have stated that a standard quality test |
+for an unknown script would include searching the source code of the |
+script for the string <code>"userAgent"</code> and dismissing |
+the script out of hand if that string is found. |
+</p> |
+ |
+<h3 id="bdOI">Assumptions Based on DOM Objects: Object inference</h3> |
+ |
+<p id="bdOI_1"> |
+A second browser detecting strategy uses the objects present in various |
+browser DOMs and make the assumption that the presence (or absence) of |
+one or more objects indicates that a browser is a particular type or |
+version. I quickly found this example of typical code of this type:- |
+</p> |
+ |
+<pre id="bdOI_ex1"> |
+<span class="commentJS">/* Warning: never use this script, or any script based on, or resembling, it. |
+*/</span> |
+var isDOM=(document.getElementById)?true:false; |
+var isIE4=(document.all&&!isDOM)?true:false; |
+var isIE5p=(document.all&&isDOM)?true:false; |
+var isIE=(document.all)?true:false; |
+var isOP=(window.opera)?true:false; |
+var isNS4=(document.layers)?true:false; |
+</pre> |
+ |
+<p id="bdOI_2"> |
+Javascript performs automatic type conversion so when a boolean result |
+is expected from an expression that evaluates to a non-boolean value |
+that non-boolean value is (internally) converted to a boolean value |
+(using the rules defined in the ECMAScript specification) and that |
+boolean is used as the result. |
+</p> |
+ |
+<p id="bdOI_3"> |
+Take the first line:- |
+</p> |
+ |
+<pre id="bdOI_ex2"> |
+var isDOM=(document.getElementById)?true:false; |
+</pre> |
+ |
+<p id="bdOI_4"> |
+The conditional expression requires that the expression preceding the <code>?</code> |
+have a boolean result. The <code>document.getElementById</code> |
+property accessor can resolve as one of two values depending on whether |
+the <code>getElementById</code> function is supported in the browser in |
+question. If it is supported then the accessor resolves as a function |
+object, and is type converted to boolean <code>true</code>. If |
+<code>getElementById</code> is not supported the accessor resolves as |
+undefined, and undefined type converts to boolean |
+<code>false</code>. Thus the expression preceding the question mark |
+resolves as <code>true</code> or <code>false</code> and based on that |
+result <code>true</code> or <code>false</code> are assigned to the |
+variable <code>isDOM</code>. |
+</p> |
+ |
+<div class="tip"> |
+ <h4>Boolean Conversion Tip: !!</h4> |
+ <p id="bdOI_5"> |
+ Incidentally, this code is not the optimum method of assigning a boolean |
+ value based on the type converted to boolean result of a property accessor. |
+ It is better to use the javascript NOT operator ( <code>!</code> ) twice |
+ or to pass the object reference as the argument to the <code>Boolean</code> |
+ constructor called as a function. The not operator will type convert its |
+ operand to boolean and then invert it so <code>false</code> becomes |
+ <code>true</code> and <code>true</code> becomes <code>false</code>. |
+ Passing that result as the operand for a second not operator inverts |
+ the boolean again so a reference to a function object results in boolean |
+ <code>true</code> and an undefined reference results in boolean |
+ <code>false</code>. The <code>Boolean</code> constructor called as a |
+ function converts its argument to boolean and returns that value. The |
+ statement would become:- |
+ </p> |
+ |
+ <pre id="bdOI_ex3"> |
+ var isDOM = !!document.getElementById; |
+ |
+ <span class="commentJS">/* - or - */</span> |
+ |
+ var isDOM = Boolean(document.getElementById); |
+ </pre> |
+ |
+ <p id="bdOI_6"> |
+ Which is shorter and faster than the original version and certainly |
+ more direct. |
+ </p> |
+</div> |
+ |
+<h4>Inductive Generalization Fallacy</h4> |
+<p id="bdOI_7"> |
+The problem with this type of browser detecting script is that it is |
+used to make assumptions about the browser's capabilities that are |
+rarely valid. For example, this <code>isDOM</code> result, based on |
+the browser's support for <code>document.getElementById</code>, is |
+often used as the basis for the assumption that the browser has a |
+fully dynamic DOM with methods such as |
+<code>document.createElement</code>, <code>replaceChild</code> and |
+<code>appendChild</code>. Browsers do not live up to that expectation, |
+some are not that dynamic and while they may implement some of the Core |
+DOM level 1 methods such as <code>getElementById</code> They do not |
+necessarily implement large parts of the various DOM standards, |
+including all of the dynamic <code>Node</code> manipulation methods. |
+</p> |
+ |
+<p id="bdOI_8"> |
+The result of the <code>isIE5p</code> test is intended to indicate that |
+the browser is Internet Explorer 5.0 or above. However, Opera 7, |
+IceBrowser 5.4, Web Browser 2.0 (palm OS), Konquerer, Safari, NetFront, |
+iCab and others will all produce a <code>true</code> value in |
+<code>isIE5p</code> because they implement <code>getElementById</code> |
+and the <code>document.all</code> collection. As a result, code that |
+assumes that it will have <em>all</em> of the capabilities of IE 5.0+ |
+available to it when <code>isIE5p</code> is <code>true</code> will as |
+often as not be mistaken. |
+</p> |
+ |
+<p id="bdOI_9"> |
+This problem applies to all of the tests above with the possible |
+exception of the <code>window.opera</code> test. I am unaware of a |
+second browser type that has implemented an <code>opera</code> object |
+on the window object. But then Opera 7 is a radically different, and |
+much more dynamic browser that its preceding versions, though they all |
+possess a <code>window.opera</code> object. |
+</p> |
+ |
+<p id="bdOI_10"> |
+To get around the problem that multiple browsers implement the same |
+features (even if they start off unique to one browser) script authors |
+have attempted to find more discriminating features to test. For |
+example, the following script extract is intended to work only on IE |
+5.0+ browsers:- |
+</p> |
+ |
+<pre id="bdOI_ex4"> |
+var isIE5p = !!window.ActiveXObject; |
+... |
+function copyToClip(myString){ |
+ if(!isIE5p) return; |
+ window.clipboardData.setData("text",myString); |
+} |
+</pre> |
+ |
+<p id="bdOI_11"> |
+The <code>ActiveXObject</code> constructor is intended to be |
+discriminating of an IE browser. However, this type if script still |
+does not work. It has placed the competing browser manufacturers in |
+exactly the same position as they were in when scripts tested the |
+<code>navigator.userAgent</code> string and excluded them from |
+accessing a site because they honestly reported that they where not |
+IE. As a result I already know of one browser that has implemented |
+a <code>window.ActiveXObject</code> function, it probably is a dummy |
+and exists in the browsers DOM specifically to defeat the exclusion |
+of that browser based on tests like the one above. |
+</p> |
+ |
+<p id="bdOI_12"> |
+The assumptions that the existence of one (or two) feature(s) in a |
+javascript environment infers the existence of any feature beyond |
+the ones tested is invalid. It is only used by those ignorant of the |
+potential for diversity, imitation and the patterns of evolution in |
+browser DOMs. |
+</p> |
+ |
+<p id="bdOI_13"> |
+No matter how specifically the objects from which the inferences are |
+derived are chosen, the technique itself sows the seeds of its own |
+invalidity, an object that may actually validly be used to infer that |
+a browser is of a particular type/version today probably will not still |
+be valid next year. Adding a maintenance burden to a task that already |
+presupposes an omniscient knowledge of <em>all</em> browser DOMs just |
+in order to be effectively implemented at present. |
+</p> |
+ |
+ |
+<h2 id="bdFD">A Strategy That Works: Object/Feature Detecting</h2> |
+ |
+<p id="bdFD_1"> |
+The main point of the previous discussion is to convey the idea that it |
+is impossible to detect exactly which type of browser (or version of |
+that browser) a script is being executed on. The use that such scripts |
+have been put to in the past (to exclude browsers from sites that |
+they probably could have successfully handled) has motivated the |
+manufactures of browsers to render browser detecting nonviable |
+as a strategy for dealing with the variations in browser DOMs. |
+</p> |
+ |
+<p id="bdFD_2"> |
+Fortunately, not being able to identify a web browser type or version |
+with more accuracy than could be achieved by generating a random number |
+and then biasing the result by your favourite (meaningless, because |
+they too are based on browser detecting and suffer exactly the same |
+unreliability) browser usage statistics, does not need to impact upon |
+your ability to script web browsers at all. A viable alternative |
+strategy has been identified and developed to the point where it is |
+possible to author javascript to be used on web pages without any |
+interest in the type or version of the browser at all. |
+</p> |
+ |
+<p id="bdFD_3"> |
+That alternative strategy is known as object or feature detecting. I |
+prefer to use the term "feature detecting", partly because the |
+resulting code often needs to test and probe a wider range of |
+features than just those that could be described as objects, but |
+mostly because "object detecting" is occasionally |
+erroneously applied to the object inference style of script described |
+above. |
+</p> |
+ |
+<p id="bdFD_4"> |
+Feature detecting seeks to match an attempt to execute as script (or a |
+part of a script) with the execution environment by seeking to test |
+features of that environment where the results of the test have a |
+direct one-to-one relationship with the features that need to be |
+supported in the environment for the code to successfully execute. It |
+is the direct one-to-one relationship in the implemented tests that |
+avoids the need to identify the specific browser because whatever |
+browser it is it either will support all of the required features or |
+it will not. That would mean testing the feature itself (to ensure |
+that it exists on the browser) and possibly aspects of the behaviour |
+of that feature. |
+</p> |
+ |
+<p id="bdFD_5"> |
+Taking the previous example that illustrated how the |
+<code>ActiveXObject</code> constructor might be used as the basis for |
+a script that inferred the existence of, and ability to use, the |
+<code>clipboardData</code> feature implemented on window IE. Rather |
+than inferring the browser's support for the <code>clipboardData</code> |
+feature from some other unrelated feature it should be fairly obvious |
+that the feature that should be tested for prior to attempting to write |
+to the clipboard <em>is</em> the <code>clipboardData</code> object, and |
+further, that calling the <code>setData</code> method of that object |
+should necessitate checking that it too is implemented:- |
+</p> |
+ |
+<pre id="bdFD_ex1"> |
+function copyToClip(myString){ |
+ if((typeof clipboardData != 'undefined')&& |
+ (clipboardData.setData)){ |
+ clipboardData.setData("text",myString); |
+ } |
+} |
+</pre> |
+ |
+<p id="bdFD_6"> |
+In this way the tests that determine whether the |
+<code>clipboardData.setData</code> method is called have a direct |
+one-to-one relationship with the browser's support for the feature. It |
+is not necessary to be interested in whether the browser is the |
+expected windows IE that is known to implement the feature, or whether |
+it is some other browser that has decided to copy IE's implementation |
+and provide the feature itself. If the feature is there (at least to |
+the required extent) it is used and if it is not there no attempt is |
+made to use it. |
+</p> |
+ |
+<p id="bdFD_7"> |
+The above feature detecting tests are done using two operations. The |
+first employs the <code>typeof</code> operator, which returns a string |
+depending on the type of its operand. That string is one of |
+<code>"undefined"</code>, <code>"object"</code>, |
+<code>"function"</code>, <code>"boolean"</code> |
+<code>"string"</code> and <code>"number"</code> |
+and the test compares the returned string with the string |
+<code>"undefined"</code>. The <code>clipboardData</code> |
+object is not used unless typeof does not return |
+<code>"undefined"</code>. |
+</p> |
+ |
+ |
+<p id="bdFD_8"> |
+The second test is a type-converting test. The logical AND |
+(<code>&&</code>) operator internally converts its operands to |
+boolean in order to make its decision about what value it will return. |
+If <code>clipboardData.setData</code> is undefined it will type-convert |
+to boolean <code>false</code>, while if it is an object or a function |
+the result of the conversion will be boolean <code>true</code>. |
+</p> |
+ |
+<p id="bdFD_9"> |
+However, that function is not a particularly clever application of |
+feature detecting because, while it avoids the function throwing errors |
+in an attempt to execute <code>clipboardData.setData</code> on a browser |
+thatdoes not support it, it will do nothing on a browser that does not |
+support it. That is a problem when the user has been presented with a |
+GUI component that gives them the impression that their interaction |
+will result in something being written to the clipboard but when they |
+use it nothing happens. And of course nothing was going to happen if |
+the browser in use did not support javascript or it had been disabled. |
+</p> |
+ |
+<p id="bdFD_10"> |
+Ensuring that a script will not attempt to use a feature that is not |
+supported is not sufficient to address the design challenge of crating |
+scripts for the Internet. Testing the browser for the features that it |
+does support makes it practical to handle a spectrum of browser DOMs |
+but the script design task also involves planning how to handle the |
+range of possibilities. A range that goes from guaranteed failure to |
+execute at all on browser that do not support javascript, to full |
+support for all of the required features. |
+</p> |
+ |
+<p id="bdFD_11"> |
+You can tell when the browser does not support the |
+<code>clipboardData</code> feature from the script prior to using it |
+but the user has no way of knowing why a button that promised them |
+some action has failed to do anything. So in addition to matching the |
+script to the browser's ability to execute it, it is also necessary to |
+match the GUI, and the user's resulting expectations, to what the |
+script is going to be able to deliver. |
+</p> |
+ |
+<p id="bdFD_12"> |
+Suppose the <code>copyToClip</code> function was called from an |
+<code>INPUT</code> element of <code>type="button"</code> |
+and was intended to copy a company e-mail address into the clipboard, |
+the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> code for the button might look like:- |
+</p> |
+ |
+<pre id="bdFD_ex2"> |
+<input type="button" |
+ value="copy our contact e-mail address to your clipboard" |
+ onclick="copyToClip('info@example.com')"> |
+</pre> |
+ |
+<p id="bdFD_13"> |
+We know that that <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> will do nothing if javascript is |
+disabled/unavailable and we know that it will do nothing if the browser |
+does not support the required features, so one option would be to use a |
+script to write the button <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> into the document in the position in |
+which the button was wanted when the browser provided the facility:- |
+</p> |
+ |
+<pre id="bdFD_ex3"> |
+<script type="text/javascript"> |
+ if((typeof clipboardData != 'undefined')&& |
+ (clipboardData.setData)&& |
+ (document.write)){ |
+ document.write('<input type="button"', |
+ 'value="copy our contact e-mail address', |
+ ' to your clipboard" onclick="', |
+ 'copyToClip(\'info@example.com\')">'); |
+ } |
+</script> |
+</pre> |
+ |
+<p id="bdFD_14"> |
+Now the user will never see the button unless the browser supports the |
+required features <em>and</em> javascript is enabled. The user never |
+gets an expectation that the script will not be able to deliver (at |
+least that is the theory, it is still possible for the user's browser |
+configuration to prevent scripts from writing to the clipboard, but |
+the user might be expected to know how their browser is configured and |
+understand that the button is not in a position to override it). |
+</p> |
+ |
+<p id="bdFD_15"> |
+If the <code>copyToClip</code> function is only ever called from |
+buttons that are written only following the required feature detection |
+then it can be simplified by the removal of the test from its body as |
+it would be shielded from generating errors on nonsupporting browsers by |
+the fact that there would be no way for it to be executed. |
+</p> |
+ |
+<p id="bdFD_16"> |
+The <code>document.write</code> method is not the only way of adding |
+GUI components to a web page in a way that can be subject to the |
+verification of the features that render those components meaningful. |
+Alternatives include writing to a parent element's |
+<code>innerHTML</code> property (where supported, see |
+<a href="/faq/#updateContent">FAQ: How do I modify the content of the current page?</a>), or using the W3C DOM |
+<code>document.crateElement</code> (or <code>createElementNS</code>) |
+methods and appending the created element at a suitable location within |
+the DOM. Either of these two approaches are suited to adding the |
+components after the page has finished loading, but that can be useful |
+as some feature testing is not practical before that point. The |
+approach used can be chosen based on the requirements of the script. |
+If the script is going to be using the |
+<code>document.createElement</code> method itself then it is a good |
+candidate as a method for inserting any required GUI components, |
+similarly with <code>innerHTML</code>. The <code>document.write</code> |
+method is universally supported in <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> DOMs but is not necessarily |
+available at all in XHTML DOMs. |
+</p> |
+ |
+<p id="bdFD_17"> |
+Other ways of handling the possibility that the browser will not |
+support either javascript or the features required by the script used |
+is to design the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span>/<span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> parts of the page so that the script, upon |
+verifying support for the features it requires, can modify, manipulate |
+and transform the resulting elements in the DOM. But in the absence of |
+sufficient script support the unmodified <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> presents all of the |
+required content, navigation, etc. |
+</p> |
+ |
+<p id="bdFD_18"> |
+This can be particularly significant with things like navigation menus. |
+One style of design would place the content of the navigation menus, |
+the URLs and text, in javascript structures such as Arrays. But either |
+of javascript being disabled/unavailable on the client or the absence |
+of the features required to support a functional javascript menu would |
+leave the page without any navigation at all. Generally that would not |
+be a viable web page, and not that good for search engine placement as |
+search engine robots do not tend to execute javascript either so they |
+would be left unable to navigate a site featuring such a menu and so |
+unable to rank its content for listing. |
+</p> |
+ |
+<p id="bdFD_19"> |
+A better approach to menu design would have the navigation menu content |
+defined in the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span>, possibly as nested list elements of some sort, and |
+once the script has ascertained that the browser is capable of executing |
+it and providing the menu in an interactive form it can modify the <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> |
+<code>position</code>, <code>display</code> and <code>visibility</code> |
+properties, move the elements to their desired location, attach event |
+handlers and generally get on with the task of providing a javascript |
+menu. And the worst that happens when the browser does not support |
+scripting or the required features is that the user (and any search |
+engine robots) finds the navigation in the page as a series of nested |
+lists containing links. Fully functional, if not quite as impressive as |
+it could have been had the script been supported. This is termed |
+"clean degradation" and goes hand in hand with feature |
+detecting during the process of planing and implementing a browser |
+script for the Internet. |
+</p> |
+ |
+<h3 id="bdGEID">Example 1: IDed Element Retrieval</h3> |
+ |
+<p id="bdGEID_1"> |
+An important aspect of feature detecting is that it allows a script to |
+take advantage of possible fall-back options. Having deduced that a |
+browser lacks the preferred feature it still may be possible to |
+achieve the desired goal by using an alternative feature that is know |
+to exist on some browsers. A common example of this is retrieving an |
+element reference from the DOM given a string representing the |
+<code>ID</code> attribute of that element. The preferred method would |
+be the W3C Core DOM standard <code>document.getElementById</code> |
+method which is supported on the widest number of browsers. If that |
+method was not available but the browser happened to support the |
+<code>document.all</code> collection then it could be used for the |
+element retrieval as a fall-back option. And for some types of |
+elements, such as <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> positioned elements on Netscape 4 (where the |
+<code>document.layers</code> collection may be used to retrieve such |
+a reference), additional options may be available. |
+</p> |
+ |
+<pre id="bdGEID_ex1"> |
+function getElementWithId(id){ |
+ var obj; |
+ if(document.getElementById){ |
+ <span class="commentJS">/* Prefer the widely supported W3C DOM method, if |
+ available:- |
+ */</span> |
+ obj = document.getElementById(id); |
+ }else if(document.all){ |
+ <span class="commentJS">/* Branch to use document.all on document.all only |
+ browsers. Requires that IDs are unique to the page |
+ and do not coincide with NAME attributes on other |
+ elements:- |
+ */</span> |
+ obj = document.all[id]; |
+ }else if(document.layers){ |
+ <span class="commentJS">/* Branch to use document.layers, but that will only work for |
+ <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> positioned elements and LAYERs that are not nested. A |
+ recursive method might be used instead to find positioned |
+ elements within positioned elements but most DOM nodes on |
+ document.layers browsers cannot be referenced at all. |
+ */</span> |
+ obj = document.layers[id]; |
+ } |
+ <span class="commentJS">/* If no appropriate/functional element retrieval mechanism |
+ exists on this browser this function returns null:- |
+ */</span> |
+ return obj||null; |
+} |
+</pre> |
+ |
+<p id="bdGEID_2"> |
+Although that function is not very long or complex (without its |
+comments) it does demonstrate a consequence of one style of |
+implementation of feature detecting, it repeats the test each time |
+it is necessary to retrieve an element using its ID. If not too many |
+elements need retrieving that may not be significant, but if many |
+elements needed retrieving in rapid succession and performance was |
+significant then the overhead of performing the feature detection on |
+each retrieval may add up and impact on the resulting |
+script. |
+</p> |
+ |
+<p id="bdGEID_3"> |
+An alternative is to assign one of many functions to a global |
+<code>getElementWithId</code> variable based on the results of the |
+feature detecting tests, as the script loads. |
+</p> |
+ |
+<pre id="bdGEID_ex2"> |
+var getElementWithId; |
+if(document.getElementById){ |
+ <span class="commentJS">/* Prefer the widely supported W3C DOM method, if |
+ available:- |
+ */</span> |
+ getElementWithId = function(id){ |
+ return document.getElementById(id); |
+ } |
+}else if(document.all){ |
+ <span class="commentJS">/* Branch to use document.all on document.all only |
+ browsers. Requires that IDs are unique to the page |
+ and do not coincide with NAME attributes on other |
+ elements:- |
+ */</span> |
+ getElementWithId = function(id){ |
+ return document.all[id]; |
+ } |
+}else if(document.layers){ |
+ <span class="commentJS">/* Branch to use document.layers, but that will only work for <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> |
+ positioned elements. This function uses a recursive method |
+ to find positioned elements within positioned elements but most |
+ DOM nodes on document.layers browsers cannot be referenced at |
+ all. This function is expected to be called with only one |
+ argument, exactly like the over versions. |
+ */</span> |
+ getElementWithId = function(id, baseLayers){ |
+ <span class="commentJS">/* If the - baseLayers - parameter is not provided default |
+ its value to the document.layers collection of the main |
+ document: |
+ */</span> |
+ baseLayers = baseLayers||document.layers; |
+ <span class="commentJS">/* Assign the value of the property of the - baseLayers - |
+ object (possibly defaulted to the document.layers |
+ collection) with the property name corresponding to the |
+ - id - parameter to the local variable - obj: |
+ */</span> |
+ var obj = baseLayers[id]; |
+ <span class="commentJS">/* If - obj - remains undefined (no element existed with the |
+ given - id -) try searching the indexed members of |
+ - baseLayers - to see if any of their layers collections |
+ contain the element with the corresponding - id: |
+ */</span> |
+ if(!obj){ <span class="commentJS">//Element not found</span> |
+ <span class="commentJS">/* Loop through the indexed members of - baseLayers: */</span> |
+ for(var c = 0;c < baseLayers.length;c++){ |
+ if((baseLayers[c])&& <span class="commentJS">//Object at index - c.</span> |
+ (baseLayers[c].document)&& <span class="commentJS">//It has a - document.</span> |
+ <span class="commentJS">/* And a layers collection on that document: */</span> |
+ (baseLayers[c].document.layers)){ |
+ <span class="commentJS">/* Recursively call this function passing the - id - as |
+ the first parameter and the layers collection from |
+ within the document found on the layer at index - c |
+ - in - baseLayers - as the second parameter and |
+ assign the result to the local variable - obj: |
+ */</span> |
+ obj=getElementWithId(id,baseLayers[c].document.layers); |
+ <span class="commentJS">/* If - obj - is now not null then we have found the |
+ required element and can break out of the - for - |
+ loop: |
+ */</span> |
+ if(obj)break; |
+ } |
+ } |
+ } |
+ <span class="commentJS">/* If - obj - will type-convert to boolean true (it is not null |
+ or undefined) return it, else return null: |
+ */</span> |
+ return obj||null; |
+ } |
+}else{ |
+ <span class="commentJS">/* No appropriate element retrieval mechanism exists on |
+ this browser. So assign this function as a safe dummy. |
+ Values returned form calls to getElementWithId probably |
+ should be tested to ensure that they are non-null prior |
+ to use anyway so this branch always returns null:- |
+ */</span> |
+ getElementWithId = function(id){ |
+ return null; |
+ } |
+} |
+ |
+<span class="commentJS">/* |
+Usage:- |
+ |
+var elRef = getElementWithId("ID_string"); |
+if(elRef){ |
+ ... //element was found |
+}else{ |
+ ... //element could not be found. |
+} |
+*/</span> |
+</pre> |
+ |
+<p id="bdGEID_4"> |
+The feature detecting tests are performed once as the page loads and |
+one of many function expressions assigned to the |
+<code>getElementWithId</code> global variable as a result. The |
+assigned function is the one most capable of retrieving the required |
+element on the browser in use but it is still necessary to check that |
+the returned value in not <code>null</code> and plan for the |
+possibility of failure in the element retrieval process. It is |
+guaranteed to fail on any browser that does not implement at least one |
+of the element retrieval mechanisms used as the default function just |
+returns <code>null</code>. |
+</p> |
+ |
+<p id="bdGEID_5"> |
+It may not be sufficient to provide a function that does the best job |
+of element retrieval that can be done on the browser in use. Other |
+scripts, or parts of the script, may need to know how successful their |
+attempts to retrieve elements are likely to be. The |
+<code>getElementWithId</code> version that uses |
+<code>document.layers</code> cannot retrieve elements that are not <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> |
+positioned and that may not be good enough for some scripts, while it |
+may not matter to others. The <code>document.getElementById</code> and |
+<code>document.all</code> versions should be able to retrieve any |
+element given its <code>ID</code>. An opting would be to set a couple |
+of boolean flags to indicate how successful element retrieval can be |
+expected to be. Defaulting the flags to <code>false</code> and setting |
+them to <code>true</code> in the branches that assign the various |
+function expressions. Then if other code is interested in what can be |
+expected from the <code>getElementWithId</code> function, say in order |
+to decide how to configure, or default itself, it can check the |
+pertinent flag. |
+</p> |
+ |
+<pre id="bdGEID_ex3"> |
+var getElementWithId; |
+var canGetAnyElement = false; <span class="commentJS">//default any element flag</span> |
+var canGetCSSPositionedElements = false; <span class="commentJS">//default <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> positioned flag</span> |
+if(document.getElementById){ |
+ canGetAnyElement = true; <span class="commentJS">//set any element flag to true</span> |
+ canGetCSSPositionedElements = true; <span class="commentJS">//set <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> positioned flag true</span> |
+ getElementWithId = ... |
+}else if(document.all){ |
+ canGetAnyElement = true; <span class="commentJS">//set any element flag to true</span> |
+ canGetCSSPositionedElements = true; <span class="commentJS">//set <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> positioned flag true</span> |
+ getElementWithId = ... |
+}else if(document.layers){ |
+ canGetCSSPositionedElements = true; <span class="commentJS">//set <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> positioned flag true</span> |
+ <span class="commentJS">/* The - canGetAnyElement - flag is not set in this branch because |
+ the document.layers collection does not make *all* elements |
+ available. |
+ */</span> |
+ getElementWithId = ... |
+}else{ |
+ <span class="commentJS">/* Neither flag is set when the dummy function is assigned because |
+ it is guaranteed not to be able to retrieve any elements: |
+ */</span> |
+ getElementWithId = function(id){ |
+ return null; |
+ } |
+} |
+... |
+if(canGetCSSPositionedElements){ |
+ <span class="commentJS">/* Expect to be able to retrieve <span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span> positioned elements. |
+ */</span> |
+ ... |
+ if(canGetAnyElement){ |
+ <span class="commentJS">/* Expect to also be able to retrieve any other elements that |
+ have an ID attribute. |
+ */</span> |
+ ... |
+ } |
+} |
+</pre> |
+ |
+<p id="bdGEID_6"> |
+The flags do not directly reflect which feature is going to be used |
+for element retrieval, instead they reflect what can be expected from |
+the <code>getElementWithId</code> function on the current browser. |
+Allowing a script that requires a particular level of performance |
+(say the retrieval of any element) to determine whether it will have |
+that facility but without denying the facility from a script with a |
+less demanding requirement. |
+</p> |
+ |
+<h3 id="bdScroll">Example 2: Scroll Values</h3> |
+ |
+<p id="bdScroll_1"> |
+Another common task that needs to be approached differently on |
+different browsers is the retrieval of the extent to which the user |
+has scrolled a web page. The majority of browsers provide properties |
+of the global object called <code>pageXOffset</code> and |
+<code>pageYOffset</code>, which hold the relevant values. Some make the |
+equivalent browsers available as scrollLeft and scrollTop properties on |
+the "root" element (either in addition to the |
+<code>pageX/YOffset</code> properties or instead of them). The task is |
+complicated further by the fact that which element is the |
+"root" element depends on various factors, it was always the |
+<code>document.body</code> element in the past but newer (<span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span>) |
+standards compliant browsers (and browsers that can operate in various |
+modes, including standards compliant mode) make the |
+<code>document.documentElement</code> the root element. Then there may |
+be browsers that do not make the scrolling values available at all. |
+</p> |
+ |
+<p id="bdScroll_2"> |
+Because the <code>pageXOffset</code> and <code>pageYOffset</code> |
+properties are implemented on the largest number of browsers, and their |
+use avoids the need to worry about the "root" element, they |
+are the preferred values to use. In there absence the problem moves on |
+to identifying the "root" element, which is made easier by |
+the browsers that understand standards compliant mode and provide a |
+<code>document.compatMode</code> string property to announce which mode |
+they are in. If the string property is missing or the value of that |
+string is other than <code>"CSS1Compat"</code> then it is the |
+<code>document.body</code> object that needs to be read for the |
+scrolling values, else the <code>document.documentElement</code> should |
+be read. Testing for the presence of any of the scroll values |
+themselves needs to done with a <code>typeof</code> test because they |
+are numeric values and if implemented but set to zero a type-converting |
+test would return <code>false</code> but that would not be an indicator |
+of their absence. |
+</p> |
+ |
+<p id="bdScroll_3"> |
+The following is an example that employs feature detection to decide |
+which scroll values to read:- |
+</p> |
+ |
+<pre id="bdScroll_ex1"> |
+<span class="commentJS">/* The - getPageScroll - global variable is assigned a reference to a |
+ function and when that function is called initially it configures |
+ the script to read the correct values, if available, and then |
+ returns a reference to the object - interface - which provides |
+ methods that retrieve the scroll values. Subsequent invocations of |
+ the getPageScroll function do not repeat the configuration, they |
+ just return a reference to the same interface object. Because the |
+ configuration stage may need to check whether the document.body |
+ element exists the function cannot be called until the browser has |
+ parsed the opening body tag as prior to that point there is no |
+ document.body element. |
+ |
+ Usage:- |
+ var scrollInterface = getPageScroll(); |
+ var scrollX = scrollInterface.getScrollX(); |
+ var scrollY = scrollInterface.getScrollY(); |
+ |
+ The interface methods return NaN if the browser provides no method |
+ of reading the scroll values. A returned NaN value can be tested for |
+ with the - isNaN - global function, but it should not be necessary |
+ to perform the isNaN test on more than the first retrieval because |
+ if the returned value is NaN it will always be NaN and if it is not |
+ it should never be. |
+ |
+ if(isNaN(scrollX)){ |
+ //No scroll value retrieval mechanism was available on this browser |
+ } |
+ |
+ (* The script performs an inline execution of a function expression |
+ which returns the function object that is assigned to the - |
+ getPageScroll - global variable. This produces a closure that |
+ preserves the local variables of the executed function expression, |
+ allowing the execution context of the function expression to provide |
+ a repository for the configuration results, keeping them out of the |
+ global namespace. The format is:- |
+ |
+ v--- Anonymous function expression --v |
+ var variable = (function(){ ...; return returnValue; })(); |
+ Inline execution of the function expression ----^^ |
+ |
+ The value returned by the inline execution of the anonymous function |
+ expression is assigned to the variable. If that returned value is a |
+ reference to an inner function object then the assignment will form |
+ a closure.) |
+*/</span> |
+var getPageScroll = (function(){ |
+ <span class="commentJS">/* The local variable "global" is assigned the value - this - |
+ because the function expression is executing in the global |
+ context and - this - refers to the global object in that |
+ context. The global object is usually the - window - object on |
+ web browsers but this local variable is going to be used in the |
+ configuration tests for convenience: |
+ */</span> |
+ var global = this; |
+ <span class="commentJS">/* notSetUp - Is a flag to indicate when the script has done the |
+ setup configuration: |
+ */</span> |
+ var notSetUp = true; |
+ <span class="commentJS">/* readScroll - Is initially a dummy object that is used to return |
+ the NaN values whenever no functional scroll value retrieval |
+ mechanism is available on the browser. It is assigned a |
+ reference to the object from which the scroll values can be read |
+ if the feature detection determines that to be possible: |
+ */</span> |
+ var readScroll = {scrollLeft:NaN,scrollTop:NaN}; |
+ <span class="commentJS">/* Using the local variables - readScrollX - and readScrollY - to |
+ hold the property names allows the same functions to read both |
+ the pageX/YOffset properties of the global object and the |
+ scrollTop/Left properties of the "root" element by assigning |
+ different values to the variables. These are the defaults: |
+ */</span> |
+ var readScrollX = 'scrollLeft'; |
+ var readScrollY = 'scrollTop'; |
+ <span class="commentJS">/* The - itrface - local variable is assigned a reference to an |
+ object and it is this object that is returned whenever |
+ getPageScroll() is called. The object has two properties, |
+ getScrollX and getScrollY, which are assigned the values of two |
+ anonymous function expressions. These functions are inner |
+ functions and as a result have access to the local variables of |
+ the function that contains them (the anonymous function |
+ expression that is executed inline in order to assign value to |
+ the getPageScroll global variable). The use a square bracket |
+ property accessor to read a value of whatever object has been |
+ assigned to the variable - readScroll - with a property name |
+ that corresponds to the value assigned to whichever of the |
+ variables - readScrollX - or - readScrollY - are employed, |
+ allows the functions to use the simplest code poible to provide |
+ values for all of the possible permutations resting from the |
+ feature detection derived configuration: |
+ */</span> |
+ var itrface = { |
+ getScrollX:function(){ |
+ return readScroll[readScrollX]; |
+ }, |
+ getScrollY:function(){ |
+ return readScroll[readScrollY]; |
+ } |
+ }; |
+ <span class="commentJS">/* The - setUp - inner function is called to perform the feature |
+ detection and configure the variables that will be employed in |
+ reading the correct scroll values. It sets the - notSetUp - flag |
+ to false once it has been executed so that configuration only |
+ happens the first time that a request for the interface object |
+ is made: |
+ */</span> |
+ function setUp(){ |
+ <span class="commentJS">/* As the paeX/YOffset properties are the preferred values to |
+ use they are tested for first. They are not both tested |
+ because if one exists the other can be assumed to exist for |
+ symmetry. The testing method is a - typeof - test to see if |
+ the value is a number. A type-converting test cannot be used |
+ because the number zero would result in boolean false and a |
+ pageXOffset value will be zero if the page has not been |
+ scrolled: |
+ */</span> |
+ if(typeof global.pageXOffset == 'number'){ |
+ <span class="commentJS">/* If pageXOffset is a number then the value of the - |
+ global - variable (assigned a reference to the global |
+ object earlier) is assigned to the - readScroll - |
+ variable and the strings "pageXOffset" and "pageYOffset" |
+ are assigned to the - readScrollX - and - readScrollY - |
+ variables so they will be the property names used to |
+ access the - readScroll- (now the global) object. |
+ */</span> |
+ readScroll = global; |
+ readScrollY = 'pageYOffset'; |
+ readScrollX = 'pageXOffset'; |
+ }else{ |
+ <span class="commentJS">/* If pageXOffset is undefined it is time to find out which |
+ object is the "root" element. First, does the browser |
+ have a - document.compatMode - string, if it does then |
+ is its value "BackCompat", "QuirksMode" or "CSS1Compat". |
+ Instead of comparing the string directly it is searched |
+ for the substring "<span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span>" which might make the script more |
+ robust in the face of possible future "CSSnCompat" |
+ modes, which are unlikely to demand that the "root" |
+ element is moved again. |
+ |
+ The tests also verifies that there is a - |
+ document.documentElement - to read and that its |
+ - scrollLeft - property is a number: |
+ */</span> |
+ if((typeof document.compatMode == 'string')&& |
+ (document.compatMode.indexOf('CSS') >= 0)&& |
+ (document.documentElement)&& |
+ (typeof document.documentElement.scrollLeft=='number')){ |
+ <span class="commentJS">/* The - readScrollX - and - readScrollY - variables |
+ are already defaulted to the required strings so it |
+ is only necessary to assign a reference to the - |
+ document.documentElement - to the - readScroll - |
+ variable: |
+ */</span> |
+ readScroll = document.documentElement; |
+ <span class="commentJS">/* If the browser is not in the appropriate mode the scroll |
+ values should be read from the document.body - element, |
+ assuming it exists on this browser and that the |
+ - scrollLeft - property is a number: |
+ */</span> |
+ }else if((document.body)&& |
+ (typeof document.body.scrollLeft == 'number')){ |
+ <span class="commentJS">/* The - readScrollX - and - readScrollY - variables |
+ are already defaulted to the required strings so it |
+ is only necessary to assign a reference to the - |
+ document.body - to the - readScroll - variable: |
+ */</span> |
+ readScroll = document.body; |
+ } |
+ <span class="commentJS">/* No other scroll value reading options exist so if - |
+ readScroll - has not been assigned a new value by this |
+ point it will remain a reference to the object with the |
+ NaN value properties. |
+ */</span> |
+ } |
+ notSetUp = false; <span class="commentJS">//No need to repeat configuration.</span> |
+ } |
+ <span class="commentJS">/* The inline execution of the anonymous function expression |
+ returns with the following statement. It returns an inner |
+ function expression and it is that function that will be called |
+ when getPageScroll() is executed. Doing this forms a closure, |
+ preserving all of the local variables and functions defined |
+ within the executed anonymous function expression. Calling that |
+ returned function as - getPageScroll() - executes the setUp |
+ function, but only if it has not already been called, and |
+ returns a reference to the - itrface - object. |
+ */</span> |
+ return (function(){ |
+ if(notSetUp){ <span class="commentJS">//If the - notSetUp - variable is still true.</span> |
+ setUp(); <span class="commentJS">//Execute the - setUp - function.</span> |
+ } |
+ return itrface; <span class="commentJS">//returns a reference to - itrface</span> |
+ }); |
+})(); <span class="commentJS">//inline-execution of anonymous function expression, one-off!</span> |
+</pre> |
+ |
+<p id="bdScroll_4"> |
+The effect of this code is to match the browser's ability to provide |
+the scrolling information with a script's desire to read it through a |
+simple and efficient interface that acts based on the results of |
+featured detecting tests that it applies only once, and if the browser |
+does not support any methods of reading the scroll values the return |
+values form the interface method indicate that fact by being NaN. It |
+does not matter that Netscape 4 will be reading the global |
+<code>pageX/YOffset</code> properties, that IE 4 will read the |
+<code>scrollTop/Left</code> properties from <code>document.body</code> |
+or that IE 6 will read those values from one of two possible objects |
+based on the <code>document.compatMode</code> value. What is important |
+is that if unknown browser XYZ provides any of those mechanisms for |
+reporting the scroll values the script is going to be able to use them, |
+without ever knowing (or caring) that it is browser XYZ that it is |
+executing on. |
+</p> |
+ |
+<h3 id="bdReplace">Example 3: String.prototype.replace</h3> |
+ |
+<p id="bdReplace_1"> |
+Feature detecting is not restricted to features of the DOM, it can be |
+extended to include features of the javascript language implementation. |
+For example the <code>String.prototype.replace</code> function in later |
+language versions will accept a function reference as its second |
+argument, while earlier versions only accept a string in that context. |
+Code that wants to use the function argument facility of the |
+<code>replace</code> method will fail badly if it is not supported on |
+the browser. |
+</p> |
+ |
+<p id="bdReplace_2"> |
+As usual, a feature-detecting test for the implementation's ability to |
+support function arguments with the <code>replace</code> method has to |
+be a direct test on that feature. The following example test takes |
+advantage of the fact that a browser that only supports the string |
+argument version of <code>replace</code> will type-convert a function |
+reference used in that context into a string. The <code>replace</code> |
+method uses a Regular Expression (its first argument) to |
+identify parts of a string and then replaces them with a string that is |
+provided as its second argument. If the second argument is a function, |
+and the browser supports the function argument, that function is called |
+and its return value replaces the identified parts of the string. |
+</p> |
+ |
+<p id="bdReplace_3"> |
+By providing a function expression that returns an empty string as its |
+second argument and a Regular Expression that identifies the entire |
+original string as the first argument, the operation of the |
+<code>replace</code> method will result in an empty string if the |
+function argument is supported. But if only string arguments are |
+supported then the function will be type-converted into a string and |
+that string will not be an empty string so the result of the |
+evaluation of the <code>replace</code> method will not be an empty |
+string. Applying a NOT (<code>!</code>) operation to the resulting |
+string type-converts the empty string into a boolean value, inverts |
+it and returns <code>true</code>, the non-empty string would result |
+in <code>false</code>. |
+</p> |
+ |
+<pre id="bdReplace_ex1"> |
+<span class="commentJS">/* The original string is the one letter string literal "a". The |
+ Regular Expression /a/ identifies that entire string, so it is the |
+ entire original string that will be replaced. The second argument is |
+ the function expression - function(){return '';} -, so the entire |
+ original string will be replaced with an empty string if the |
+ function expression is executed. If it is instead type-converted |
+ into a string that string will not be an empty string. The NOT (!) |
+ operation type-converts its operand to boolean and then inverts it |
+ so the results of the test is boolean true if function references |
+ are supported in the second argument for the - replace - method, and |
+ false when not supported: |
+*/</span> |
+if(!('a'.replace(/a/, (function(){return '';})))){ |
+ ... <span class="commentJS">//function references OK.</span> |
+}else{ |
+ ... <span class="commentJS">//no function references with replace.</span> |
+} |
+</pre> |
+ |
+<p id="bdReplace_4"> |
+The common thread with feature detecting is that it is the code that is |
+going to use the features, and the nature of those features, that |
+defines how support for the required feature needs to be tested. Once |
+you get used to the idea it starts to become obvious which tests need |
+to be applied to verify a browser's support for a feature, and then it |
+is time to work on the efficient application of feature detection. |
+</p> |
+ |
+<h2 id="bdDesPb">The Javascript Design Problem</h2> |
+ |
+<p id="bdDesPb_1"> |
+Javascript as a language is not that complex, it may have its quirks |
+but it can be defined entirely in the 173 pages of the ECMA |
+specification (3rd edition). The challenge of authoring javascript |
+comes form the diversity of execution environments. When authoring for |
+the Internet nothing is known about the receiving software in advance, |
+and even when that software is a web browser that will execute |
+javascript, there is still a spectrum of possible DOM implementations |
+to contend with. |
+</p> |
+ |
+<p id="bdDesPb_2"> |
+The combination of the facts that it is impossible to determine which |
+browser is executing the script, and that it is impossible to be |
+familiar with all browser DOMs can be rendered insignificant by using |
+feature detection to match code execution with any browser's ability to |
+support it. But there is still going to be a diversity of |
+outcomes, ranging from total failure to execute any scripts (on |
+browsers that do not support javascript, or have it disabled) to full |
+successful execution on the most capable javascript enabled browsers. |
+</p> |
+ |
+<p id="bdDesPb_3"> |
+The challenge when designing scripts is to cope with all of the |
+possibilities in a way that makes sense for everyone. As those |
+possibilities will always include browsers incapable of executing |
+javascript at all, the starting point must be pages based on (valid) |
+<span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> that contain all of the required content, allow the necessary |
+navigation and are as functional as they purport to be (possibly with |
+the backing of server-side scripting, which does not have any of the |
+problems of client side scripting). On top of that reliable foundation |
+it is possible to layer the scripts. Feature detecting and adding |
+scripted enhancements when the browser is capable of supporting them, |
+cleanly degrading to the underlying and reliable <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> when it is not. |
+</p> |
+ |
+<p id="bdDesPb_4"> |
+A well designed script, implementing a suitable strategy, can enhance |
+the underlying <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> page, exploiting the browser's capabilities to the |
+maximum extent possible and still exhibit planed behaviour in the |
+absence of any (or all) desired features and degrade cleanly where |
+necessary. Nobody should either consider themselves a skilled Internet |
+javascript author, or deprecate javascript as a language and/or browser |
+scripting as a task, until they have demonstrated an ability to write |
+a non-trivial script that achieves that goal. |
+</p> |
+</body> |
+</html> |
/cljs/notes/detect-browser/index.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/notes/index.html |
=================================================================== |
--- cljs/notes/index.html (nonexistent) |
+++ cljs/notes/index.html (revision 2) |
@@ -0,0 +1,90 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" |
+"http://www.w3.org/TR/html4/strict.dtd"> |
+<html lang="en"> |
+<head> |
+<title>Notes on the comp.lang.javascript FAQ</title> |
+<meta HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1"> |
+<link href="../faq.css" rel="stylesheet" type="text/css"> |
+<link href="notes.css" rel="stylesheet" type="text/css"> |
+</head> |
+<body> |
+ |
+<h1>Notes on the comp.lang.javascript FAQ</h1> |
+ |
+<div id="faqNav"> |
+ <a href="../">FAQ</a> > FAQ Notes |
+</div> |
+ |
+<h2 id="toc">Table of Contents</h2> |
+<ul id="contTable"> |
+ <li>Posting tips |
+ <ul> |
+ <li> |
+ <a href="posting/">Questions and Replies</a> |
+ </li> |
+ <li> |
+ <a href="code-guidelines/">Code Guidelines</a> |
+ </li> |
+ <li> |
+ <a href="review/">Code Review Guidelines</a> |
+ </li> |
+ </ul> |
+ </li> |
+ <li>Numbers |
+ <dl> |
+ <dt>Why does K = parseInt('09') set K to 0?</dt> |
+ <dd><a href="type-conversion/#tcPrIntRx" |
+ >Javascript Type-Conversion - parseInt with a radix argument</a> |
+ </dd> |
+ </dl> |
+ </li> |
+ <li>DOM and Forms |
+ <dl> |
+ <!--dt>How can I see in javascript if a web browser accepts cookies?</dt> |
+ <dd> |
+ <a href="cookies/">Privacy filters on proxies</a> |
+ </dd--> |
+ <dt> |
+ How do I get the value of a form control? |
+ </dt> |
+ <dd> |
+ <a href="form-access/">Referencing Forms and Form Controls</a> |
+ </dd> |
+ <dd> |
+ <a href="/faq/names/">Unsafe Names for Form Controls</a> |
+ </dd> |
+ <dt>How do I detect Opera/Netscape/IE?</dt> |
+ <dd> |
+ <a href="detect-browser/">Browser Detection (and What to Do Instead)</a> |
+ </dd> |
+ <!-- |
+ <dt>My element is named myselect[], how do I access it?</dt> |
+ <dd> |
+ <a href="square_brackets/">Javascript Square Bracket Notation - Illegal characters in Identifier-strings</a> |
+ </dd> |
+ <dt>How do I access the property of an object using a string? |
+ <dd><a href="square_brackets">Javascript Square Bracket Notation</a> |
+ </dd> |
+ --> |
+ </dl> |
+ </li> |
+ <li>Functions |
+ <ul> |
+ <li><a href="closures/">Javascript Closures</a></li> |
+ <li><a href="http://yura.thinkweb2.com/named-function-expressions/">Named Function Expressions</a></li> |
+ </ul> |
+ </li> |
+ |
+ <!--li>Miscellaneous |
+ <ol> |
+ <li><a href="charter/">The comp.lang.javascript Charter</a></li> |
+ <li><a href="script_tags/">How to Include Scripts in |
+ <abbr class="initialism" title="HyperText Mark-up Language">HTML</abbr> Documents</a></li> |
+ <li><a href="misc/">Tricks and Tips</a></li> |
+ </ol> |
+ </li--> |
+ <!--li><a href="contributors/">Contributors</a></li--> |
+</ul> |
+ |
+</body> |
+</html> |
/cljs/notes/index.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/notes/square-brackets/index.html |
=================================================================== |
--- cljs/notes/square-brackets/index.html (nonexistent) |
+++ cljs/notes/square-brackets/index.html (revision 2) |
@@ -0,0 +1,373 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" |
+"http://www.w3.org/TR/html4/strict.dtd"> |
+<html lang="en"> |
+<head> |
+<title>Square Bracket Notation</title> |
+<meta http-equiv="Content-Type" CONTENT="text/html; charset=iso-8859-1"> |
+<link href="../../faq.css" rel="stylesheet" type="text/css"> |
+<link href="../notes.css" rel="stylesheet" type="text/css"> |
+<meta name="ROBOTS" content="NOINDEX NOFOLLOW"> |
+</head> |
+<body> |
+<h1>Javascript Square Bracket Notation</h1> |
+<div id="faqNav"> |
+ <a href="../../">FAQ</a> > <a href="../">FAQ Notes</a> |
+ |
+</div> |
+<ul> |
+ <li><a href="#intro">Introduction</a></li> |
+ <li><a href="#sBs">Square Bracket Syntax</a></li> |
+ <li><a href="#vId">String Variables as Identifiers</a></li> |
+ <li><a href="#eId">String Expressions as Identifiers</a></li> |
+ <li><a href="#aVa">Global Variable access with the Square Bracket Notation</a></li> |
+ <li><a href="#illc">Illegal characters in Identifier-strings</a></li> |
+</ul> |
+<h2 id="intro">Introduction</h2> |
+ |
+<p id="intro_1">To be useful javascript needs to be able to access the properties of |
+objects. It is impossible to learn javascript without understanding the |
+dot notation that is normally used to access the properties of objects. |
+</p> |
+ |
+<p id="intro_2">Javascript also offers an alternative property accessor notation |
+using square brackets in a way that is similar to the way in which the |
+indexed members of an Array are accessed, except that a string is used |
+between the square brackets. This alternative notation is extremely |
+powerful and useful but gets very little coverage in most books on |
+javascript and that seems to leave novice javascript programmers |
+unaware that they even have this option.</p> |
+ |
+<p id="intro_3">The coverage in javascript books can be very poor. Looking back at |
+some of the books that I first used to learn javascript, one devotes |
+exactly one paragraph to property accessors and another actually states |
+that the square bracket notation can only be used with integer indexes |
+to access Arrays and array-like structures.</p> |
+ |
+<p id="intro_4">With an understanding of dot notation and few clues that an |
+alternative exists, novice (and a few surprisingly experienced) |
+javascript programmers often turn to the <code>eval</code> function, |
+constructing a string that represents a dot notation accessor |
+(frequently retrieving the property names from javascript variables) |
+and then passing it to the <code>eval</code> function in order to |
+access the object property that it refers to. The <code>eval</code> |
+function is just not needed to perform this type of property access |
+and it is a relatively inefficient way of doing so (plus, some embedded |
+browsers lack the resources to implement an <code>eval</code> function). |
+</p> |
+ |
+<h2 id="sBs">Square Bracket Syntax</h2> |
+<p id="sBs_1">If you can access the property of an object using dot |
+notation, such as:-</p> |
+ |
+<pre id="sBs_ex1">document.body</pre> |
+ |
+<p id="sBs_2">- you can also use the square bracket notation:-</p> |
+ |
+<pre id="sBs_ex2">document['body']</pre> |
+ |
+<p id="sBs_3">- in which the dot and the identifier to the right of the dot are |
+replaced with a set of square brackets containing a string that |
+represents the identifier that was to the right of the dot.</p> |
+ |
+<p id="sBs_4">The Property Accessors section of javascript language specification |
+(ECMA 262) makes it clear that the dot notation and the square bracket |
+notation are parallel ways of accessing the properties of objects.</p> |
+ |
+<blockquote cite="http://www.ecma-international.org/publications/files/ecma-st/Ecma-262.pdf"> |
+<dl> |
+ <dt>ECMA 262 3rd Edition. Section 11.2.1 Property Accessors</dt> |
+ <dd> |
+ Properties are accessed by name, using either the dot notation: |
+<pre > |
+MemberExpression.Identifier |
+CallExpression.Identifier |
+</pre> |
+ or the bracket notation: |
+<pre> |
+MemberExpression[ Expression ] |
+CallExpression[ Expression ] |
+</pre> |
+ The dot notation is explained by the following syntactic conversion: |
+ <pre>MemberExpression.Identifier</pre> |
+ is identical in its behaviour to |
+ <pre>MemberExpression[ <identifier-string> ]</pre> |
+ and similarly |
+ <pre>CallExpression.Identifier</pre> |
+ is identical in its behaviour to |
+ <pre >CallExpression[ <identifier-string> ]</pre> |
+ where <code><identifier-string></code> is a string literal |
+ containing the same sequence of characters as the Identifier. |
+ <dd> |
+</dl> |
+</blockquote> |
+ |
+<p id="sBs_5">In the following simple <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> page:-</p> |
+ |
+<pre id="sBs_ex3"> |
+<html> |
+ <head> |
+ <title></title> |
+ </head> |
+ <body> |
+ <form name="formName" action="#"> |
+ <input type="text" name="inpName" value="Example value text"> |
+ </form> |
+ </body> |
+</html> |
+</pre> |
+ |
+<p id="sBs_6">- which contains a form named <code>"formName"</code> with |
+one input element named <code>"inpName"</code>. Various forms |
+of dot notation property accessor can be used to reference the |
+<code>"value"</code> property of the input element. One of |
+the simplest is:-</p> |
+ |
+<pre id="sBs_ex4"> |
+var stringOfValue = document.formName.inpName.value; |
+</pre> |
+ |
+<p id="sBs_7">This dot notation has three dots, so there are three points at which |
+the square bracket notation could be used in place of the dot notation |
+(these are all equivalent).</p> |
+ |
+<pre id="sBs_ex5"> |
+var stringOfValue = document["formName"].inpName.value; |
+ |
+var stringOfValue = document.formName["inpName"].value; |
+ |
+var stringOfValue = document.formName.inpName["value"]; |
+</pre> |
+ |
+<p id="sBs_8">The following combinations are also all equivalent to the original |
+dot notation:-</p> |
+ |
+<pre id="sBs_ex6"> |
+var stringOfValue = document["formName"].inpName["value"]; |
+ |
+var stringOfValue = document["formName"]["inpName"].value; |
+ |
+var stringOfValue = document["formName"]["inpName"]["value"]; |
+ |
+var stringOfValue = window["document"]["formName"]["inpName"]["value"]; |
+</pre> |
+ |
+<p id="sBs_9">Where the dot notation follows the dot with the identifier for the |
+property that is to be accessed, the square bracket notation replaces |
+the dot and identifier with square brackets that contain a string that |
+represents the identifier for the property (the property name).</p> |
+ |
+<h2 id="vId">String Variables as Identifiers</h2> |
+ |
+<p id="vId_1">The string used within the square brackets does not need to be a |
+string literal. It can be any expression that results in a string. |
+This is where the square bracket notation becomes most useful as the |
+expression could be a reference to a string variable that holds the |
+property name as its value, or a function call that returns a string, |
+or an expression that concatenates two strings, or any combination of |
+these.</p> |
+ |
+<p id="vId_2">This means that the identifier needed to access a property does not |
+need to be coded into a javascript. Consider the following simple |
+function:-</p> |
+ |
+<pre id="vId_ex1"> |
+function setPropertyToValue(oObj, sPropName, value){ |
+ oObj[sPropName] = value; |
+} |
+</pre> |
+ |
+<p id="vId_3">- provided with a reference to an object (<code>oObj</code>), the |
+name of a property (<code>sPropName</code>) and a value for that |
+property (<code>value</code>), it will set the value of the property |
+without needing to know what the name of the property that it is |
+setting is. Called as |
+<code>setPropertyToValue(document.formName.inpName, "value", "new value")</code> |
+it will set the value of the field in the example form above to the |
+string <code>"new value"</code>. However, called as |
+<code>setPropertyToValue(window, "location", "http://www.google.com")</code> |
+and the same function will navigate a web browser to the URL provided |
+as the final parameter. Although this is a forced example you should be |
+able to see that the square bracket notation offers considerable power |
+and flexibility.</p> |
+ |
+<p id="vId_4">Any variable that holds a string value can be used between the |
+square brackets to form a property accessor. Variables that hold |
+non-strings will have their value internally type converted into a |
+string and that string will be used as the property name. This is not very |
+useful, especially if the variables contain references to objects or |
+functions, as the returned string is likely to be implementation |
+dependent.</p> |
+ |
+<h2 id="eId">String Expressions as Identifiers</h2> |
+ |
+<p id="eId_1">The ability to build the string used as the property name can be |
+very useful in loops and with dynamically generating web pages (server |
+side) that have variable length content. The strings can be the result |
+of expressions that concatenate string literals with variables |
+(particularly loop counters).</p> |
+ |
+<p id="eId_2">Given the form:-</p> |
+ |
+<pre id="eId_ex1"> |
+<form name="formName" action="#"> |
+ <input type="text" name="field_1"> |
+ <input type="text" name="field_2"> |
+ <input type="text" name="field_3"> |
+</form> |
+</pre> |
+ |
+<p id="eId_3">- the following loop will clear the value property of each element |
+it turn:-</p> |
+ |
+<pre id="eId_ex2"> |
+for(var c = 1;c < 4;c++){ |
+ document.forms["formName"].elements["field_"+c].value = ""; |
+} |
+</pre> |
+ |
+<p id="eId_4">If a server side process had created the <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> form with |
+<code>n</code> elements, named <code>field_1, field_2 ... field_n</code> |
+, then all the server side process would have to do to have the loop |
+clear each and every input element would be to change the <code>4</code> |
+in the example to the value of <code>n+1</code>.</p> |
+ |
+<p id="eId_5">Concatenation is the most common type of expression used with the |
+square bracket notation but any javascript expression could be used. |
+A function that returned a string could be used.</p> |
+ |
+<p id="eId_6">In the following (rather contrived) example :-</p> |
+ |
+<pre id="eId_ex3"> |
+function getRootElName(){ |
+ if(document.compatMode && (document.compatMode == "CSS1Compat")){ |
+ return "documentElement"; |
+ }else{ |
+ return "body"; |
+ } |
+} |
+ |
+var verticalScroll = document[getRootElName()].scrollTop; |
+</pre> |
+<p id="eId_7">- the <code>scrollTop</code> value is read from either the |
+<code>document.body</code> or <code>document.documentElement</code> |
+depending on the value of <code>document.compatMode</code>. Passing |
+strings about is far from the best way of achieving what the code |
+above does but there will be circumstances when returning a string |
+from a function call for use in a property accessor is potentially |
+useful.</p> |
+ |
+<h2 id="aVa">Global Variable access with the Square Bracket Notation</h2> |
+ |
+<p id="aVa_1">The square bracket notation requires that there be some sort of |
+object reference to the left of the brackets.</p> |
+ |
+<pre id="aVa_ex1">["document"] <span class="commentJS">//Array literal, not a Property Accessor!</span></pre> |
+ |
+<p id="aVa_2">-will produce an error if an attempt is made to assign a value to it, |
+as it will be treated as an Array literal, if an attempt to read from |
+it is made the one element array containing the string within the |
+brackets is returned. Global variables are normally referenced by their |
+one identifier alone. This would seem to exclude global variables from |
+the possibility of being referenced using a string that held their |
+identifier name or an expression that built, or returned, their name. |
+However, javascript global variables (and global function names for |
+that matter) are properties of a global object. Any identifier that |
+holds a reference to the global object can be used to the left of the |
+square brackets to form a property accessor that refers to a global |
+variable.</p> |
+ |
+<p id="aVa_3">In a web browser the global object is the window (or frame) in which |
+the script is running. Each window (or frame) object contains a number |
+of properties, at least two of which are references to the window |
+(global object) itself. These properties are 'window' and 'self'. |
+These property names can be used as the identifier to the left of the |
+square brackets when referring to global variables. So given a global |
+variable defined as:-</p> |
+ |
+<pre id="aVa_ex2"> |
+var anyName = 0; |
+</pre> |
+ |
+<p id="aVa_4">- that global variable can be referenced as:-</p> |
+ |
+<pre id="aVa_ex3"> |
+window["anyName"] |
+</pre> |
+ |
+<p id="aVa_5">As with any other use of the square bracket notation, the string |
+within the brackets can be held in a variable or constructed/returned |
+by an expression.</p> |
+ |
+<p id="aVa_6">Code that is executing in the global context, the code within global |
+functions (except Object constructors invoked with the <code>new</code> |
+keyword) and inline code outside of any functions, could also use the |
+<code>this</code> keyword to refer to the global object. The |
+<code>this</code> keyword refers to an object depending on the |
+execution context. For code executing in the global context |
+<code>this</code> is the global object (on a web browser, the window |
+object). As a result, the above variable could be referred to as |
+<code>this["anyName"]</code>, but only in code that is |
+executing in the global context.</p> |
+ |
+<p id="aVa_7">However, using the <code>this</code> keyword is very likely to be |
+confusing, especially in scripts that include custom javascript objects |
+where the methods (and constructors) of those objects would be using |
+<code>this</code> to refer to their own object instances.</p> |
+ |
+<p id="aVa_8">Some javascript implementations do not have a property of the global |
+object that refers to the global object. Rather than trying to use the |
+<code>this</code> keyword to access global variables it is possible to |
+create your own global variable that refers to the global object.</p> |
+ |
+<pre id="aVa_ex4"> |
+var myGlobal = this; |
+</pre> |
+ |
+<p id="aVa_9">- executed as inline code at the start of a script will assign a |
+reference to the global object (<code>this</code> in that context). |
+From then on all global variables can be referenced with square bracket |
+notation as:-</p> |
+ |
+<pre id="aVa_ex5"> |
+myGlobal["anyName"]; |
+</pre> |
+ |
+<p id="aVa_10">- and expect <code>myGlobal</code> to refer to the global object |
+from any execution context.</p> |
+ |
+<h2 id="illc">Illegal characters in Identifier-strings</h2> |
+ |
+<p id="illc_1">One advantage of the square bracket notation over dot notation is |
+the ability to use characters in identifier-strings that are not legal |
+identifier characters. It is generally best to avoid giving javascript |
+properties names and <span class="initialism" title="HyperText Mark-up Language"><abbr title="HyperText Mark-up Language">HTML</abbr></span> elements names/IDs that are not made up |
+entirely of characters that are legal in the relevant context. However, |
+it is not always possible to avoid referencing elements with names that |
+include characters that would be illegal in a javascript identifier. |
+PHP offers an example of this, multiple form elements given the same |
+name followed with empty square brackets, such as |
+<code>name="inpEl[]"</code>, are made available on the server |
+as an array.</p> |
+ |
+<p id="illc_2">The square bracket notation would allow an element with such a name |
+to be referenced as <code> document.forms["formName"].elements["inpEl[]"][0]</code> |
+for example (the final <code>[0]</code> reflects the fact that |
+multiple elements with the same name, when accessed by name, generate |
+collections of elements and individual elements within that collection |
+need to be referenced by index).</p> |
+ |
+<ul style="list-style-type:none;margin-top:2.5em;"> |
+ <li>Written by <span class="person">Richard Cornford</span>. March 2003.</li> |
+ <li>With technical corrections and suggestions by:-<br> |
+ <ul style="list-style-type:none;"> |
+ <li><span class="person">Yann-Erwan Perio (Yep)</span>. (Also, thanks for testing the use |
+ of <code>this</code> to reference the global object in WSH |
+ and ASP2.) |
+ </li> |
+ <li><span class="person">Lasse Reichstein Nielsen</span>.</li> |
+ <li><span class="person">Dr John Stockton</span>.</li> |
+ </ul> |
+ </li> |
+</ul> |
+</body> |
+</html> |
/cljs/notes/square-brackets/index.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/res/[MS-ES3EX].pdf |
=================================================================== |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/cljs/res/[MS-ES3EX].pdf |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+application/octet-stream |
\ No newline at end of property |
Index: cljs/res/ISO_8601-2004_E.pdf |
=================================================================== |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/cljs/res/ISO_8601-2004_E.pdf |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+application/octet-stream |
\ No newline at end of property |
Index: cljs/res/[MS-ES3].pdf |
=================================================================== |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/cljs/res/[MS-ES3].pdf |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+application/octet-stream |
\ No newline at end of property |
Index: cljs/index.html |
=================================================================== |
--- cljs/index.html (nonexistent) |
+++ cljs/index.html (revision 2) |
@@ -0,0 +1,2110 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" |
+"http://www.w3.org/TR/html4/strict.dtd"> |
+<html lang="en"> |
+<head> |
+<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1"> |
+<meta name="DCTERMS.language" scheme="RFC1766" content="en"> |
+<meta name="DC.title" content="comp.lang.javascript Frequently Asked Questions"> |
+<meta name="DCTERMS.subject" content="Frequently asked questions in the Usenet newsgroup comp.lang.javascript"> |
+<meta name="DC.format" content="text/html"> |
+<meta name="DC.type" content="Text"> |
+<meta name="DC.creator" content="Jim Ley"> |
+<meta name="DC.publisher" content="Garrett Smith"> |
+<META name="DC.Publisher.Address" content="dhtmlkitchen@gmail.com"> |
+<meta name="DCTERMS.modified" content="2010-10-08"> |
+<meta name="DCTERMS.audience" content="Programmers, web developers"> |
+<meta name="DC.description" content="Javascript Frequently Asked Questions"> |
+<meta name="DC.identifier" content="http://jibbering.com/faq"> |
+<meta name="DC.source" content="http://www.ecma-international.org/publications/standards/Ecma-262.htm"> |
+<meta name="DC.source" content="news:comp.lang.javascript"> |
+<meta name="DC.source" content="https://developer.mozilla.org/en/JavaScript"> |
+<meta name="DC.source" content="http://msdn.microsoft.com/en-us/library/hbxc2t98%28VS.85%29.aspx"> |
+<meta name="DC.source" content="http://msdn.microsoft.com/en-us/library/ms533050%28VS.85%29.aspx"> |
+<meta name="DC.rights" content="copyright contributors, comp.lang.javascript"> |
+<link rel="StyleSheet" href="faq.css" type="text/css" media="screen"> |
+<title> comp.lang.javascript FAQ</title> |
+</head> |
+ <body> |
+<h1> comp.lang.javascript FAQ</h1> |
+<p>Version 32.2, Updated 2010-10-08, by Garrett Smith</p><div id="nav"><a href="notes/">FAQ Notes</a></div> |
+<ul id='faqList'> |
+<li>1 <a href='#meta'>Meta-FAQ meta-questions</a> |
+ |
+<ul> |
+<li>1.1 <a href='#newsgroups'>Which newsgroups deal with javascript?</a></li> |
+<li>1.2 <a href='#appropriateQuestions'>What questions are on-topic for comp.lang.javascript?</a></li> |
+<li>1.3 <a href='#posting'>What should I do before posting to comp.lang.javascript?</a></li> |
+<li>1.4 <a href='#noAnswer'>Why was my post not answered?</a></li> |
+</ul></li><li>2 <a href='#tips'>Language Overview</a> |
+ |
+<ul> |
+<li>2.1 <a href='#ecma'>What is ECMAScript?</a></li> |
+<li>2.2 <a href='#jScript'>What is JScript?</a></li> |
+<li>2.3 <a href='#dom'>What is the Document Object Model (DOM)?</a></li> |
+<li>2.4 <a href='#localization'>Internationalisation and Localisation in javascript</a></li> |
+<li>2.5 <a href='#futureEcmaScript'>What does the future hold for ECMAScript?</a></li> |
+</ul></li><li>3 <a href='#ecmascriptResources'>Javascript Resources</a> |
+ |
+<ul> |
+<li>3.1 <a href='#books'>What books are recommended for javascript?</a></li> |
+<li>3.2 <a href='#onlineResources'>What online resources are available?</a></li> |
+<li>3.3 <a href='#libraryResources'>Javascript Libraries</a></li> |
+</ul></li><li>4 <a href='#functions'>Functions</a> |
+ |
+<ul> |
+<li>4.1 <a href='#scope'>What is (function(){ /*...*/ })() ?</a></li> |
+<li>4.2 <a href='#functionStatement'>What is a function statement?</a></li> |
+</ul></li><li>5 <a href='#dates'>Dates</a> |
+ |
+<ul> |
+<li>5.1 <a href='#formatDate'>How do I format a Date object with javascript?</a></li> |
+<li>5.2 <a href='#parseDate'>How can I create a Date object from a String?</a></li> |
+</ul></li><li>6 <a href='#numbers'>Numbers</a> |
+ |
+<ul> |
+<li>6.1 <a href='#formatNumber'>How do I format a Number as a String with exactly 2 decimal places?</a></li> |
+<li>6.2 <a href='#binaryNumbers'>Why does simple decimal arithmetic give strange results?</a></li> |
+<li>6.3 <a href='#parseIntBase'>Why does K = parseInt('09') set K to 0?</a></li> |
+<li>6.4 <a href='#typeConvert'>Why does 1+1 equal 11? or How do I convert a string to a number?</a></li> |
+<li>6.5 <a href='#randomNumber'>How do I generate a random integer from 1 to n?</a></li> |
+</ul></li><li>7 <a href='#objects'>Objects</a> |
+ |
+<ul> |
+<li>7.1 <a href='#nativeObject'>What is a native object?</a></li> |
+<li>7.2 <a href='#builtInObject'>What is a built-in object?</a></li> |
+<li>7.3 <a href='#hostObject'>What is a host object?</a></li> |
+<li>7.4 <a href='#eval'>When should I use eval?</a></li> |
+<li>7.5 <a href='#propertyAccessAgain'>How do I access a property of an object using a string?</a></li> |
+</ul></li><li>8 <a href='#strings'>Strings and RegExp</a> |
+ |
+<ul> |
+<li>8.1 <a href='#trimString'>How do I trim whitespace?</a></li> |
+</ul></li><li>9 <a href='#domRef'>DOM and Forms</a> |
+ |
+<ul> |
+<li>9.1 <a href='#formControlAccess'>How do I get the value of a form control?</a></li> |
+<li>9.2 <a href='#propertyAccess'>My element is named myselect[], how do I access it?</a></li> |
+<li>9.3 <a href='#globalPollution'>Why doesn't the global variable "divId" always refer to the element with id="divId"?</a></li> |
+<li>9.4 <a href='#updateContent'>How do I modify the content of the current page?</a></li> |
+<li>9.5 <a href='#accessElementBeforeDefined'>Why does my code fail to access an element?</a></li> |
+<li>9.6 <a href='#testCookie'>How can I see in javascript if a web browser accepts cookies?</a></li> |
+</ul></li><li>10 <a href='#windows'>Windows and Frames</a> |
+ |
+<ul> |
+<li>10.1 <a href='#disableBackButton'>How can I disable the back button in a web browser?</a></li> |
+<li>10.2 <a href='#frameRef'>How do I access a frame's content?</a></li> |
+<li>10.3 <a href='#getWindowSize'>How do I find the size of the window?</a></li> |
+<li>10.4 <a href='#isWindowOpen'>How do I check to see if a child window is open, before opening another?</a></li> |
+<li>10.5 <a href='#printFrame'>Why does framename.print() not print the correct frame in IE?</a></li> |
+<li>10.6 <a href='#windowClose'>How do I close a window and why does it not work on the first one?</a></li> |
+<li>10.7 <a href='#permissionDenied'>Why do I get permission denied when accessing a frame/window?</a></li> |
+<li>10.8 <a href='#setTimeout'>How do I make a 10 second delay?</a></li> |
+<li>10.9 <a href='#printSettings'>How do I change print settings for window.print()?</a></li> |
+<li>10.10 <a href='#changeBrowserDialog'>How do I change the confirm box to say yes/no or default to cancel?</a></li> |
+<li>10.11 <a href='#fileDownload'>How do I prompt a "Save As" dialog for an accepted mime type?</a></li> |
+<li>10.12 <a href='#modifyChrome'>How do I modify the current browser window?</a></li> |
+<li>10.13 <a href='#target'>How do I POST a form to a new window?</a></li> |
+<li>10.14 <a href='#openWindow'>How do I open a new window with javascript?</a></li> |
+</ul></li><li>11 <a href='#ajaxRef'>Ajax and Server Communication</a> |
+ |
+<ul> |
+<li>11.1 <a href='#ajax'>What is Ajax?</a></li> |
+<li>11.2 <a href='#downloadPage'>How do I download a page to a variable?</a></li> |
+<li>11.3 <a href='#getServerVariable'>How do I get a jsp/php variable into client-side javascript?</a></li> |
+<li>11.4 <a href='#sessionExpired'>How do I log-out a user when they leave my site?</a></li> |
+<li>11.5 <a href='#runServerScript'>How do I run a server side script?</a></li> |
+<li>11.6 <a href='#noCache'>How do I force a reload from the server/prevent caching?</a></li> |
+<li>11.7 <a href='#ajaxCache'>Why is my Ajax page not updated properly when using an HTTP GET request in Internet Explorer?</a></li> |
+</ul></li><li>12 <a href='#debugging'>Debugging</a> |
+ |
+<ul> |
+<li>12.1 <a href='#javascriptErrors'>How do I get my browser to report javascript errors?</a></li> |
+</ul></li><li>13 <a href='#doNotTry'>Things not to attempt in a browser</a> |
+ |
+<ul> |
+<li>13.1 <a href='#detectBrowser'>How do I detect Opera/Safari/IE?</a></li> |
+<li>13.2 <a href='#preventAccess'>How can I prevent access to a web page by using javascript?</a></li> |
+<li>13.3 <a href='#hideSource'>How do I protect my javascript code?</a></li> |
+<li>13.4 <a href='#disableRightClick'>How do I suppress a context menu (right-click menu)?</a></li> |
+<li>13.5 <a href='#readFile'>How can I access the client-side filesystem?</a></li> |
+<li>13.6 <a href='#javascriptURI'>I have <a href="javascript:somefunction()"> what ... ?</a></li> |
+</ul></li><li>14 <a href='#comments'>Comments and Suggestions</a> |
+ |
+<ul> |
+<li>14.1 <a href='#FAQENTRY'>Why do some posts have <FAQENTRY> in them?</a></li> |
+<li>14.2 <a href='#makeSuggestion'>How do I make a suggestion?</a></li> |
+</ul></li></ul><div id='meta' class='section'><h2 id='FAQ1'>1 Meta-FAQ meta-questions</h2> |
+<p> |
+ |
+This is the <em>comp.lang.javascript</em> meta-FAQ, 32.2. The latest |
+version is available at <a href="http://jibbering.com/faq/" >http://jibbering.com/faq/</a> in HTML form. |
+</p> <p> |
+ |
+Each day, one section of the FAQ is posted for review and questions, |
+and as a reminder that the FAQ is available. |
+</p> <p> |
+ |
+For additional explanation and detail relating to some aspects |
+of the FAQ, please see the |
+<a href="notes/" >FAQ Notes</a>. |
+It has been provided separately to avoid increasing the size of |
+the FAQ to a point where it would be unreasonable to post it to |
+the group. |
+</p> <p> |
+ |
+Code examples in this FAQ use <a href="http://jsdoctoolkit.org/" >JSDoc Toolkit</a> comments. |
+</p> </div><div id='newsgroups' class='section'><h3 id='FAQ2_1'>1.1 Which newsgroups deal with javascript?</h3><p> |
+ |
+The official Big 8 Usenet newsgroup dealing with javascript is |
+ <a href="news:comp.lang.javascript">comp.lang.javascript</a>. |
+Some "language" hierarchies also have *.comp.lang.javascript groups. |
+ </p> <p> |
+ |
+c.l.js is an unmoderated newsgroup. |
+ </p> </div> |
+<div id='appropriateQuestions' class='section'><h3 id='FAQ2_2'>1.2 What questions are on-topic for comp.lang.javascript?</h3><p> |
+ |
+The comp.lang.javascript newsgroup deals with ECMAScript |
+languages, so any questions about JavaScript or JScript are |
+welcome. However, the majority of questions sent to this group |
+relates to javascript in a web browser. If you are experiencing |
+issues with a particular browser, or the host is not a browser |
+at all, please make this information clear. |
+ </p> <p> |
+ |
+Javascript and Java are two completely different languages. |
+Java questions should be asked in one of the comp.lang.java.* |
+newsgroups; they are not appropriate for c.l.js (as Java and |
+javascript are distinct programming languages with only |
+superficial similarities due to sharing a C-like syntax and |
+some of the characters in their names). |
+ </p> <p> |
+ |
+Questions dealing with other scripting languages, such as |
+VBScript, PerlScript or CGI scripting are also off-topic, |
+as are HTML-only or CSS-only questions. |
+ </p> <p> |
+ |
+Questions that are specific to Microsoft's JScript may also |
+be appropriately asked at: |
+ <a href="news:microsoft.public.scripting.jscript">microsoft.public.scripting.jscript</a></p> <p> |
+ |
+The comp.lang.javascript newsgroup charter is included in |
+<a href="faq_notes/cljs_charter.html" >faq_notes/cljs_charter.html</a>. |
+ </p> </div> |
+<div id='posting' class='section'><h3 id='FAQ2_3'>1.3 What should I do before posting to comp.lang.javascript?</h3><p> |
+ |
+Before posting to c.l.js, you should read this document. |
+You should also check the <a href="#onlineResources" >Resources section</a>. |
+ </p> |
+<h4 id='ask'>How to Ask a Question</h4> |
+ |
+<ul> |
+ <li> |
+State your question clearly and concisely. |
+ </li> |
+ <li> |
+Use the Subject: line to show the type of problem you have but |
+include the question in the body as well. |
+ </li> |
+ <li> |
+For a more detailed explanation of formatting, see |
+ <a href="notes/posting/" >"Posting Questions and Replies to comp.lang.javascript"</a>. |
+ </li></ul> |
+<h4 id='reply'>Replying</h4> |
+ |
+<ul> |
+ <li> |
+Quote only relevant parts of earlier messages, and add your |
+comments below each quoted section |
+(<a href="http://www.ietf.org/rfc/rfc1855.txt" >FYI28/RFC1855</a>). |
+ </li> |
+ <li> |
+Link to specific sections of the FAQ that are relevant. |
+ </li> |
+ <li> |
+Avoid being unnecessarily rude, but do not complain about other rude posts. |
+ </li> |
+ <li> |
+Don't quote signatures. |
+ </li></ul> |
+<h4 id='postCode'>Posting Code</h4> |
+ |
+<ul> |
+ <li> |
+Remove everything that does not contribute to the problem (images, |
+markup, other scripts, etc). |
+ </li> |
+ <li> |
+Validate the HTML and CSS <a href="http://validator.w3.org/" >http://validator.w3.org/</a>, <a href="http://jigsaw.w3.org/css-validator/" >http://jigsaw.w3.org/css-validator/</a>. |
+ </li> |
+ <li> |
+Make sure the code is executable as transmitted. |
+ </li> |
+ <li> |
+Format lines to 72 characters; indent with 2-4 spaces (not tabs). |
+ </li> |
+ <li> |
+State what you expect the code to do. |
+ </li> |
+ <li> |
+Mention the platforms, browsers, and versions. |
+ </li> |
+ <li> |
+See also the <a href="#debugging" >FAQ section on debugging</a>. |
+ </li> |
+ <li> |
+Post in plain-text only. Do not encode it. Do not attach files. |
+ </li> |
+ <li> |
+If the code is more than about 100 lines, provide a URL in addition. |
+ </li> |
+ <li> |
+Do not multi-post; cross-post if necessary |
+(<a href="http://en.wikipedia.org/wiki/Cross-post" >Wikipedia description</a>). |
+ </li></ul> |
+<h4 id='doNotPost'>What Not to Post</h4> |
+ |
+<ul> |
+ <li> |
+Do not post job postings. Job postings should go to |
+an appropriate regional jobs group. |
+ </li> |
+ <li> |
+Do not post copyright material without permission |
+from the copyright holder. |
+ </li></ul><p> |
+ |
+Relevant announcements are welcome, but no more often than once |
+per major release, as a short link to the product's webpage. |
+ </p> </div> |
+<div id='noAnswer' class='section'><h3 id='FAQ2_4'>1.4 Why was my post not answered?</h3><p> |
+ |
+This could be for several reasons: |
+ </p> |
+<ul> <li> |
+It was a variation of a frequently asked question and was |
+therefore ignored by everyone. |
+ </li> |
+<li> |
+Nobody knows the answer. |
+ </li> |
+<li> |
+The person with the answer has not seen the post. |
+ </li> |
+<li> |
+It might not be possible to do what you want to do but perhaps |
+readers of c.l.js are reluctant to answer your post in the negative |
+when they are not convinced that it cannot be done. |
+ </li> |
+<li> |
+The question was not asked clearly enough, or did not included |
+enough information to be answered. |
+ </li> |
+<li> |
+The questioner did not realise the need to read the group, for a |
+few days, to see the answers posted there. |
+ </li> |
+<li> You ignored the <a href="#posting" >section on posting</a> </li> |
+</ul> |
+<p> |
+If it is not one of these, then after a few days consider |
+reposting after checking <a href="http://groups.google.com/group/comp.lang.javascript/topics" >http://groups.google.com/group/comp.lang.javascript/topics</a> |
+for replies. Make sure the post is phrased well, and everything |
+needed to answer is correct, and the subject is appropriate. |
+ </p> </div> |
+<div id='tips' class='section'><h2 id='FAQ2'>2 Language Overview</h2> |
+</div><div id='ecma' class='section'><h3 id='FAQ2_6'>2.1 What is ECMAScript?</h3><p> |
+ <a href="http://www.ecma-international.org/publications/standards/Ecma-262.htm" >ECMA-262</a> |
+is the international standard that current language implementations |
+(JavaScript™, JScript etc.) are based on. |
+ |
+ </p> <p> |
+ <a href="http://www.ecma-international.org/publications/standards/Ecma-262.htm" >ECMA-262</a> |
+defines the language Syntax, Types, Keywords, Operators, and built-in |
+objects. The ECMAScript specification is the reference to determine the |
+expected behavior of a program. ECMAScript does not define any host |
+objects, such as <code>document</code>, <code>window</code>, or <code>ActiveXObject</code>. |
+ </p> <p> |
+ |
+ECMA-327 defines the Compact Profile of ECMAScript by |
+describing the features from ECMA 262 that may be omitted in some |
+resource-constrained environments. |
+<a href="http://www.ecma-international.org/publications/standards/Ecma-327.htm" >http://www.ecma-international.org/publications/standards/Ecma-327.htm</a></p> <p> |
+ |
+The most widely supported edition of ECMA-262 is the 3rd edition (1999). |
+There is fair support for this edition in JScript 5.5+ (buggy) and good |
+support JavaScript 1.5. |
+</p> <p> |
+ |
+The term "javascript" is used as a common name for all dialects of ECMAScript. |
+ </p> </div> |
+<div id='jScript' class='section'><h3 id='FAQ2_7'>2.2 What is JScript?</h3><p> |
+ |
+JScript is Microsoft's implementation of ECMAScript. |
+ </p> <p> |
+ |
+Questions that are specific to Microsoft's JScript may also |
+be appropriately asked at: |
+ <a href="news:microsoft.public.scripting.jscript">microsoft.public.scripting.jscript</a>. |
+ </p> </div> |
+<div id='dom' class='section'><h3 id='FAQ2_9'>2.3 What is the Document Object Model (DOM)?</h3><p> |
+ |
+The |
+<dfn>Document Object Model</dfn> (DOM) is a interface-based model for <code>Document</code> |
+objects. The DOM allows scripts to dynamically access and update a |
+document's content, style, and event handlers. |
+</p> <p> |
+ |
+The DOM is <em>not</em> part of the ECMAScript programming language. |
+</p> <p> |
+ |
+Official DOM standards are defined by the World Wide Web Consortium. |
+Scriptable browsers also have |
+<dfn>proprietary</dfn> DOM features (<a href="http://msdn.microsoft.com/en-us/library/ms533050(VS.85).aspx" >MSDN</a>, <a href="https://developer.mozilla.org/en/DOM_Client_Object_Cross-Reference" >MDC</a>), |
+such as <code>document.writeln()</code>. |
+ </p> <p> |
+ |
+Also see the section on <a href="#domRef" >DOM and Forms</a>. |
+</p><ul class='linkList'><li><a href="#onlineResources" >c.l.js DOM Resources</a></li> |
+<li><a href="http://www.w3.org/DOM/faq.html" >W3C DOM FAQ</a></li> |
+<li><a href="http://www.w3.org/DOM/" >W3C DOM </a></li> |
+<li><a href="https://developer.mozilla.org/en/Gecko_DOM_Reference/Introduction#What_is_the_DOM.3F" >MDC: What is the DOM?</a></li> |
+</ul> </div> |
+<div id='localization' class='section'><h3 id='FAQ2_10'>2.4 Internationalisation and Localisation in javascript</h3><p> |
+ |
+<dfn>Internationalisation</dfn> means using one form which is everywhere both |
+acceptable and understood. Any international standard not supported by |
+default can be coded for. |
+ </p> <p> |
+ |
+For example, there is an International Standard for numeric Gregorian |
+date format; but none for decimal and thousands separators. |
+ </p> <p> |
+ |
+<dfn>Localisation</dfn> is the process of adapting software for a specific region |
+or language by adding locale-specific components and translating text. It |
+cannot work well in general, because it requires a knowledge of all |
+preferences and the ability to choose the right one, in an environment |
+where many systems are inappropriately set anyway. |
+ </p> <p> |
+ |
+ECMAScript has a few |
+<dfn>localisation</dfn> features. The various |
+<code>toString()</code> methods are all implementation dependent, |
+but tend to use either UK or US settings (not necessarily correctly). |
+ECMAScript Ed. 3 introduced some capabilities, including the |
+<code>toLocaleString()</code>method which should create a string |
+based on the host's locale. |
+ </p> <p> |
+ |
+ECMAScript 5th Edition introduces limited ISO 8601 capabilities with |
+<code>Date.prototype.toISOString()</code> and new behavior for <code>Date.parse()</code>. |
+</p> </div> |
+<div id='futureEcmaScript' class='section'><h3 id='FAQ2_12'>2.5 What does the future hold for ECMAScript?</h3><p> |
+ |
+The 5th edition of ECMAScript was approved on 2009-12-04. There is some |
+support in implementations released before approval date (JScript 5.8, |
+JavaScript 1.8, JavaScriptCore). |
+http://www.ecma-international.org/publications/standards/Ecma-262.htm |
+</p><ul class='linkList'><li><a href="http://www.ecma-international.org/publications/standards/Ecma-262.htm" >http://www.ecma-international.org/publications/standards/Ecma-262.htm</a></li> |
+</ul> </div> |
+<div id='ecmascriptResources' class='section'><h2 id='FAQ3'>3 Javascript Resources</h2> |
+</div><div id='books' class='section'><h3 id='FAQ3_1'>3.1 What books are recommended for javascript?</h3><p> |
+ |
+Most javascript books have been found to contain so many technical |
+errors that consensus recommendations have not emerged from the group. |
+ </p> <p> |
+ |
+The following books have been considered to have value by some |
+individuals on c.l.js. The reviews of these books are provided: |
+ </p> |
+<ul> |
+ <li> <em>"JavaScript: The Definitive Guide,"</em> 5th Edition, by David Flanagan |
+ |
+<ul> <li> Published: 2006-08 </li> |
+<li> Pages: 1018 </li> |
+<li> Errata: <a href="http://oreilly.com/catalog/9780596101992/errata/" >http://oreilly.com/catalog/9780596101992/errata/</a> </li> |
+<li> Discussed in: |
+ |
+<ul> <li> <a href="http://groups.google.com/group/comp.lang.javascript/browse_thread/thread/7283898f77fd2a66/9252aa024e058dea#c5f145ae807c918e" >FAQ Update 9.85 Dated 2007-08-31</a> </li> |
+</ul> |
+ </li> |
+</ul> |
+ </li> |
+ <li> <em>"JavaScript, The Good Parts,"</em> 1st Edition, by Douglas Crockford |
+ |
+<ul> <li> Published: 2008-05 </li> |
+<li> Pages: 170 </li> |
+<li> Errata: <a href="http://oreilly.com/catalog/9780596517748/errata/" >http://oreilly.com/catalog/9780596517748/errata/</a> </li> |
+<li> Discussed in: |
+ |
+<ul> <li> <a href="http://groups.google.com/group/comp.lang.javascript/browse_thread/thread/d084d2109f7b4ec7#" >Crockford's 'The Good Parts': a short review</a> </li> |
+<li> <a href="http://groups.google.com/group/comp.lang.javascript/browse_thread/thread/db1e49ab113aa05c/3987eac87ad27966#3987eac87ad27966" >FunctionExpression's and memory consumptions</a> </li> |
+<li> <a href="http://groups.google.com/group/comp.lang.javascript/browse_thread/thread/6a41f7835ee728de/da5ccfc65e2df64a#da5ccfc65e2df64a" >FAQ Topic - What books are recommended for javascript? (2008-12-02)</a> </li> |
+<li> <a href="http://groups.google.com/group/comp.lang.javascript/browse_thread/thread/3a08fb741525ab6d/" >Augmenting functions</a> </li> |
+<li> <a href="http://groups.google.com/group/comp.lang.javascript/browse_thread/thread/bf26be6e63494ee2/acb733a1c35f6ce5#ee9e4ee29e658d5d" >Crockford's JavaScript, The Good Parts (a book review).</a> </li> |
+<li> <a href="http://groups.google.com/group/comp.lang.javascript/browse_thread/thread/df602506ee48b400/e65e00f5cad07676#e65e00f5cad07676" >Closures Explained</a> </li> |
+<li> <a href="http://groups.google.com/group/comp.lang.javascript/browse_thread/thread/acadf1b22b219433/4f69a95607d0b3ae#4f69a95607d0b3ae" >Javascript library development</a> </li> |
+</ul> |
+ </li> |
+</ul> |
+ </li></ul></div> |
+<div id='onlineResources' class='section'><h3 id='FAQ3_2'>3.2 What online resources are available?</h3> |
+<h4 id='ecmaResources'>ECMAScript</h4> |
+ |
+<dl> |
+ <dt> |
+The Official ECMAScript Specification |
+ </dt> |
+ <dd> <a href="[ECMA-262] http://www.ecma-international.org/publications/standards/Ecma-262-arch.htm" >[ECMA-262] http://www.ecma-international.org/publications/standards/Ecma-262-arch.htm</a> </dd> |
+ <dt> |
+[ISO16262] ISO/IEC 16262, Second Edition 2002-06-01 : ISO Standard matching |
+ECMA-262 3rd Edition, with corrections. |
+ </dt> |
+ <dd> <a href="http://standards.iso.org/ittf/PubliclyAvailableStandards/c033835_ISO_IEC_16262_2002(E).zip" >http://standards.iso.org/ittf/PubliclyAvailableStandards/c033835_ISO_IEC_16262_2002(E).zip</a> </dd> |
+ <dt> |
+ [MS-ES3]: Internet Explorer ECMA-262 ECMAScript Language Specification Standards Support |
+ </dt> |
+ <dd> <a href="http://msdn.microsoft.com/en-us/library/ff520996%28VS.85%29.aspx" >http://msdn.microsoft.com/en-us/library/ff520996%28VS.85%29.aspx</a> </dd> |
+ <dd> <a href="res/%5BMS-ES3%5D.pdf" >res/%5BMS-ES3%5D.pdf</a> (local alias) </dd> |
+ <dt> |
+ [MS-ES3EX]: Microsoft JScript Extensions to the ECMAScript Language Specification Third Edition |
+ </dt> |
+ <dd> <a href="http://msdn.microsoft.com/en-us/library/ff521046%28VS.85%29.aspx" >http://msdn.microsoft.com/en-us/library/ff521046%28VS.85%29.aspx</a> </dd> |
+ <dd> <a href="res/%5BMS-ES3EX%5D.pdf" >res/%5BMS-ES3EX%5D.pdf</a> (local alias) </dd> |
+ <dt> ECMAScript on Wikipedia |
+ </dt> |
+ <dd> <a href="http://en.wikipedia.org/wiki/ECMAScript" >http://en.wikipedia.org/wiki/ECMAScript</a> </dd></dl> |
+<h4 id='domResources'>W3C DOM</h4> |
+ |
+<dl> |
+ <dt> |
+DOM Level 1 ECMAScript Binding |
+ </dt> |
+ <dd> <a href="http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html" >http://www.w3.org/TR/REC-DOM-Level-1/ecma-script-language-binding.html</a> </dd> |
+ <dt> |
+DOM Level 2 ECMAScript Binding |
+ </dt> |
+ <dd> <a href="http://www.w3.org/TR/DOM-Level-2-HTML/ecma-script-binding.html" >http://www.w3.org/TR/DOM-Level-2-HTML/ecma-script-binding.html</a> </dd> |
+ <dt> |
+DOM Level 2 Events |
+ </dt> |
+ <dd> <a href="http://www.w3.org/TR/DOM-Level-2-Events/events.html" >http://www.w3.org/TR/DOM-Level-2-Events/events.html</a> </dd> |
+ <dt> |
+DOM Level 2 Style |
+ </dt> |
+ <dd> <a href="http://www.w3.org/TR/DOM-Level-2-Style/" >http://www.w3.org/TR/DOM-Level-2-Style/</a> </dd> |
+ <dt> |
+DOM Level 3 ECMAScript Binding |
+ </dt> |
+ <dd> <a href="http://www.w3.org/TR/DOM-Level-3-Core/ecma-script-binding.html" >http://www.w3.org/TR/DOM-Level-3-Core/ecma-script-binding.html</a> </dd></dl> |
+<h4 id='browserResources'>Browser Documentation</h4> |
+ |
+<dl> |
+ <dt> |
+Mozilla |
+ </dt> |
+ <dd> JavaScript: |
+<a href="http://developer.mozilla.org/en/docs/JavaScript" >http://developer.mozilla.org/en/docs/JavaScript</a> </dd> |
+ <dd> Gecko DOM Reference: |
+<a href="http://developer.mozilla.org/en/docs/Gecko_DOM_Reference" >http://developer.mozilla.org/en/docs/Gecko_DOM_Reference</a> </dd> |
+ <dt> |
+Microsoft |
+ </dt> |
+ <dd> HTML and DHTML Reference: |
+<a href="http://msdn.microsoft.com/en-us/library/ms533050.aspx" >http://msdn.microsoft.com/en-us/library/ms533050.aspx</a> </dd> |
+ <dd> JScript Language Reference: |
+<a href="http://msdn.microsoft.com/en-us/library/hbxc2t98%28VS.85%29.aspx" >http://msdn.microsoft.com/en-us/library/hbxc2t98%28VS.85%29.aspx</a> </dd> |
+ <dd> Scripting: |
+<a href="http://msdn.microsoft.com/en-us/library/ms950396.aspx" >http://msdn.microsoft.com/en-us/library/ms950396.aspx</a> </dd> |
+ <dt> |
+Opera |
+ </dt> |
+ <dd> Web Specifications Support: |
+<a href="http://www.opera.com/docs/specs/#ecmascript" >http://www.opera.com/docs/specs/#ecmascript</a> </dd> |
+ <dd> JavaScript Support: |
+<a href="http://www.opera.com/docs/specs/js/" >http://www.opera.com/docs/specs/js/</a> </dd> |
+ <dd> ECMAScript Support: |
+<a href="http://www.opera.com/docs/specs/js/ecma" >http://www.opera.com/docs/specs/js/ecma</a> </dd> |
+ <dt> |
+BlackBerry JavaScript Reference |
+ </dt> |
+ <dd> <a href="http://docs.blackberry.com/en/developers/deliverables/11849/" >http://docs.blackberry.com/en/developers/deliverables/11849/</a> </dd> |
+ <dt> |
+ICab InScript |
+ </dt> |
+ <dd> <a href="http://www.muchsoft.com/inscript/" >http://www.muchsoft.com/inscript/</a> </dd> |
+ <dt> Apple Safari </dt> |
+ <dd> Web Content Guide: |
+<a href="http://developer.apple.com/safari/library/documentation/AppleApplications/Reference/SafariWebContent/Introduction/Introduction.html" >http://developer.apple.com/safari/library/documentation/AppleApplications/Reference/SafariWebContent/Introduction/Introduction.html</a> </dd> |
+ <dt> |
+Webkit |
+ </dt> |
+ <dd> Project Site: <a href="http://webkit.org/" >http://webkit.org/</a> </dd> |
+ <dd> |
+ Wiki: <a href="http://trac.webkit.org/wiki" >http://trac.webkit.org/wiki</a> </dd> |
+ <dd> DOM Reference: |
+<a href="http://developer.apple.com/Mac/library/documentation/AppleApplications/Reference/WebKitDOMRef/index.html#//apple_ref/doc/uid/TP40006089" >http://developer.apple.com/Mac/library/documentation/AppleApplications/Reference/WebKitDOMRef/index.html#//apple_ref/doc/uid/TP40006089</a> </dd> |
+ <dt> |
+Netscape 4 Client-Side JavaScript Reference |
+ </dt> |
+ <dd> <a href="http://docs.sun.com/source/816-6408-10/" >http://docs.sun.com/source/816-6408-10/</a> </dd> |
+ <dt> |
+Archived documentation for MSIE 3.x |
+ </dt> |
+ <dd> <a href="http://members.tripod.com/%7Ehousten/download/" >http://members.tripod.com/%7Ehousten/download/</a> </dd></dl> |
+<h4 id='standaloneImplementations'>Standalone ECMAScript Implementations</h4> |
+ |
+<dl> |
+ <dt> |
+Rhino: An open-source implementation of JavaScript written in Java |
+ </dt> |
+ <dd> <a href="http://www.mozilla.org/rhino/" >http://www.mozilla.org/rhino/</a> </dd> |
+ <dt> |
+Besen IDE: ECMAScript Edition 5 with IDE |
+ </dt> |
+ <dd> <a href="http://besen.sourceforge.net/" >http://besen.sourceforge.net/</a> </dd> |
+ <dt> |
+V8: Google's open source JavaScript engine |
+ </dt> |
+ <dd> <a href="http://code.google.com/p/v8/" >http://code.google.com/p/v8/</a> </dd> |
+ <dt> |
+SpiderMonkey: Mozilla's C implementation of JavaScript |
+ </dt> |
+ <dd> <a href="http://www.mozilla.org/js/spidermonkey/" >http://www.mozilla.org/js/spidermonkey/</a> </dd> |
+ <dt> |
+Digital Mars DMD Script, console and MS Active Script implementation of ECMAScript |
+ </dt> |
+ <dd> <a href="http://www.digitalmars.com/dscript/" >http://www.digitalmars.com/dscript/</a> </dd></dl> |
+<h4 id='nonBrowserResources'>Other ECMAScript Implementations</h4> |
+ |
+<dl> |
+ <dt> |
+Developing Dashboard Widgets: Apple Developer Connection |
+ </dt> |
+ <dd> <a href="http://developer.apple.com/macosx/dashboard.html" >http://developer.apple.com/macosx/dashboard.html</a> </dd> |
+ <dt> |
+Whitebeam Apache Module: Server Side JavaScript in Apache |
+ </dt> |
+ <dd> <a href="http://www.whitebeam.org/" >http://www.whitebeam.org/</a> </dd></dl></div> |
+<div id='libraryResources' class='section'><h3>3.3 Javascript Libraries</h3><p> |
+ |
+No javascript libraries are endorsed by this group. If you want help |
+with using a library, visit that library's discussion group instead. |
+ </p> </div> |
+<div id='functions' class='section'><h2>4 Functions</h2> |
+</div><div id='scope' class='section'><h3>4.1 What is (function(){ /*...*/ })() ?</h3><p> |
+ |
+This is an anonymous |
+<dfn>FunctionExpression</dfn> that is called |
+immediately after creation. |
+</p> <p> |
+ |
+Variables declared inside a function are not accessible from |
+outside the function. This can be useful, for example, to hide |
+implementation details or to avoid polluting the global scope. |
+</p><ul class='linkList'><li><a href="http://yura.thinkweb2.com/named-function-expressions/" >http://yura.thinkweb2.com/named-function-expressions/</a></li> |
+<li><a href="notes/closures/" >notes/closures/</a></li> |
+<li><a href="http://dmitrysoshnikov.com/ecmascript/chapter-5-functions/#question-about-surrounding-parentheses" >http://dmitrysoshnikov.com/ecmascript/chapter-5-functions/#question-about-surrounding-parentheses</a></li> |
+</ul> </div> |
+<div id='functionStatement' class='section'><h3>4.2 What is a function statement?</h3><p> |
+ |
+The term |
+<dfn>function statement</dfn> has been widely and wrongly used to |
+describe a <code>FunctionDeclaration</code>. This is misleading because in ECMAScript, |
+a <code>FunctionDeclaration</code> is not a |
+<dfn>Statement</dfn>; there are places in a program |
+where a |
+<dfn>Statement</dfn> is permitted but a <code>FunctionDeclaration</code> is not. To add |
+to this confusion, some implementations, notably Mozillas', provide a |
+syntax extension called |
+<dfn>function statement</dfn>. This is allowed under |
+section 16 of ECMA-262, Editions 3 and 5. |
+</p> <p> |
+ |
+Example of nonstandard |
+<dfn>function statement</dfn>: |
+</p> |
+<pre> |
+// Nonstandard syntax, found in GMail source code. DO NOT USE. |
+try { |
+ // FunctionDeclaration not allowed in Block. |
+ function Fze(b,a){return b.unselectable=a} |
+ /*...*/ |
+} catch(e) { _DumpException(e) } |
+</pre> |
+ <p> |
+ |
+Code that uses |
+<dfn>function statement</dfn> has three known interpretations. Some |
+implementations process <code>Fze</code> as a |
+<dfn>Statement</dfn>, in order. Others, including |
+JScript, evaluate <code>Fze</code> upon entering the execution context that it |
+appears in. Yet others, notably DMDScript and default configuration of BESEN, |
+throw a <code>SyntaxError</code>. |
+</p> <p> |
+ |
+For consistent behavior across implementations, <em>do not use function |
+statement</em>; use either <code>FunctionExpression</code> or <code>FunctionDeclaration</code> instead. |
+</p> <p> |
+ |
+Example of <code>FunctionExpression</code> (valid): |
+</p> |
+<pre> |
+var Fze; |
+try { |
+ Fze = function(b,a){return b.unselectable=a}; |
+ /*...*/ |
+} catch(e) { _DumpException(e) } |
+</pre> |
+<p> |
+Example of <code>FunctionDeclaration</code> (valid): |
+</p> |
+<pre> |
+// Program code |
+function aa(b,a){return b.unselectable=a} |
+</pre> |
+ <p> |
+ <!-- |
+Notable examples of the misuse of the term "function statement" |
+can be seen in David Flanagan's "JavaScript: The Definitive Guide", |
+Douglas Crockford's "JavaScript: The Good Parts", MDC documentation, |
+JSLint error messages. |
+--></p><ul class='linkList'><li><a href="example/functionStatement.html" >example/functionStatement.html</a></li> |
+<li><a href="https://mail.mozilla.org/pipermail/es-discuss/2008-February/005314.html" >https://mail.mozilla.org/pipermail/es-discuss/2008-February/005314.html</a></li> |
+<li><a href="http://groups.google.com/group/comp.lang.javascript/msg/aa9a32d0c6ae0342" >http://groups.google.com/group/comp.lang.javascript/msg/aa9a32d0c6ae0342</a></li> |
+<li><a href="http://groups.google.com/group/comp.lang.javascript/msg/3987eac87ad27966" >http://groups.google.com/group/comp.lang.javascript/msg/3987eac87ad27966</a></li> |
+<li><a href="http://nanto.asablo.jp/blog/2005/12/10/172622" >http://nanto.asablo.jp/blog/2005/12/10/172622</a></li> |
+<li> (Article in Japanese) |
+</li> |
+</ul> </div> |
+<div id='dates' class='section'><h2>5 Dates</h2> |
+<p> |
+ |
+ISO 8601 defines date and time formats. Some benefits include: |
+</p> |
+<ul> |
+ <li> language-independent and unambiguous world-wide </li> |
+ <li> sortable with a trivial string comparison </li> |
+ <li> easily readable and writable by software </li> |
+ <li> compatible with standards ISO 9075 and <a href="http://www.ietf.org/rfc/rfc3339.txt" >rfc 3339</a> </li></ul><p> |
+ |
+The ISO Extended format for common date is <code>YYYY-MM-DD</code>, and for time is |
+<code>hh:mm:ss</code>. |
+</p> <p> |
+ |
+For an event with an offset from UTC, use <code>YYYY-MM-DDThh:mm:ss±hh:mm</code>. |
+</p> <p> |
+ |
+Never use a local date/time format for a non-local event. Instead, use |
+UTC, as in <code>YYYY-MM-DDThh:mm:ssZ</code> (<code>Z</code> is the only letter suffix). |
+</p> <p> |
+ |
+The <code>T</code> can be omitted where that would not cause ambiguity. For |
+rfc 3339 compliance, it may be replaced by a space and for SQL, |
+it <em>must</em> be replaced by a single space. |
+</p> <p> |
+ |
+Year <code>0000</code> is unrecognized by some formats (XML Schema, <code>xs:date</code>). |
+ </p><ul class='linkList'><li><a href="#onlineResources" >ECMA-262 Date.prototype, s. 15.9</a></li> |
+<li><a href="http://www.cl.cam.ac.uk/~mgk25/iso-time.html" >A summary of the international standard date and time notation, by Markus Kuhn</a></li> |
+<li><a href="http://en.wikipedia.org/wiki/ISO_8601" >http://en.wikipedia.org/wiki/ISO_8601</a></li> |
+<li><a href="res/ISO_8601-2004_E.pdf" >ISO 8601:2004(E)</a></li> |
+<li><a href="http://www.w3.org/QA/Tips/iso-date" >W3C QA Tip: Use international date format (ISO)</a></li> |
+<li><a href="http://www.ietf.org/rfc/rfc3339.txt" >RFC 3339, Date and Time on the Internet: Timestamps |
+</a></li> |
+<li><a href="http://www.w3.org/TR/xmlschema-2/#dateTime" >http://www.w3.org/TR/xmlschema-2/#dateTime</a></li> |
+</ul> </div><div id='formatDate' class='section'><h3 id='FAQ4_30'>5.1 How do I format a Date object with javascript?</h3><p> |
+ |
+A local <code>Date</code> object where <code>0 <= year <= 9999</code> can be |
+formatted to a common ISO 8601 format <code>YYYY-MM-DD</code> with:- |
+ </p> |
+<pre> |
+ /** Formats a Date to YYYY-MM-DD (local time), compatible with both |
+ * ISO 8601 and ISO/IEC 9075-2:2003 (E) (SQL 'date' type). |
+ * @param {Date} dateInRange year 0000 to 9999. |
+ * @throws {RangeError} if the year is not in range |
+ */ |
+ function formatDate(dateInRange) { |
+ var year = dateInRange.getFullYear(), |
+ isInRange = year >= 0 && year <= 9999, yyyy, mm, dd; |
+ if(!isInRange) { |
+ throw RangeError("formatDate: year must be 0000-9999"); |
+ } |
+ yyyy = ("000" + year).slice(-4); |
+ mm = ("0" + (dateInRange.getMonth() + 1)).slice(-2); |
+ dd = ("0" + (dateInRange.getDate())).slice(-2); |
+ return yyyy + "-" + mm + "-" + dd; |
+ } |
+ </pre> |
+<ul class='linkList'><li><a href="http://www.merlyn.demon.co.uk/js-date9.htm" >http://www.merlyn.demon.co.uk/js-date9.htm</a></li> |
+</ul> </div> |
+<div id='parseDate' class='section'><h3>5.2 How can I create a Date object from a String?</h3><p> |
+ |
+An Extended ISO 8601 local Date format <code>YYYY-MM-DD</code> can be parsed to a |
+Date with the following:- |
+</p> |
+<pre> |
+ /**Parses string formatted as YYYY-MM-DD to a Date object. |
+ * If the supplied string does not match the format, an |
+ * invalid Date (value NaN) is returned. |
+ * @param {string} dateStringInRange format YYYY-MM-DD, with year in |
+ * range of 0000-9999, inclusive. |
+ * @return {Date} Date object representing the string. |
+ */ |
+ function parseISO8601(dateStringInRange) { |
+ var isoExp = /^\s*(\d{4})-(\d\d)-(\d\d)\s*$/, |
+ date = new Date(NaN), month, |
+ parts = isoExp.exec(dateStringInRange); |
+ |
+ if(parts) { |
+ month = +parts[2]; |
+ date.setFullYear(parts[1], month - 1, parts[3]); |
+ if(month != date.getMonth() + 1) { |
+ date.setTime(NaN); |
+ } |
+ } |
+ return date; |
+ }</pre> |
+ </div> |
+<div id='numbers' class='section'><h2>6 Numbers</h2> |
+</div><div id='formatNumber' class='section'><h3 id='FAQ4_6'>6.1 How do I format a Number as a String with exactly 2 decimal places?</h3><p> |
+ |
+When formatting money for example, to format 6.57634 to 6.58, 6.7 to |
+6.50, and 6 to 6.00? |
+ </p> <p> |
+ |
+Rounding of x.xx5 is unreliable, as most numbers are not represented |
+exactly. See also: |
+<a href="#binaryNumbers" >Why does simple decimal arithmetic give strange results?</a></p> <p> |
+ |
+The statement <code>n = Math.round(n * 100)/100</code> converts <code>n</code> to a <code>Number</code> value |
+close to a multiple of <code>0.01</code>. However, there are some problems. |
+Converting the number to a string <code>(n + "")</code>, does not give |
+trailing zeroes. Rounding numbers that are very close to <code>x.5</code>, for example, |
+<code>Math.round(0.49999999999999992)</code> results <code>1</code>. |
+ </p> <p> |
+ |
+ECMA-262 3rd Edition introduced <code>Number.prototype.toFixed</code>. |
+There are bugs in JScript 5.8 and below with certain numbers, for example |
+<code>0.007.toFixed(2)</code> incorrectly results <code>0.00</code>. |
+ </p> <p> |
+ </p> |
+<pre> |
+var numberToFixed = |
+(function() { |
+ return toFixedString; |
+ |
+ function toFixedString(n, digits) { |
+ var unsigned = toUnsignedString(Math.abs(n), digits); |
+ return (n < 0 ? "-" : "") + unsigned; |
+ } |
+ |
+ function toUnsignedString(m, digits) { |
+ var t, s = Math.round(m * Math.pow(10, digits)) + "", |
+ start, end; |
+ if (/\D/.test(s)) { |
+ return "" + m; |
+ } |
+ s = padLeft(s, 1 + digits, "0"); |
+ start = s.substring(0, t = (s.length - digits)); |
+ end = s.substring(t); |
+ if(end) { |
+ end = "." + end; |
+ } |
+ return start + end; // avoid "0." |
+ } |
+ /** |
+ * @param {string} input: input value converted to string. |
+ * @param {number} size: desired length of output. |
+ * @param {string} ch: single character to prefix to s. |
+ */ |
+ function padLeft(input, size, ch) { |
+ var s = input + ""; |
+ while(s.length < size) { |
+ s = ch + s; |
+ } |
+ return s; |
+ } |
+})(); |
+ |
+// Test results |
+document.writeln([ |
+ "numberToFixed(9e-3, 12) => " + numberToFixed(9e-3, 12), |
+ "numberToFixed(1.255, 2) => " + numberToFixed(1.255, 2), |
+ "numberToFixed(1.355, 2) => " + numberToFixed(1.355, 2), |
+ "numberToFixed(0.1255, 3) => " + numberToFixed(0.1255, 3), |
+ "numberToFixed(0.07, 2) => " + numberToFixed(0.07, 2), |
+ "numberToFixed(0.0000000006, 1) => " + numberToFixed(0.0000000006, 1), |
+ "numberToFixed(0.0000000006, 0) => " + numberToFixed(0.0000000006, 0) |
+].join("\n")); |
+</pre> |
+<ul class='linkList'><li><a href="http://www.merlyn.demon.co.uk/js-round.htm" >http://www.merlyn.demon.co.uk/js-round.htm</a></li> |
+<li><a href="http://msdn.microsoft.com/en-us/library/sstyff0z%28VS.85%29.aspx" >http://msdn.microsoft.com/en-us/library/sstyff0z%28VS.85%29.aspx</a></li> |
+</ul> </div> |
+<div id='binaryNumbers' class='section'><h3 id='FAQ4_7'>6.2 Why does simple decimal arithmetic give strange results?</h3><p> |
+ |
+For example, <code>5 * 1.015</code> does not give exactly |
+<code>5.075</code> and <code>0.06+0.01</code> does |
+not give exactly <code>0.07</code> in javascript. |
+ </p> <p> |
+ |
+ECMAScript numbers are represented in binary as IEEE-754 (IEC 559) |
+Doubles, with a resolution of 53 bits, giving an accuracy of |
+15-16 decimal digits; integers up to just over <code>9e15</code> are |
+precise, but few decimal fractions are. Given this, arithmetic |
+is as exact as possible, but no more. Operations on integers |
+are exact if the true result and all intermediates are integers |
+within that range. |
+ </p> <p> |
+ |
+In particular, non-integer results should not normally be |
+compared for equality; and non-integer computed results |
+commonly need rounding; see <a href="#formatNumber" >How do I format a Number as a String with exactly 2 decimal places?</a></p><ul class='linkList'><li><a href="http://msdn.microsoft.com/en-us/library/7wkd9z69%28VS.85%29.aspx" >http://msdn.microsoft.com/en-us/library/7wkd9z69%28VS.85%29.aspx</a></li> |
+<li><a href="http://www.merlyn.demon.co.uk/js-misc0.htm#DW4" >http://www.merlyn.demon.co.uk/js-misc0.htm#DW4</a></li> |
+</ul> <p> |
+ |
+Otherwise, use <code>Math.round</code> on the results of expressions which |
+should be of integer value. |
+ </p> </div> |
+<div id='parseIntBase' class='section'><h3 id='FAQ4_12'>6.3 Why does K = parseInt('09') set K to 0?</h3><p> |
+ |
+Method <code>parseInt</code> generally needs a second parameter, <code>radix</code>, |
+for the base (from 2 to 36). |
+ </p> <p> |
+ |
+If <code>radix</code> is omitted, the base is determined by the contents of |
+the string. Any string beginning with <code>'0x'</code> or <code>'0X'</code> represents a |
+hexadecimal number. A string beginning with a leading 0 may be parsed as |
+octal (as if <code>raxix</code> were 8), in ECMA-262 Ed 3 (octal digits are <code>0-7</code>). |
+If string <code>'09'</code> is converted to <code>0</code>. |
+ </p> <p> |
+ |
+To force use of a particular base, use the <code>radix</code> |
+parameter: <code>parseInt("09", base)</code>. |
+ |
+ <!-- [omit] |
+ If base 10 is desired, |
+ the unary <ICODE>+</ICODE> operator can be an option. Example: |
+ <ICODE> |
+var s = '-09.1'; // Input string. |
+var j = +s; // Convert to number. Result: -9.1 |
+var n = j|0; // Chop off decimal (convert ToInt32). Result: -9 |
+</ICODE> |
+ [/omit] --></p> <p> |
+ </p><ul class='linkList'><li><a href="http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Functions/parseInt" >http://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Functions/parseInt</a></li> |
+<li><a href="http://msdn.microsoft.com/en-us/library/x53yedee%28VS.85%29.aspx" >http://msdn.microsoft.com/en-us/library/x53yedee%28VS.85%29.aspx</a></li> |
+<li><a href="http://docs.sun.com/source/816-6408-10/toplev.htm#1064173" >http://docs.sun.com/source/816-6408-10/toplev.htm#1064173</a></li> |
+<li><a href="notes/type-conversion/#tcPrIntRx" >notes/type-conversion/#tcPrIntRx</a></li> |
+</ul> </div> |
+<div id='typeConvert' class='section'><h3>6.4 Why does 1+1 equal 11? or How do I convert a string to a number?</h3><p> |
+ |
+Variables are not typed; their values are. The conversion between a |
+string and a number happens automatically. |
+</p> <p> |
+ |
+The addition operator (<code>+</code>) performs concatenation if either operand is a |
+string, thus <code>"1" + 1</code> results <code>"11"</code>. To perform addition, you might need |
+to first convert the string to a number. For example <code>+varname</code> or |
+<code>Number(varname)</code> or <code>parseInt(varname, 10)</code> or |
+<code>parseFloat(varname)</code>. Form control values are strings, as is the result |
+from a <code>prompt</code> dialog. Convert these to numbers before performing |
+addition: <code>+'1' + 1</code> results <code>2</code>. |
+ </p><ul class='linkList'><li> |
+Additional Notes: </li> |
+<li><a href="notes/type-conversion/" >notes/type-conversion/</a></li> |
+<li><a href="http://msdn.microsoft.com/en-us/library/67defydd%28VS.85%29.aspx" >http://msdn.microsoft.com/en-us/library/67defydd%28VS.85%29.aspx</a></li> |
+</ul> </div> |
+<div id='randomNumber' class='section'><h3 id='FAQ4_22'>6.5 How do I generate a random integer from 1 to n?</h3><p> |
+ <code>Math.random()</code> returns a value <code>R</code> such that <code>0 <= R < 1.0</code>; therefore: |
+ </p> |
+<pre> |
+ // positive integer expected |
+ function getRandomNumber(n) { |
+ return Math.floor(n * Math.random()); |
+ } |
+</pre> |
+<p> |
+- gives an evenly distributed random integer in the range from |
+ <code>0</code> to <code>n - 1</code> inclusive; use <code>getRandomNumber(n)+1</code> for <code>1</code> to <code>n</code>. |
+ </p><ul class='linkList'><li><a href="http://msdn.microsoft.com/en-us/library/41336409%28VS.85%29.aspx" >http://msdn.microsoft.com/en-us/library/41336409%28VS.85%29.aspx</a></li> |
+<li><a href="http://docs.sun.com/source/816-6408-10/math.htm" >http://docs.sun.com/source/816-6408-10/math.htm</a></li> |
+<li> |
+How to Deal and Shuffle, see in: </li> |
+<li><a href="http://www.merlyn.demon.co.uk/js-randm.htm" >http://www.merlyn.demon.co.uk/js-randm.htm</a></li> |
+</ul> </div> |
+<div id='objects' class='section'><h2>7 Objects</h2> |
+</div><div id='nativeObject' class='section'><h3>7.1 What is a native object?</h3><p> |
+ |
+A |
+<dfn>native object</dfn> is any object whose semantics are fully defined by |
+ECMA-262. |
+</p> <p> |
+ |
+Some |
+<dfn>native objects</dfn> are |
+<dfn>built-in</dfn>; others, such as |
+<dfn>user-defined</dfn> objects, |
+may be constructed during the execution of an ECMAScript program. |
+</p> <p> |
+ |
+Example: |
+</p> |
+<pre> |
+// Native built-in objects: |
+var m = Math, // Built-in Math object. |
+ slice = Array.prototype.slice, // Built-in native method. |
+ o = {}, // Native user-defined object. |
+ f = function(){}, // Native user-defined function. |
+ d = new Date(), |
+ a = [], |
+ e = new Error("My Message."); |
+ </pre> |
+<p> |
+See also: |
+</p><ul class='linkList'><li><a href="http://dmitrysoshnikov.com/ecmascript/chapter-7-2-oop-ecmascript-implementation/" >http://dmitrysoshnikov.com/ecmascript/chapter-7-2-oop-ecmascript-implementation/</a></li> |
+</ul> </div> |
+<div id='builtInObject' class='section'><h3>7.2 What is a built-in object?</h3><p> |
+ |
+ A |
+<dfn>built-in</dfn> object is any object supplied by an ECMAScript |
+ implementation, independent of the host environment, that is present |
+ at the start of the execution of an ECMAScript program. |
+ </p> <p> |
+ |
+ECMA-262 3rd Edition defines the following |
+<dfn>built-in</dfn> objects: |
+</p> |
+<dl id='builtInsList'> |
+ <dt> Objects </dt> |
+ <dd> <em>global</em>, Math </dd> |
+ <dt> Constructors </dt> |
+ <dd> Object, Function, Array, String, Boolean, Number, Date, RegExp </dd> |
+ <dt> Errors </dt> |
+ <dd> Error, Date, EvalError, RangeError, ReferenceError, SyntaxError, TypeError, URIError </dd> |
+ <dt> Functions </dt> |
+ <dd> eval, parseInt, parseFloat, isNaN, isFinite, decodeURI, |
+ decodeURIComponent, encodeURI, encodeURIComponent </dd></dl><p> |
+ |
+ECMA-262 Edition 5 defines also the built-in object <code>JSON</code>. |
+</p> <p> |
+ |
+Nonstandard |
+<dfn>built-in</dfn> objects may include <code>RuntimeObject</code>, |
+<code>String.prototype.link</code>, <code>CollectGarbage</code>, and more. |
+</p> </div> |
+<div id='hostObject' class='section'><h3 id='FAQ2_8'>7.3 What is a host object?</h3><p> |
+ |
+A |
+<dfn>host object</dfn> is any object supplied by the host environment to |
+complete the execution environment of ECMAScript. |
+</p> <p> |
+ |
+A |
+<dfn>host object</dfn> is not part of the ECMAScript implementation, but is |
+exposed to the ECMAScript implementation. |
+</p> <p> |
+ |
+A |
+<dfn>host object</dfn> may be implemented as a native ECMAScript object, however |
+this is not required. For example, Internet Explorer implements many |
+scriptable DOM objects as ActiveX Objects, often resulting in unexpected errors. |
+</p> <p> |
+ |
+Availability and behavior of a host object depends on the host environment. |
+</p> <p> |
+ |
+For example, in a browser, <code>XMLHttpRequest</code> might be available, with or |
+without standard or proprietary features or events. Windows Script Host object model |
+has the <code>WScript</code> object available. |
+</p> <p> |
+ |
+ For information on a particular host object, consult the pertinent |
+ documentation available for the implementation(s). For web browsers, |
+ this usually includes the w3c specifications as well as documentation |
+ for that browser. |
+ See also: |
+ |
+</p><ul class='linkList'><li><a href="notes/code-guidelines/#hostObjects" >notes/code-guidelines/#hostObjects</a></li> |
+<li><a href="http://peter.michaux.ca/articles/feature-detection-state-of-the-art-browser-scripting" >http://peter.michaux.ca/articles/feature-detection-state-of-the-art-browser-scripting</a></li> |
+</ul> </div> |
+<div id='eval' class='section'><h3 id='FAQ4_40'>7.4 When should I use eval?</h3><p> |
+ |
+The <code>eval</code> function should <em>only</em> be used when it is necessary to |
+evaluate a string supplied or composed at run-time; the string |
+can be anything from a simple (but unpredictable) expression such |
+as <code>"12 * 2.54"</code> to a substantial piece of javascript code. |
+</p> <p> |
+ |
+When <code>eval( '{"key" : 42}' )</code> is called, <code>{</code> is interpreted as a block of |
+code instead of an object literal. Hence, the Grouping Operator (parentheses) |
+is used to force <code>eval</code> to interpret the JSON as an object literal: |
+<code>eval( '({"key" : 42})' );</code>. |
+ </p><ul class='linkList'><li><a href="http://json.org/" >http://json.org/</a></li> |
+<li><a href="#propertyAccessAgain" >How do I access a property of an object using a string?</a></li> |
+<li><a href="notes/square-brackets/" >notes/square-brackets/</a></li> |
+</ul> </div> |
+<div id='propertyAccessAgain' class='section'><h3 id='FAQ4_39'>7.5 How do I access a property of an object using a string?</h3><p> |
+ |
+There are two ways to access properties: dot notation and square bracket |
+notation. What you are looking for is the square bracket notation in |
+which the dot, and the identifier to its right, are replaced with a set |
+of square brackets containing a string. The value of the string matches |
+the identifier. For example:- |
+</p> |
+<pre> |
+ //dot notation |
+ var bodyElement = document.body; |
+ |
+ //square bracket notation, using an expression |
+ var bodyElement = document["bo"+"dy"];</pre> |
+<ul class='linkList'><li><a href="notes/square-brackets/" >notes/square-brackets/</a></li> |
+</ul> </div> |
+<div id='strings' class='section'><h2>8 Strings and RegExp</h2> |
+</div><div id='trimString' class='section'><h3 id='FAQ4_16'>8.1 How do I trim whitespace?</h3><p> |
+ |
+ECMAScript 5 defines <code>String.prototype.trim</code>. Where not supported, |
+it can be added as a function that uses a |
+<dfn>regular expression</dfn>: |
+</p> |
+<pre> |
+if(!String.prototype.trim) { |
+ String.prototype.trim = function() { |
+ return String(this).replace(/^\s+|\s+$/g, ""); |
+ }; |
+} |
+</pre> |
+<p> |
+Implementations are inconsistent with <code>\s</code>. For example, |
+some implementations, notably JScript 5.8 and Safari 2, do not match <code>\xA0</code> |
+(no-break space), among others. |
+ </p> <p> |
+ |
+A more consistent approach would be to create a character class |
+that defines the characters to trim. |
+ </p> <p> |
+ </p><ul class='linkList'><li><a href="https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/RegExp" >https://developer.mozilla.org/en/Core_JavaScript_1.5_Reference/Global_Objects/RegExp</a></li> |
+<li><a href="http://thinkweb2.com/projects/prototype/whitespace-deviations/" >http://thinkweb2.com/projects/prototype/whitespace-deviations/</a></li> |
+<li><a href="https://developer.mozilla.org/en/Firefox_3.1_for_developers" >https://developer.mozilla.org/en/Firefox_3.1_for_developers</a></li> |
+<li><a href="http://docs.sun.com/source/816-6408-10/regexp.htm" >http://docs.sun.com/source/816-6408-10/regexp.htm</a></li> |
+<li><a href="http://msdn.microsoft.com/en-us/library/6wzad2b2%28VS.85%29.aspx" >http://msdn.microsoft.com/en-us/library/6wzad2b2%28VS.85%29.aspx</a></li> |
+<li><a href="http://groups.google.com/group/comp.lang.javascript/browse_frm/thread/c7010139217600c3/31092c5eb99625d0?#31092c5eb99625d0" >http://groups.google.com/group/comp.lang.javascript/browse_frm/thread/c7010139217600c3/31092c5eb99625d0?#31092c5eb99625d0</a></li> |
+<li><a href="http://unicode.org/Public/UNIDATA/PropList.txt" >http://unicode.org/Public/UNIDATA/PropList.txt</a></li> |
+</ul> </div> |
+<div id='domRef' class='section'><h2>9 DOM and Forms</h2> |
+</div><div id='formControlAccess' class='section'><h3 id='FAQ4_13'>9.1 How do I get the value of a form control?</h3><p> |
+ |
+In HTML documents, a form may be referred to as a property of the |
+<code>document.forms</code> collection, either by its ordinal index or by name |
+(if the <code>form</code> has a name). A <code>form</code>'s controls may be similarly referenced |
+from its <code>elements</code> collection: |
+</p> |
+<pre> |
+ var frm = document.forms[0]; |
+ var control = frm.elements["elementname"]; |
+</pre> |
+<p> |
+Once a reference to a control is obtained, its (string) <code>value</code> |
+property can be read:- |
+</p> |
+<pre> |
+ var value = control.value; |
+ value = +control.value; //string to number. |
+</pre> |
+<p> |
+Some exceptions would be: |
+</p> <p> |
+ |
+First Exception: Where the control is a <code>SELECT</code> element, and |
+support for older browsers, such as NN4, is required: |
+</p> |
+<pre> |
+ var value = control.options[control.selectedIndex].value; |
+</pre> |
+<p> |
+Second Exception: Where several controls share the same name, |
+such as radio buttons. These are made available as collections |
+and require additional handling. For more information, see:- |
+</p><ul class='linkList'><li><a href="notes/form-access/" >notes/form-access/</a></li> |
+<li><a href="names/" >Unsafe Names for HTML Form Controls</a></li> |
+</ul> <p> |
+ |
+Third Exception: File inputs. Most current browsers do not allow |
+reading of <code>type="file"</code> input elements in a way that is useful. |
+ </p> </div> |
+<div id='propertyAccess' class='section'><h3 id='FAQ4_25'>9.2 My element is named myselect[], how do I access it?</h3><p> |
+ |
+Form controls with any "illegal" characters can be accessed with |
+<code>formref.elements["myselect[]"]</code> - The bracket characters, |
+amongst others, are illegal in ID attributes and javascript |
+identifiers, so you should try to avoid them as browsers may |
+handle them incorrectly. |
+</p><ul class='linkList'><li><a href="http://msdn.microsoft.com/en-us/library/ms537449%28VS.85%29.aspx" >http://msdn.microsoft.com/en-us/library/ms537449%28VS.85%29.aspx</a></li> |
+<li><a href="https://developer.mozilla.org/en/DOM/form" >https://developer.mozilla.org/en/DOM/form</a></li> |
+<li><a href="notes/form-access/" >notes/form-access/</a></li> |
+</ul> </div> |
+<div id='globalPollution' class='section'><h3 id='FAQ4_41'>9.3 Why doesn't the global variable "divId" always refer to the element with id="divId"?</h3><p> |
+ |
+Microsoft introduced a shortcut that can be used to reference |
+elements which include an <code>id</code> attribute where the |
+<code>id</code> becomes a globally-accessible property. Some browsers reproduce |
+this behavior. Some, most notably Gecko-based browsers (Netscape and Mozilla), |
+do so only in "quirks" mode. The best approach is the <code>document.getElementById</code> |
+method, which is part of the W3C DOM standard and implemented |
+in modern browsers (including IE from version 5.0). So an |
+element with <code>id="foo"</code> can be referenced |
+with:- |
+ </p> |
+<pre> |
+ var el = document.getElementById("foo"); |
+</pre> |
+<p> |
+Note: make sure not to use the same <code>id</code> twice in the same document |
+and do not give an element a <code>name</code> that matches an <code>id</code> |
+of another in the same document or it will trigger bugs in MSIE <= 7 with |
+<code>document.getElementsByName</code> and <code>document.getElementById</code>. |
+</p><ul class='linkList'><li><a href="https://developer.mozilla.org/en/Using_Web_Standards_in_your_Web_Pages/Using_the_W3C_DOM#Accessing_Elements_with_the_W3C_DOM |
+" >https://developer.mozilla.org/en/Using_Web_Standards_in_your_Web_Pages/Using_the_W3C_DOM#Accessing_Elements_with_the_W3C_DOM |
+</a></li> |
+<li><a href="faq_notes/faq_notes.html#FAQN4_41" >faq_notes/faq_notes.html#FAQN4_41</a></li> |
+</ul> </div> |
+<div id='updateContent' class='section'><h3 id='FAQ4_15'>9.4 How do I modify the content of the current page?</h3><p> |
+ |
+Using the non-standard but widely implemented |
+<code>innerHTML</code> property: |
+<code><div id="anID">Some Content</div></code> with script: |
+ </p> |
+<pre> |
+ document.getElementById("anID").innerHTML = |
+ "Some <em>new</em> Content"; |
+</pre> |
+<p> |
+Where <code>"anID"</code> is the (unique on the HTML page) |
+<code>id</code> attribute value of the element to modify. |
+ </p> <p> |
+ |
+All versions of Internet Explorer exhibit problems with innerHTML, including: |
+ </p> |
+<ul> |
+ <li> Fails with FRAMESET, HEAD, HTML, STYLE, SELECT, |
+OBJECT, and all TABLE-related elements. |
+ </li> |
+ <li> Replaces consecutive whitespace characters with a single space. </li> |
+ <li> Changes attribute values and order of appearance. </li> |
+ <li> Removes quotations around attribute values. </li></ul><p> |
+ |
+If the new content is only text and does not need to replace existing HTML, |
+it is more efficient to modify the <code>data</code> property of a text node. |
+ </p> |
+<pre> |
+ document.getElementById("anID").firstChild.data = "Some new Text"; |
+</pre> |
+ <p> |
+ |
+Compatibility Note: Implementations have been known to split long text |
+content among several adjacent text nodes, so replacing the data of the |
+first text node may not replace all the element's text. The <code>normalize</code> |
+method, where supported, will combine adjacent text nodes. |
+</p> <p> |
+ |
+Note: Make sure the element exists in the document (has been parsed) before trying to |
+reference it. |
+ </p><ul class='linkList'><li><a href="http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-FF21A306" >http://www.w3.org/TR/DOM-Level-2-Core/core.html#ID-FF21A306</a></li> |
+<li><a href="http://msdn.microsoft.com/en-us/library/cc304097%28VS.85%29.aspx" >http://msdn.microsoft.com/en-us/library/cc304097%28VS.85%29.aspx</a></li> |
+<li><a href="http://msdn.microsoft.com/en-us/library/ms533897%28VS.85%29.aspx" >http://msdn.microsoft.com/en-us/library/ms533897%28VS.85%29.aspx</a></li> |
+<li><a href="http://developer.mozilla.org/en/Whitespace_in_the_DOM" >http://developer.mozilla.org/en/Whitespace_in_the_DOM</a></li> |
+<li><a href="http://developer.mozilla.org/en/docs/DOM:element.innerHTML" >http://developer.mozilla.org/en/docs/DOM:element.innerHTML</a></li> |
+<li><a href="http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#html-fragment-serialization-algorithm" >http://www.whatwg.org/specs/web-apps/current-work/multipage/the-end.html#html-fragment-serialization-algorithm</a></li> |
+<li> (draft) |
+ </li> |
+</ul> </div> |
+<div id='accessElementBeforeDefined' class='section'><h3>9.5 Why does my code fail to access an element?</h3><p> |
+ |
+An element can only be accessed after it exists in the document. |
+ </p> <p> |
+ |
+Either: |
+A) include your script after the HTML element it refers to, or |
+B) use the <code>"load"</code> event to trigger your script. |
+ </p> <p> |
+ |
+Example A: |
+</p> |
+<pre> |
+<div id="snurgle">here</div> |
+<script type="text/javascript"> |
+// Don't forget var. |
+var snurgleEl = document.getElementById("snurgle"); |
+window.alert(snurgleEl.parentNode); |
+</script> |
+</pre> |
+ <p> |
+ |
+Example B: |
+</p> |
+<pre> |
+// In the HEAD. |
+<script type="text/javascript"> |
+window.onload = function(){ |
+ var snurgleEl = document.getElementById("snurgle"); |
+}; |
+</script> |
+</pre> |
+ |
+<h4>Other problems can include:</h4> |
+ |
+<ul> |
+ <li> invalid HTML </li> |
+ <li> two elements with the same <code>name</code> or <code>id</code> </li> |
+ <li> use of an unsafe name: http://jibbering.com/names/ </li></ul></div> |
+<div id='testCookie' class='section'><h3 id='FAQ4_4'>9.6 How can I see in javascript if a web browser accepts cookies?</h3><p> |
+ |
+Write a cookie and read it back and check if it's the same. |
+ </p><ul class='linkList'><li> |
+Additional Notes: |
+</li> |
+<li><a href="http://www.ietf.org/rfc/rfc2965.txt" >http://www.ietf.org/rfc/rfc2965.txt</a></li> |
+<li><a href="http://www.galasoft-lb.ch/myjavascript/consulting/2001012701/" >http://www.galasoft-lb.ch/myjavascript/consulting/2001012701/</a></li> |
+<li><a href="http://www.cookiecentral.com/" >http://www.cookiecentral.com/</a></li> |
+</ul> </div> |
+<div id='windows' class='section'><h2>10 Windows and Frames</h2> |
+<p> |
+ |
+The <code>window</code> object (also referred to by <code>self</code>) is "DOM Level 0". |
+No formal standard for it exists. |
+</p> </div><div id='disableBackButton' class='section'><h3 id='FAQ4_2'>10.1 How can I disable the back button in a web browser?</h3><p> |
+ |
+You can't. The browser's history cannot be modified. However, you |
+can use <code>self.location.replace(url);</code> in some browsers to replace |
+the current page in the history. |
+ </p><ul class='linkList'><li><a href="http://msdn.microsoft.com/en-us/library/ms536712%28VS.85%29.aspx" >http://msdn.microsoft.com/en-us/library/ms536712%28VS.85%29.aspx</a></li> |
+<li><a href="http://docs.sun.com/source/816-6408-10/location.htm#1194240" >http://docs.sun.com/source/816-6408-10/location.htm#1194240</a></li> |
+</ul> </div> |
+<div id='frameRef' class='section'><h3 id='FAQ4_8'>10.2 How do I access a frame's content?</h3><p> |
+ |
+To reference another frame on the <em>same domain</em>: |
+</p> <p> |
+ |
+The |
+<dfn>content window</dfn> of a <code>FRAME</code> or <code>IFRAME</code> can be |
+accessed by the <code>frames</code> collection. |
+</p> <p> |
+ |
+Example: |
+</p> |
+<pre> |
+var fwin; |
+fwin = self.frames[0]; // or: |
+fwin = self.frames["iframeName"]; |
+</pre> |
+ <p> |
+ or, from the <code>IFRAME</code> or <code>FRAME</code> element: |
+</p> |
+<pre> |
+var iframeEl = document.getElementById("myFrame"); |
+var fwin = iframeEl.contentWindow; // Nonstandard, but widely supported. |
+var fdoc = iframeEl.contentDocument; // DOM2 HTML Standard. |
+</pre> |
+ <p> |
+ |
+A global identifier <code>moomin</code> in the the iframe's |
+<dfn>content window</dfn> |
+is accessed as <code>fwin.moomin</code>. |
+ </p> <p> |
+ |
+To communicate between frames on <em>different</em> domains: |
+</p> <p> |
+ |
+Where supported, (IE8, Firefox 3, Opera 9, Safari 4), use |
+<code>window.postMessage( message[, port], otherDomain);</code>. |
+</p> <p> |
+ |
+Example: |
+<a href="http://jibbering.com/faq/example/postMessage.html" >http://jibbering.com/faq/example/postMessage.html</a></p> <p> |
+ |
+Where <code>window.postMessage</code> is not supported, the <code>window.name</code> property |
+can be set on the other window, which can poll for updates to that |
+property using <code>setInterval(checkWinName, 100);</code> where <code>checkWinName</code> |
+is a function that polls to check the value of |
+<code>self.name</code>. |
+</p><ul class='linkList'><li><a href="http://en.wikipedia.org/wiki/Same_origin_policy" >http://en.wikipedia.org/wiki/Same_origin_policy</a></li> |
+<li><a href="http://www-archive.mozilla.org/docs/dom/domref/dom_frame_ref5.html" >http://www-archive.mozilla.org/docs/dom/domref/dom_frame_ref5.html</a></li> |
+<li><a href="https://developer.mozilla.org/en/DOM/window.postMessage" >https://developer.mozilla.org/en/DOM/window.postMessage</a></li> |
+<li><a href="http://msdn.microsoft.com/en-us/library/cc197015(VS.85).aspx" >http://msdn.microsoft.com/en-us/library/cc197015(VS.85).aspx</a></li> |
+</ul> </div> |
+<div id='getWindowSize' class='section'><h3 id='FAQ4_9'>10.3 How do I find the size of the window?</h3><p> |
+ |
+Here is a detailed explanation of a cross-browser strategy to |
+find the dimensions of the viewport, excepting all chrome |
+(excludes scrollbars, etc). |
+ </p> <p> |
+ |
+We can consider various properties: |
+ </p> |
+<pre> |
+ window.innerWidth |
+ document.clientWidth |
+ document.documentElement.clientWidth |
+ document.body.clientWidth |
+</pre> |
+<p> |
+ |
+Of the browsers that have an <code>innerWidth</code> property, most |
+include scrollbar dimensions. Some versions of KHTML browsers |
+(including Safari 2) do <em>not</em> include scrollbar width. |
+ </p> <p> |
+ |
+The <code>window.inner*</code> properties are unreliable and not |
+useful here. We don't want scrollbar dimensions included. |
+</p> |
+<pre> document.clientWidth</pre> |
+ <p> |
+ |
+Certain versions of KHTML, including Safari 2, have |
+<code>document.clientHeight</code> and <code>document.clientWidth</code> |
+properties. Where supported, these rare properties accurately |
+return the height and width of the viewport, without including |
+scrollbar dimensions. |
+ </p> |
+<pre> |
+ document.documentElement.clientWidth |
+ document.body.clientWidth |
+</pre> |
+<p> |
+MSHTML (Trident), Firefox (Gecko), Opera (Presto), and Safari |
+(Webkit) all support <code>clientHeight</code> on <code>document.body</code> |
+and <code>document.documentElement</code>. The difficulty is figuring out |
+which one is reliable. In other words which object to get the |
+<code>clientHeight</code> property from:<code>documentElement</code> or <code>body</code>? |
+ </p> <p> |
+ |
+What the number returned from either of these properties |
+represents depends on the environment. The environment includes |
+the browser, its version, and the rendering mode of the document. |
+In quirks mode, we'll mostly want to use <code>body.clientHeight</code> |
+(except for in Safari 2). |
+ |
+ </p> |
+<pre> document.body.clientHeight</pre> |
+<p> |
+ |
+Some environments will return the viewport height. Others will |
+return <code>0</code>. Yet others will return the <code>clientHeight</code> of |
+the <code>BODY</code> element. |
+ |
+ </p> |
+<pre> document.documentElement.clientHeight</pre> |
+<p> |
+ |
+This is the more "standard" property for getting the height of |
+the viewport. It usually "works" in modern browsers in |
+ |
+<dfn>standards mode</dfn>. Notable exceptions include Safari 2 and |
+Opera <= 9.25, both of which return the <code>clientHeight</code> |
+of the <code>html</code> <em>element</em>. (Oddly, Opera <= 9.25 |
+in standards mode returns the width of the viewport for |
+<code>documentElement.clientWidth</code>). |
+ </p> <p> |
+ |
+With the exception of Safari 2, <code>body.clientHeight</code> is reliable |
+where <code>documentElement.clientHeight</code> is found to be unreliable. |
+For example, in Safari 3+, Opera, and Mozilla, all in quirks mode, |
+<code>document.documentElement.clientHeight</code> returns the <code>clientHeight</code> |
+of the <code>html</code> element (this may seem unsurprising but |
+it is not what we want). |
+ </p> <p> |
+ |
+Conversely, <code>document.body.clientHeight</code> will return |
+the height of the viewport in most cases where |
+<code>document.documentElement.clientHeight</code> does not. An exception |
+to that is Safari 2, where <code>documentElement.clientHeight</code> |
+and <code>body.clientHeight</code> both return the height of their |
+corresponding element (not what we want). |
+ </p> <p> |
+ |
+By using a combination of |
+<dfn>Feature Testing</dfn> and |
+<dfn>Capability Testing</dfn>, |
+the dimensions of the viewport can be strategically retrieved |
+from the property that works in the environment the script is |
+running in. The trick is determining which property will give us |
+the value we want. |
+ </p> <p> |
+ |
+Since <code>document.clientHeight</code> is reliable where |
+(rarely) supported, and since browsers that support this property |
+don't return the viewport dimensions from |
+<code>document.body.clientHeight</code> or |
+<code>document.documentElement.clientHeight</code>, this should be the |
+very first condition: |
+ |
+ </p> |
+<pre> |
+ // Safari 2 uses document.clientWidth (default). |
+ if(typeof document.clientWidth == "number") { |
+ // use document.clientWidth. |
+ } |
+</pre> |
+<p> |
+ |
+The next strategy is to determine if |
+<code>document.documentElement.clientHeight</code> property is unreliable. |
+It is deemed "unreliable" when it is either <code>0</code> or taller |
+than the viewport. |
+ </p> <p> |
+ |
+ Determining if <code>documentElement.clientHeight</code> is <code>0</code> is easy. |
+ The result is stored in a variable <code>IS_BODY_ACTING_ROOT</code>. |
+ |
+ </p> |
+<pre> |
+ var docEl = document.documentElement, |
+ IS_BODY_ACTING_ROOT = docEl && docEl.clientHeight === 0; |
+ docEl = null; |
+</pre> |
+<p> |
+ |
+To determine if <code>documentElement.clientHeight</code> returns |
+a value taller than the viewport, we need a |
+<dfn>Capability Test.</dfn></p> <p> |
+ |
+If we can force <code>documentElement</code> to be very tall |
+(taller than a normal viewport) we can then check to see if |
+<code>documentElement.clientHeight</code> returns that "very tall" number. |
+If it does, then it is unreliable. |
+ </p> <p> |
+ |
+We can force <code>documentElement</code> to be taller than the viewport |
+(or any "normal" viewport) by adding a <code>div</code> to the <code>body</code>, |
+give that <code>div</code> a height larger than any normal monitor, |
+and then check to see if <code>documentElement.clientHeight</code> is |
+that high (or "almost" that high, to account for <code>documentElement</code> |
+having a border). |
+ |
+ </p> |
+<pre> |
+ // Used to feature test Opera returning wrong values |
+ // for documentElement.clientHeight. |
+ // The results of this function should be cached, |
+ // so it does not need to be called more than once. |
+ function isDocumentElementHeightOff(){ |
+ var d = document, |
+ div = d.createElement('div'); |
+ div.style.height = "2500px"; |
+ d.body.insertBefore(div, d.body.firstChild); |
+ var r = d.documentElement.clientHeight > 2400; |
+ d.body.removeChild(div); |
+ return r; |
+ } |
+</pre> |
+<p> |
+ |
+We can use this function to see if we should use |
+<code>body.clientHeight</code>, instead. (but only after checking if |
+<code>document.clientHeight</code> is supported). |
+ |
+ </p> |
+<pre> |
+ // Safari 2 uses document.clientWidth (default). |
+ if(typeof document.clientWidth == "number") { |
+ // use document.clientHeight/Width. |
+ } |
+ else if(IS_BODY_ACTING_ROOT || isDocumentElementHeightOff()) { |
+ // use document.body.clientHeight/Width. |
+ } else { |
+ // use document.documentElement.clientHeight/Width. |
+ } |
+</pre> |
+<p> |
+The preceding strategy was developed by Garrett Smith with input |
+from John David Dalton. A complete and tested example can be found |
+in APE Library under <code>APE.dom.getViewportDimensions</code>. |
+Source code: |
+<a href="http://dhtmlkitchen.com/ape/build/dom/viewport-f.js" >http://dhtmlkitchen.com/ape/build/dom/viewport-f.js</a>. |
+APE is publicly released under Academic Free License. |
+APE home: <a href="http://dhtmlkitchen.com/ape/" >http://dhtmlkitchen.com/ape/</a>. |
+ </p> <p> |
+ |
+Note: The dimensions cannot be determined accurately until after |
+the document has finished loading. |
+</p><ul class='linkList'><li><a href="http://msdn.microsoft.com/en-us/library/ms533566%28VS.85%29.aspx" >http://msdn.microsoft.com/en-us/library/ms533566%28VS.85%29.aspx</a></li> |
+<li><a href="http://developer.mozilla.org/en/DOM/window.innerWidth" >http://developer.mozilla.org/en/DOM/window.innerWidth</a></li> |
+<li><a href="http://dev.opera.com/articles/view/using-capability-detection/" >http://dev.opera.com/articles/view/using-capability-detection/</a></li> |
+</ul> </div> |
+<div id='isWindowOpen' class='section'><h3 id='FAQ4_10'>10.4 How do I check to see if a child window is open, before opening another?</h3><p> |
+ </p> |
+<pre> |
+ var myWin; |
+ function openWin(aURL) { |
+ if (!myWin || myWin.closed ) { |
+ myWin = window.open(aURL,'myWin'); |
+ } else { |
+ myWin.location.href = aURL; |
+ myWin.focus(); |
+ } |
+ }</pre> |
+<p> |
+Popup windows cause usability problems and are generally best avoided. |
+</p><ul class='linkList'><li><a href="https://developer.mozilla.org/en/DOM:window.open" >https://developer.mozilla.org/en/DOM:window.open</a></li> |
+<li><a href="http://msdn.microsoft.com/en-us/library/ms533574%28VS.85%29.aspx" >http://msdn.microsoft.com/en-us/library/ms533574%28VS.85%29.aspx</a></li> |
+<li><a href="http://docs.sun.com/source/816-6408-10/window.htm#1201877" >http://docs.sun.com/source/816-6408-10/window.htm#1201877</a></li> |
+<li><a href="http://www.useit.com/alertbox/990530.html" >http://www.useit.com/alertbox/990530.html</a></li> |
+</ul> </div> |
+<div id='printFrame' class='section'><h3 id='FAQ4_11'>10.5 Why does framename.print() not print the correct frame in IE?</h3><p> |
+ |
+IE prints the frame that has focus when you call the print |
+method <code>frameref.focus();frameref.print();</code></p><ul class='linkList'><li><a href="http://msdn.microsoft.com/en-us/library/ms976105.aspx" >http://msdn.microsoft.com/en-us/library/ms976105.aspx</a></li> |
+</ul> </div> |
+<div id='windowClose' class='section'><h3 id='FAQ4_14'>10.6 How do I close a window and why does it not work on the first one?</h3><p> |
+ |
+If a window was opened by javascript, then it can be closed |
+without confirmation by using <code>windowRef.close()</code>. |
+</p> <p> |
+ |
+Before calling <code>windowRef.close()</code> (or other <code>window</code> methods), make |
+sure the window reference is not null and its <code>closed</code> property is <code>false</code>. |
+</p> <p> |
+ |
+Popup windows cause usability problems and are generally best avoided. |
+</p> <p> |
+ </p><ul class='linkList'><li><a href="http://www.useit.com/alertbox/990530.html" >http://www.useit.com/alertbox/990530.html</a></li> |
+<li><a href="#isWindowOpen " >#isWindowOpen </a></li> |
+<li><a href="http://msdn.microsoft.com/en-us/library/ms536367%28VS.85%29.aspx" >http://msdn.microsoft.com/en-us/library/ms536367%28VS.85%29.aspx</a></li> |
+<li><a href="https://developer.mozilla.org/en/DOM/window.close#Description" >https://developer.mozilla.org/en/DOM/window.close#Description</a></li> |
+<li><a href="http://docs.sun.com/source/816-6408-10/window.htm#1201822" >http://docs.sun.com/source/816-6408-10/window.htm#1201822</a></li> |
+</ul> </div> |
+<div id='permissionDenied' class='section'><h3 id='FAQ4_19'>10.7 Why do I get permission denied when accessing a frame/window?</h3><p> |
+ |
+In the normal browser security model, a script may only access the |
+properties of documents served from the same domain or IP address, |
+protocol, and port. |
+ </p> <p> |
+ |
+Any attempt to access a property in such cases will result in a "Permission |
+Denied" error. Signed scripts or trusted ActiveX objects can |
+overcome this in limited situations. |
+</p><ul class='linkList'><li><a href="http://msdn.microsoft.com/en-us/library/ms533028%28VS.85%29.aspx" >http://msdn.microsoft.com/en-us/library/ms533028%28VS.85%29.aspx</a></li> |
+<li><a href="https://developer.mozilla.org/En/Same_origin_policy_for_JavaScript" >https://developer.mozilla.org/En/Same_origin_policy_for_JavaScript</a></li> |
+</ul> </div> |
+<div id='setTimeout' class='section'><h3 id='FAQ4_20'>10.8 How do I make a 10 second delay?</h3><p> |
+ |
+There is no built-in way to pause execution in javascript such |
+as a sleep function, but hosts usually provide a method of some |
+form. Web browsers are designed for event driven programming and |
+only provide the <code>setTimeout</code> and <code>setInterval</code> functions |
+to facilitate timed delays. The delay before calling <code>getSnork</code> may |
+exceed the second parameter to <code>setTimeout</code> and <code>setInterval</code> |
+due to implementation differences among browsers. |
+ </p> <p> |
+ |
+ To call the function <code>getSnork</code>, approximately 10 seconds |
+ after the function <code>getMoomin()</code> completes, you would do this: |
+ </p> |
+<pre> |
+ getMoomin(); |
+ setTimeout(getSnork, 10000); |
+</pre> |
+<p> |
+Script execution is not stopped, and adding <code>getSnufkin()</code> after the |
+<code>setTimeout</code> line would immediately execute the function <code>getSnufkin</code> |
+before <code>getSnork</code>. |
+ </p> <p> |
+ |
+Achieving delays through running a loop of some sort for a pre-defined |
+period is a bad strategy, as that will inhibit whatever was supposed to |
+be happening during the delay, including blocking user interation. |
+ </p> <p> |
+ |
+Other (less event driven) hosts have different wait functions, |
+such as <code>WScript.Sleep()</code> in the Windows Script Host. |
+</p><ul class='linkList'><li><a href="http://msdn.microsoft.com/en-us/library/ms536753%28VS.85%29.aspx" >http://msdn.microsoft.com/en-us/library/ms536753%28VS.85%29.aspx</a></li> |
+<li><a href="http://docs.sun.com/source/816-6408-10/window.htm#1203758" >http://docs.sun.com/source/816-6408-10/window.htm#1203758</a></li> |
+<li><a href="http://en.wikipedia.org/wiki/Event-driven_programming" >http://en.wikipedia.org/wiki/Event-driven_programming</a></li> |
+<li><a href="faq_notes/misc.html#mtSetTI" >faq_notes/misc.html#mtSetTI</a></li> |
+</ul> </div> |
+<div id='printSettings' class='section'><h3 id='FAQ4_23'>10.9 How do I change print settings for window.print()?</h3><p> |
+ |
+In a normal security environment, you can't change anything. |
+</p> <p> |
+ |
+Print Stylesheet rules provide options. |
+</p> <p> |
+ For IE, <code>ActiveX</code> or Plugin ScriptX and |
+Neptune from Meadroid to give you more control for Windows |
+versions of Internet Explorer, Netscape, and Opera. |
+</p><ul class='linkList'><li><a href="http://www.meadroid.com/scriptx/" >http://www.meadroid.com/scriptx/</a></li> |
+<li><a href="http://msdn.microsoft.com/en-us/library/ms976105.aspx" >http://msdn.microsoft.com/en-us/library/ms976105.aspx</a></li> |
+</ul> </div> |
+<div id='changeBrowserDialog' class='section'><h3 id='FAQ4_28'>10.10 How do I change the confirm box to say yes/no or default to cancel?</h3><p> |
+ |
+The buttons on a confirm box cannot be changed, nor can a default |
+button be specified. |
+ </p> <p> |
+ |
+Change the question to a statement so that "OK" is suitable as the |
+default response. |
+</p> <p> |
+ |
+ Example: |
+ "Would you like us to charge your credit card?" (wrong) |
+ "We will now charge your credit card." (right). |
+</p> </div> |
+<div id='fileDownload' class='section'><h3 id='FAQ4_33'>10.11 How do I prompt a "Save As" dialog for an accepted mime type?</h3><p> |
+ |
+It is not possible with client-side javascript. |
+ </p> <p> |
+ |
+Some browsers accept the Content-Disposition header, but this |
+must be added by the server. Taking the form:- |
+<code>Content-Disposition: attachment; filename=filename.ext</code></p><ul class='linkList'><li><a href="http://classicasp.aspfaq.com/general/how-do-i-prompt-a-save-as-dialog-for-an-accepted-mime-type.html" >http://classicasp.aspfaq.com/general/how-do-i-prompt-a-save-as-dialog-for-an-accepted-mime-type.html</a></li> |
+<li><a href="http://support.microsoft.com/kb/q260519/" >http://support.microsoft.com/kb/q260519/</a></li> |
+</ul> </div> |
+<div id='modifyChrome' class='section'><h3 id='FAQ4_36'>10.12 How do I modify the current browser window?</h3><p> |
+ |
+In a default security environment you are very limited in how much |
+you can modify the current browser window. You can use |
+<code>window.resizeTo</code> or <code>window.moveTo</code> to resize or move a |
+window respectively, but that is it. Normally you can only |
+suggest chrome changes in a <code>window.open</code>. |
+</p><ul class='linkList'><li><a href="http://msdn.microsoft.com/en-us/library/ms536651%28VS.85%29.aspx" >http://msdn.microsoft.com/en-us/library/ms536651%28VS.85%29.aspx</a></li> |
+<li><a href="https://developer.mozilla.org/en/DOM:window.open" >https://developer.mozilla.org/en/DOM:window.open</a></li> |
+</ul> </div> |
+<div id='target' class='section'><h3 id='FAQ4_37'>10.13 How do I POST a form to a new window?</h3><p> |
+ |
+Use the target attribute on the form, opening a window with |
+that name and your feature string in the onsubmit handler of the |
+FORM. |
+ </p> |
+<pre> |
+ <form action="" method="post" |
+ target="wndname" onsubmit="window.open('',this.target);return true;"></pre> |
+<ul class='linkList'><li><a href="http://www.htmlhelp.com/reference/html40/forms/form.html" >http://www.htmlhelp.com/reference/html40/forms/form.html</a></li> |
+</ul> </div> |
+<div id='openWindow' class='section'><h3 id='FAQ4_42'>10.14 How do I open a new window with javascript?</h3><p> |
+ |
+New windows can be opened on browsers that support the |
+<code>window.open</code> function and are not subject to the action of any |
+pop-up blocking mechanism with code such as:- |
+ </p> |
+<pre> |
+ var wRef; |
+ if(window.open){ |
+ wRef = window.open("http://example.com/page.html","windowName"); |
+ }</pre> |
+<ul class='linkList'><li><a href="https://developer.mozilla.org/en/DOM:window.open" >https://developer.mozilla.org/en/DOM:window.open</a></li> |
+<li><a href="http://www.infimum.dk/HTML/JSwindows.html" >http://www.infimum.dk/HTML/JSwindows.html</a></li> |
+</ul> </div> |
+<div id='ajaxRef' class='section'><h2>11 Ajax and Server Communication</h2> |
+</div><div id='ajax' class='section'><h3 id='FAQ4_44'>11.1 What is Ajax?</h3><p> |
+ |
+<dfn title = 'Asynchronous JavaScript and XML'>Ajax</dfn> |
+is shorthand for Asynchronous JavaScript and XML. The technology is |
+based on the <code>XMLHttpRequest</code> Object. At its simplest, |
+it is the sending/retrieving of new data from the server without |
+changing or reloading the window location. |
+</p><ul class='linkList'><li> |
+Mozilla Documentation: |
+</li> |
+<li><a href="http://developer.mozilla.org/en/docs/XMLHttpRequest" >http://developer.mozilla.org/en/docs/XMLHttpRequest</a></li> |
+<li> |
+MSDN Documention: |
+</li> |
+<li><a href="http://msdn.microsoft.com/en-us/library/ms535874%28VS.85%29.aspx" >http://msdn.microsoft.com/en-us/library/ms535874%28VS.85%29.aspx</a></li> |
+<li><a href="http://msdn.microsoft.com/en-us/library/ms759148%28VS.85%29.aspx" >http://msdn.microsoft.com/en-us/library/ms759148%28VS.85%29.aspx</a></li> |
+<li> |
+Libraries and Tutorial Sites: |
+</li> |
+<li><a href="http://jibbering.com/2002/4/httprequest.html" >http://jibbering.com/2002/4/httprequest.html</a></li> |
+<li><a href="http://www.ajaxtoolbox.com/" >http://www.ajaxtoolbox.com/</a></li> |
+</ul> </div> |
+<div id='downloadPage' class='section'><h3 id='FAQ4_38'>11.2 How do I download a page to a variable?</h3><p> |
+ |
+Although <code>XMLHttpRequest</code> can be used to download |
+entire pages, it is often used for downloading small pieces |
+of data that can be used to update the current page. |
+ </p><ul class='linkList'><li><a href="http://jibbering.com/2002/4/httprequest.html" >http://jibbering.com/2002/4/httprequest.html</a></li> |
+<li><a href="http://www.ajaxtoolbox.com/" >http://www.ajaxtoolbox.com/</a></li> |
+</ul> </div> |
+<div id='getServerVariable' class='section'><h3 id='FAQ4_18'>11.3 How do I get a jsp/php variable into client-side javascript?</h3><p> |
+ |
+Use a server-side language to generate the javascript. |
+</p> <p> |
+ |
+Certain characters of ECMAScript strings must be escaped by backslash. |
+These include quote marks, backslash, and line terminators. |
+</p> <p> |
+ JSP Example, using Apache Commons: <code>org.apache.commons.lang.StringEscapeUtils</code>: |
+ </p> |
+<pre> |
+var jsVar = "<%= StringEscapeUtils.escapeJavaScript(str) %>"; |
+</pre> |
+ <p> |
+ PHP example using <code>addcslashes</code>: |
+</p> |
+<pre> |
+var jsVar = "<?php echo addcslashes($str,"\\\'\"\n\r"); ?>"; |
+</pre> |
+<ul class='linkList'><li><a href="example/addcslashes.php" >example/addcslashes.php</a></li> |
+<li><a href="http://php.net/manual/en/function.addcslashes.php" >http://php.net/manual/en/function.addcslashes.php</a></li> |
+<li><a href="http://commons.apache.org/lang/" >http://commons.apache.org/lang/</a></li> |
+</ul> </div> |
+<div id='sessionExpired' class='section'><h3 id='FAQ4_29'>11.4 How do I log-out a user when they leave my site?</h3><p> |
+ |
+This cannot be done reliably. Here's why: |
+ </p> |
+<ul> <li> |
+The user may disable javascript so the log-out script will |
+never execute. |
+ </li> |
+<li> |
+The user may not be on-line when they close your web page. |
+ </li> |
+<li> |
+Javascript errors elsewhere in the page may prevent the script |
+executing. |
+ </li> |
+<li> |
+The browser may not support the onunload event, or may not fire |
+it under certain circumstances, so the log-out function will |
+not execute. |
+ </li> |
+</ul> |
+<p> |
+The URL below has more information. |
+</p><ul class='linkList'><li><a href="http://groups.google.com/groups?selm=BlmZ7.55691%244x4.7344316%40news2-win.server.ntlworld.com" >http://groups.google.com/groups?selm=BlmZ7.55691%244x4.7344316%40news2-win.server.ntlworld.com</a></li> |
+</ul> </div> |
+<div id='runServerScript' class='section'><h3 id='FAQ4_34'>11.5 How do I run a server side script?</h3><p> |
+ |
+You trigger a server-side script by sending an HTTP request. |
+This can be achieved by setting the <code>src</code> of an <code>img</code>, |
+<code>Image</code>, <code>frame</code>, or <code>iframe</code>, or by using |
+<dfn title = 'XMLHttpRequest or XMLHTTP'>XHR</dfn>, where supported. |
+ </p> <p> |
+ |
+An image will also |
+"swallow" the data sent back by the server, so that they will |
+not be visible anywhere. |
+</p> <p> |
+ </p> |
+<pre> |
+ var dummyImage = new Image(); |
+ dummyImage.src = "scriptURL.asp?param=" + varName; |
+</pre> |
+ <p> |
+ |
+Mozilla, Opera 7.6+, Safari 1.2+, and Windows IE 7 |
+provide the <code>XMLHttpRequest</code> object |
+(Windows IE versions 5+, provides ActiveX to acheive an analagous |
+effect). <code>XMLHttpRequest</code> can send HTTP requests to |
+the server, and provides access the <code>responseText</code> or <code>responseXML</code> |
+(when the response is XML), and HTTP header information. |
+</p><ul class='linkList'><li><a href="http://jibbering.com/2002/4/httprequest.html" >http://jibbering.com/2002/4/httprequest.html</a></li> |
+<li><a href="http://www.w3.org/TR/XMLHttpRequest/" >http://www.w3.org/TR/XMLHttpRequest/</a></li> |
+<li><a href="http://developer.mozilla.org/en/XMLHttpRequest" >http://developer.mozilla.org/en/XMLHttpRequest</a></li> |
+<li><a href="http://msdn.microsoft.com/en-us/library/ms537505(VS.85).aspx" >http://msdn.microsoft.com/en-us/library/ms537505(VS.85).aspx</a></li> |
+</ul> </div> |
+<div id='noCache' class='section'><h3 id='FAQ4_17'>11.6 How do I force a reload from the server/prevent caching?</h3><p> |
+ |
+To reload a page, use <code>location.reload()</code>. However, this depends |
+upon the cache headers that your server sends. To change this, |
+you need to alter the server configuration. A quick fix on the |
+client is to change the page URI so that it contains a unique |
+element, such as the current time. For example: |
+<code>location.replace(location.href+'?d='+new Date().valueOf())</code> |
+If the <code>location.href</code> already contains a query String, use: |
+<code>location.replace(location.href+'&d='+new Date().valueOf())</code></p><ul class='linkList'><li><a href="http://www.mnot.net/cache_docs/" >http://www.mnot.net/cache_docs/</a></li> |
+<li><a href="http://docs.sun.com/source/816-6408-10/date.htm" >http://docs.sun.com/source/816-6408-10/date.htm</a></li> |
+</ul> </div> |
+<div id='ajaxCache' class='section'><h3 id='FAQ4_45'>11.7 Why is my Ajax page not updated properly when using an HTTP GET request in Internet Explorer?</h3><p> |
+ |
+ Browsers cache the results of HTTP requests to reduce network traffic. |
+ To force the browser to request the document from the server, either |
+ set the <code>EXPIRES</code> and/or <code>CACHE-CONTROL</code> response header(s) |
+ with a past date or use a unique query string. |
+ </p> |
+<pre> |
+ req.open("GET", "/example.jsp?date=" + (+new Date), true); |
+</pre> |
+<p> |
+ |
+Always use the appropriate HTTP method. Do not use <code>POST</code> |
+to prevent caching. See <a href="http://www.faqs.org/rfcs/rfc2616.html" >RFC 2616</a>. |
+ |
+</p><ul class='linkList'><li><a href="http://www.mnot.net/cache_docs/#EXPIRES" >http://www.mnot.net/cache_docs/#EXPIRES</a></li> |
+<li><a href="http://www.mnot.net/javascript/xmlhttprequest/cache.html " >http://www.mnot.net/javascript/xmlhttprequest/cache.html </a></li> |
+</ul> </div> |
+<div id='debugging' class='section'><h2>12 Debugging</h2> |
+</div><div id='javascriptErrors' class='section'><h3 id='FAQ4_43'>12.1 How do I get my browser to report javascript errors?</h3><p> |
+ |
+There are debugging tools for many browsers. Learn to use them all. |
+ </p> |
+<dl> |
+ <dt> Windows </dt> |
+ <dd> <a href="http://www.fiddlertool.com/fiddler/" >Fiddler</a>. |
+Fiddler is an HTTP Debugging proxy (it won't find script |
+errors). Fiddler logs HTTP activity, like Firebug's Net |
+tab, but can be attached to any browser running on Windows. |
+ </dd> |
+ <dt> Windows IE </dt> |
+ <dd> Microsoft Script Editor. Included with Visual Studio or Microsoft |
+Word 2003 (discontinued in Office 2007). |
+To enable, |
+<code>Tools</code>, <code>Internet Options</code>, <code>Advanced</code>, and uncheck |
+<code>Disable Script Debugging</code>. After enabling Script Debugging, |
+a <code>Script Debugger</code> option will appear in the <code>View</code> menu. </dd> |
+ <dd> <a href="http://www.my-debugbar.com/wiki/IETester/HomePage" >IETester</a> for testing IE 5.5- IE8. </dd> |
+ <dd> <a href="http://www.my-debugbar.com/wiki/CompanionJS/HomePage" >CompanionJS</a><code>console</code> for IE. </dd> |
+ <dd> <em>Note:</em> For debugging scripts in IE, the Microsoft Script <em>Editor</em> |
+is recommended. However, if not available, the <a href="http://www.microsoft.com/downloads/details.aspx?FamilyId=2F465BE0-94FD-4569-B3C4-DFFDF19CCD99&displaylang=en" >Microsoft Script Debugger</a> may be somewhat helpful. |
+ </dd> |
+ <dd> <a href="http://www.microsoft.com/downloads/details.aspx?FamilyID=e59c3964-672d-4511-bb3e-2d5e1db91038&displaylang=en" >Internet Explorer Developer Toolbar</a> </dd> |
+ <dd> |
+To report errors: Wait until a little yellow |
+triangle appears at the left end of the status bar, double click |
+on it and, when the error dialog box appears, check the "Always |
+show errors" checkbox it contains. |
+ |
+Or, <code>Internet Options</code>, <code>Advanced</code>, deselect <code>"Disable Script Debugging"</code>, |
+select <code>"Display a notification ..."</code>. |
+ </dd> |
+ <dt> Firefox </dt> |
+ <dd> <code>Tools > Error console</code> (<code>Ctrl</code> + <code>Shift</code> + <code>j</code>). |
+ </dd> |
+ <dd> <a href="http://getfirebug.com/" >Firebug</a> </dd> |
+ <dd> <a href="https://addons.mozilla.org/en-US/firefox/addon/5369" >YSlow</a>. |
+YSlow analyzes web pages and tells you why they're slow |
+based on Yahoo's rules for high performance web sites. |
+ </dd> |
+ <dd> <a href="https://addons.mozilla.org/en-US/firefox/addon/1743" >Lori</a> |
+<dfn>Lori</dfn> or Life-of-request info, is useful for troubleshooting |
+server response and page load time. |
+ </dd> |
+ <dd> <a href="https://addons.mozilla.org/en-US/firefox/addon/60" >Web Developer Toolbar</a>. |
+ </dd> |
+ <dd> <a href="https://addons.mozilla.org/en-US/firefox/addon/1201" >Cookie Watcher</a>. |
+ </dd> |
+ <dd> <a href="https://addons.mozilla.org/en-US/firefox/addon/1192" >XPather</a>. |
+XPath generator, editor and inspector. |
+ </dd> |
+ <dt> Opera </dt> |
+ <dd> |
+Tools > Advanced > Error console |
+ </dd> |
+ <dd> <a href="http://dev.opera.com/articles/view/introduction-to-opera-dragonfly/" >Introduction to Opera Dragonfly</a> </dd> |
+ <dt> Safari </dt> |
+ <dd> |
+To display the <code>Develop</code> menu in Safari 3.1 or higher, select |
+the checkbox labeled "Show Develop menu in menu bar" in |
+Safari's <code>Advanced</code> Preferences panel. |
+ </dd> |
+ <dd> <a href="http://trac.webkit.org/wiki/Web%20Inspector " >Safari Web Inspector</a> </dd> |
+ <dt> Chrome </dt> |
+ <dd> |
+JavaScript Console: click the <code>Page</code> menu icon and select |
+<code>Developer > JavaScript Console</code>. From here, you'll be |
+able to view errors in the JavaScript execution, and enter |
+additional javascript commands to execute. |
+ </dd> |
+ <dd> |
+JavaScript Debugger: available as <code>Page</code> menu icon > <code>Developer</code> |
+> Debug JavaScript, the debugger provides a command prompt from which you |
+can set breakpoints, backtrace, and more. Type <code>help</code> at the debugger |
+command line to get started. |
+ </dd> |
+ <dd> |
+<ul> <li> <a href="http://www.google.com/chrome/intl/en/webmasters-faq.html#jsexec" >Google Chrome Script Debugging</a> </li> |
+<li> <a href="http://blog.chromium.org/2009/06/developer-tools-for-google-chrome.html" >Developer Tools for Google Chrome</a> </li> |
+<li> <a href="http://blog.chromium.org/2009/08/google-chrome-developer-tools-for.html" >Tools for Eclipse Users</a> </li> |
+</ul> |
+ </dd> |
+ <dt> Mac IE </dt> |
+ <dd> |
+Use the Preferences dialog. |
+ </dd></dl></div> |
+<div id='doNotTry' class='section'><h2>13 Things not to attempt in a browser</h2> |
+</div><div id='detectBrowser' class='section'><h3 id='FAQ4_26'>13.1 How do I detect Opera/Safari/IE?</h3><p> |
+ |
+The short answer: <em>Don't do that</em>. |
+ </p> <p> |
+ |
+The <code>navigator</code> |
+<dfn>host object</dfn> contains properties which |
+may identify the browser and version. These properties are historically |
+inaccurate. Some browsers allow the user to set <code>navigator.userAgent</code> to any value. For |
+example, Firefox, (type <code>about:config</code> and search <code>useragent</code> |
+or Safari, <code>Develop > User Agent > Other...</code>, IE, via Registry. |
+ </p> <p> |
+ |
+Other browsers, such as Opera, provide a list of user agents |
+for the user to select from. There are also at least 25 other |
+javascript capable browsers, with multiple versions, each |
+with their own string. |
+ </p> <p> |
+ |
+Browser detection is unreliable, at best. It usually causes |
+forward-compatibility and maintenance problems. It is unrelated to the |
+problem or incompatiblity it is trying to solve and obscures the |
+problems it is used for, where it is used. |
+ </p> <p> |
+ |
+Object detection is checking that the object in question exists. |
+<a href="http://dev.opera.com/articles/view/using-capability-detection/" >Capability detection</a> goes one step further to actually test the object, |
+method, or property, to see if behaves in the desired manner. |
+ </p> <p> |
+ |
+Feature Test Example: |
+ </p> |
+<pre> |
+/** |
+ * Returns the element/object the user targeted. |
+ * If neither DOM nor IE event model is supported, returns undefined. |
+ * @throws TypeError if the event is not an object. |
+ */ |
+function getEventTarget(e) { |
+ e = e || window.event; |
+ // First check for the existence of standard "target" property. |
+ return e.target || e.srcElement; |
+}</pre> |
+<ul class='linkList'><li><a href="notes/detect-browser/" >notes/detect-browser/</a></li> |
+<li><a href="http://dev.opera.com/articles/view/using-capability-detection/" >http://dev.opera.com/articles/view/using-capability-detection/</a></li> |
+<li><a href="http://developer.apple.com/internet/webcontent/objectdetection.html" >http://developer.apple.com/internet/webcontent/objectdetection.html</a></li> |
+<li><a href="http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43" >http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.43</a></li> |
+</ul> </div> |
+<div id='preventAccess' class='section'><h3 id='FAQ4_5'>13.2 How can I prevent access to a web page by using javascript?</h3><p> |
+ |
+In practice you can't. While you could create a suitable |
+encryption system with a password in the page, the level of |
+support you need to do this means it's always simpler to do it |
+server-side. Anything that "protects" a page |
+other than the current one is definitely flawed. |
+ </p> </div> |
+<div id='hideSource' class='section'><h3 id='FAQ4_1'>13.3 How do I protect my javascript code?</h3><p> |
+ |
+With clientside javascript you can't as your code is distributed |
+in source form and is easily readable. With JScript, there is the |
+Script Encoder (see MSDN), but this is nothing more than obfuscation. |
+Attempting to disable the context menu does nothing to |
+protect your script in a Web browser. |
+ </p><ul class='linkList'><li> |
+ Your code is likely protected under copyright laws. See: |
+ </li> |
+<li><a href="http://www.wipo.int/about-ip/en/copyright.html" >http://www.wipo.int/about-ip/en/copyright.html</a></li> |
+<li><a href="http://webdesign.about.com/od/copyright/Copyright_Issues_on_the_Web_Intellectual_Property.htm" >http://webdesign.about.com/od/copyright/Copyright_Issues_on_the_Web_Intellectual_Property.htm</a></li> |
+</ul> </div> |
+<div id='disableRightClick' class='section'><h3 id='FAQ4_27'>13.4 How do I suppress a context menu (right-click menu)?</h3><p> |
+ |
+A context menu, often triggered by right-click, can be requested by the |
+user in a few ways. For example, on windows, shift + F10 and on macs, |
+click-and-hold. Other input devices exist and mouse buttons can be |
+configured, making the term "right click" a misnomer, in context. |
+</p> <p> |
+ |
+In browsers that allow it, a script can suppress the context menu by |
+returning false from an object's <code>oncontextmenu</code> event handler. |
+</p> |
+<pre> |
+document.oncontextmenu = function() { |
+ return false; |
+}; |
+</pre> |
+<p> |
+Some browsers lack context menus (e.g. iphone). Browsers that have |
+context menus do not always have a scriptable event for them. Some |
+browsers can be configured to disallow scripts from detecting context |
+menu events (IE, Opera); others may fire the event but be configured to |
+disallow scripts from suppressing the context menu (Firefox,Seamonkey). |
+</p> <p> |
+ |
+Even when the context menu has been suppressed, it will still be |
+possible to view/save the source code and to save images. |
+</p><ul class='linkList'><li><a href="http://en.wikipedia.org/wiki/Context_menu" >http://en.wikipedia.org/wiki/Context_menu</a></li> |
+<li><a href="http://kb.mozillazine.org/Ui.click_hold_context_menus" >http://kb.mozillazine.org/Ui.click_hold_context_menus</a></li> |
+<li><a href="http://support.microsoft.com/kb/823057" >http://support.microsoft.com/kb/823057</a></li> |
+<li><a href="http://stackoverflow.com/questions/1870880/opera-custom-context-menu-picking-up-the-right-click/1902730#1902730" >http://stackoverflow.com/questions/1870880/opera-custom-context-menu-picking-up-the-right-click/1902730#1902730</a></li> |
+<li><a href="http://support.mozilla.com/en-US/kb/Javascript#Advanced_JavaScript_settings" >http://support.mozilla.com/en-US/kb/Javascript#Advanced_JavaScript_settings</a></li> |
+<li><a href="http://msdn.microsoft.com/en-us/library/ms536914%28VS.85%29.aspx" >http://msdn.microsoft.com/en-us/library/ms536914%28VS.85%29.aspx</a></li> |
+</ul> </div> |
+<div id='readFile' class='section'><h3 id='FAQ4_3'>13.5 How can I access the client-side filesystem?</h3><p> |
+ |
+Security means that by default you can't. In a more restricted |
+environment, there are options. For example, using LiveConnect to |
+connect to Java with Netscape, and using the FileSystemObject in |
+IE. Check <a href="http://groups.google.com/group/comp.lang.javascript/topics" >Google Groups archives</a> |
+for previous posts on the subject. |
+ </p><ul class='linkList'><li><a href="http://msdn.microsoft.com/en-us/library/z9ty6h50%28VS.85%29.aspx" >http://msdn.microsoft.com/en-us/library/z9ty6h50%28VS.85%29.aspx</a></li> |
+<li><a href="http://www.javaworld.com/javaworld/jw-10-1998/jw-10-apptowin32.html" >http://www.javaworld.com/javaworld/jw-10-1998/jw-10-apptowin32.html</a></li> |
+</ul> </div> |
+<div id='javascriptURI' class='section'><h3 id='FAQ4_24'>13.6 I have <a href="javascript:somefunction()"> what ... ?</h3><p> |
+ |
+Whatever the rest of your question, this is generally a very bad idea. |
+The <code>javascript:</code> pseudo protocol was designed to replace the |
+current document with the value that is returned from the expression. |
+For example: |
+ </p> |
+<pre> |
+ <a href="javascript:'&lt;h1&gt;' + document.lastModified + '&lt;/h1&gt;'">lastModified</a> |
+</pre> |
+<p> |
+will result in replacing the current document with the value |
+returned from <code>document.lastModified</code>, wrapped in an <code><h1></code> |
+tag. |
+ </p> <p> |
+ |
+When the expression used evaluates to an <code>undefined</code> value |
+(as some function calls do), the contents of the current page are not |
+replaced. Regardless, some browsers (notably IE6) interpret this as |
+navigation and will enter into a 'navigation' state where GIF |
+animations and plugins (such as movies) will stop and navigational |
+features such as <code>META</code> refresh, assignment to <code>location.href</code>, and image |
+swaps fail. |
+ </p> <p> |
+ |
+It is also possible for IE to be configured such that it supports |
+javascript but not the <code>javascript:</code> protocol. This results |
+in the user seeing a protocol error for <code>javascript:</code> URIs. |
+ </p> <p> |
+ |
+The <code>javascript:</code> pseudo protocol creates accessibility and |
+usability problems. It provides no fallback for when the script is not |
+supported. |
+ </p> <p> |
+ |
+Instead, use |
+<code><a href="something.html" onclick="somefunction();return false"></code> |
+where <code>something.html</code> is a meaningful alternative. Alternatively, |
+attach the <code>click</code> callback using an event registry. |
+ </p><ul class='linkList'><li><a href="example/jsuri/" >example/jsuri/</a></li> |
+<li><a href="http://groups.google.com/group/comp.lang.javascript/msg/f665cfca3b619692" >Set/Navigate to a Location</a></li> |
+<li><a href="http://www.useit.com/alertbox/20021223.html" >Top Ten Web-Design Mistakes of 2002</a></li> |
+</ul> </div> |
+<div id='comments' class='section'><h2 id='FAQ5'>14 Comments and Suggestions</h2> |
+<p> |
+ |
+The FAQ uses the stylesheet <a href="faq.css" >faq.css</a> and is generated |
+from the xml source <a href="index.xml" >index.xml</a> by the windows script |
+host script <a href="process.wsf" >process.wsf</a> which also checks the links. |
+ </p> </div><div id='FAQENTRY' class='section'><h3 id='FAQ5_1'>14.1 Why do some posts have <FAQENTRY> in them?</h3><p> |
+ |
+If a poster feels that the question they are answering should be |
+covered in the FAQ, placing <FAQENTRY> in the post lets the FAQ |
+robot collect the messages for easy review and inclusion. A Draft Proposal |
+for the FAQ is requested and appreciated. |
+ </p> <p> |
+ |
+The <FAQENTRY> should not be used in posts except in |
+conjunction with a suggestion/proposal for the FAQ. It should |
+also not be literally quoted in replies, instead it should be |
+partly obscured as, e.g. <FAQ**TRY> or similar. |
+ </p> </div> |
+<div id='makeSuggestion' class='section'><h3 id='FAQ5_2'>14.2 How do I make a suggestion?</h3><p> |
+ |
+The FAQ is currently lacking a maintainer, please contact Jim Ley |
+(jim.ley@gmail.com) if you wish to take it over, you will need to |
+be in good standing in the group and trustworthy to have access to the |
+server. All comments, suggestions, and especially corrections are |
+welcome. |
+ </p> </div> |
+<!--<script src='FAQReader.js' type='text/javascript'></script>--></body> |
+</html> |
+ |
/cljs/index.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/example/addcslashes.php |
=================================================================== |
--- cljs/example/addcslashes.php (nonexistent) |
+++ cljs/example/addcslashes.php (revision 2) |
@@ -0,0 +1,10 @@ |
+ |
+<pre> |
+$str: " ' \ |
+
+</pre> |
+ |
+<pre> |
+addcslashes($str,"\\\'\"\n\r"): |
+\" \' \\ \n\r |
+</pre> |
\ No newline at end of file |
Index: cljs/example/jsuri/index.html |
=================================================================== |
--- cljs/example/jsuri/index.html (nonexistent) |
+++ cljs/example/jsuri/index.html (revision 2) |
@@ -0,0 +1,49 @@ |
+<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" |
+"http://www.w3.org/TR/html4/loose.dtd"> |
+<html lang="en"> |
+<head> |
+<title>javascript pseudo-protocol errors</title> |
+<meta http-equiv="refresh" content="10; url=pseudoGifTest.html"> |
+<link rel="index" href="http://jibbering.com/faq/"> |
+<script type="text/javascript"> |
+var loadTime; |
+function init(){ |
+ loadTime = +new Date |
+ showTime(); |
+ setInterval(showTime, 100); |
+ |
+} |
+window.onbeforeunload = function() { |
+ document.getElementById("bNotifier").value = "beforeonload handler called"; |
+}; |
+ |
+function showTime(){ |
+ document.forms['f'].elements['t'].value = (((new Date()).getTime() - loadTime)/1000) |
+} |
+</script> |
+</head> |
+<body onload="init()"> |
+<h1>javascript: uri problems demo</h1> |
+<p> |
+ <img src="waveAnim.gif" alt="animated wave"> |
+</p> |
+ |
+<form action="" onsubmit="return false;" name="f"> |
+ <input type="text" value="" name="t" size="20"> |
+ <input type="text" value="" id="bNotifier" size="30"> |
+</form> |
+ |
+<h3>javascript: uri as href</h3> |
+<p> |
+<a href="javascript:void 0;">javascript:void 0;</a> |
+</p> |
+ |
+<h3>Actual link to invalid URL</h3> |
+ <a href="http://bogus.example.com/v.html">http://bogus.example.com/</a> |
+ |
+<h3>javascript: uri with syntactially invalid code</h3> |
+<p> |
+ <a href="javascript:void();">javascript:void();</a> |
+</p> |
+</body> |
+</html> |
/cljs/example/jsuri/index.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/example/jsuri/waveAnim.gif |
=================================================================== |
Cannot display: file marked as a binary type. |
svn:mime-type = application/octet-stream |
/cljs/example/jsuri/waveAnim.gif |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+application/octet-stream |
\ No newline at end of property |
Index: cljs/example/functionStatement.html |
=================================================================== |
--- cljs/example/functionStatement.html (nonexistent) |
+++ cljs/example/functionStatement.html (revision 2) |
@@ -0,0 +1,54 @@ |
+<!doctype html> |
+<html lang="en"> |
+<head> |
+<meta charset="iso-8859-15"> |
+<link rel="DCTERMS.isReferencedBy" href="http://jibbering.com/faq/#functionStatement"> |
+ |
+<title>Function Statement Example - FAQ - comp.lang.javascript</title> |
+ |
+<style type="text/css"> |
+pre { |
+ background: #fefefe; |
+ padding: 1ex; |
+ border: 1px dashed #eee; |
+} |
+</style> |
+</head> |
+ |
+<body style="background: #f9f9f9"> |
+<h1>Function Statement Example - FAQ : "What is a function statement?"</h1> |
+<h2>Example Code</h2> |
+<pre> |
+try { |
+ x; // ReferenceError: x is not defined. |
+ function Fze(a, b) {a.unselectable = b} |
+} catch(e) { } |
+ |
+document.write("typeof Fze: ", typeof Fze, "\ntypeof e: ", typeof e); |
+</pre> |
+ |
+<h2>Result</h2> |
+<pre> |
+<script type="text/javascript"> |
+try { |
+ x; // ReferenceError: x is not defined. |
+ function Fze(a, b) {a.unselectable = b} |
+} catch(e) { } |
+ |
+document.write("typeof Fze: ", typeof Fze, "\ntypeof e: ", typeof e); |
+</script> |
+</pre> |
+ |
+<p> |
+Expected outcome for <code>typeof Fze</code> is not specified by ECMA-262. |
+</p> |
+If <code>typeof Fze</code> results <code>"function"</code>, then <code>Fze</code> was interpreted |
+as a FunctionDeclaration. Otherwise if <code>typeof Fze</code> resulted <code>"undefined"</code>, |
+then <code>Fze</code> was not reached as a Statement; the preceeding statement - <code>x;</code> - |
+would trigger a ReferenceError, making it unreachable. |
+</p> |
+<p> |
+Expected outcome for <code>typeof e</code> is <code>"undefined"</code>. |
+</p> |
+</body> |
+</html> |
/cljs/example/functionStatement.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/example/postMessage.html |
=================================================================== |
--- cljs/example/postMessage.html (nonexistent) |
+++ cljs/example/postMessage.html (revision 2) |
@@ -0,0 +1,60 @@ |
+<!doctype html> |
+<html> |
+<head> |
+<title>window postMessage</title> |
+ |
+<body> |
+<h1>Ask the 8-Ball</h1> |
+<iframe src="http://dhtmlkitchen.com/jstest/postMessage/receiver.html" id="iframe" |
+ style="width: 90%; height: 10em;"></iframe> |
+<form id="posterForm"> |
+ <textarea id="msg" placeholder="Ask the 8 ball" cols="30" rows="5"></textarea> |
+ <input type="submit"> |
+ <pre id="responseMessage">-</pre> |
+</form> |
+<script type="text/javascript"> |
+window.onload = function() { |
+ |
+ var DOMAIN_RECEIVER = "http://dhtmlkitchen.com", |
+ win = document.getElementById("iframe").contentWindow, |
+ responseMessage = document.getElementById("responseMessage"), |
+ form = document.getElementById("posterForm").onsubmit = postDataToWin; |
+ |
+ |
+ |
+ function postDataToWin(ev){ |
+ win.postMessage( |
+ document.getElementById("msg").value, |
+ DOMAIN_RECEIVER |
+ ); |
+ return false; |
+ } |
+ |
+ // Listen for message back from dhtmlkitchen. |
+ addCallback(self, "message", messageReceivedBackHandler); |
+ |
+ function messageReceivedBackHandler(ev) { |
+ ev = ev || self.event; |
+ var ACCEPT_DOMAIN = "http://dhtmlkitchen.com", |
+ origin = ev.origin, |
+ messageEl = document.getElementById("m"); |
+ |
+ // Allow only accepted domain. |
+ if(origin !== ACCEPT_DOMAIN) { |
+ return; |
+ } |
+ |
+ responseMessage.firstChild.data = ev.data; |
+ } |
+ |
+ function addCallback(o, type, cb){ |
+ if(o.addEventListener) { |
+ o.addEventListener(type, cb, false); |
+ } else { |
+ o.attachEvent("on" + type, cb); |
+ } |
+ } |
+}; |
+</script> |
+</body> |
+</html> |
/cljs/example/postMessage.html |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: cljs/process.wsf |
=================================================================== |
--- cljs/process.wsf (nonexistent) |
+++ cljs/process.wsf (revision 2) |
@@ -0,0 +1,387 @@ |
+<job id="process"> |
+<!-- |
+This file generates the FAQ index.html |
+--> |
+<SCRIPT> |
+/** |
+ * Formatting - Still messy. |
+ * Needed corrections: |
+ * statements terminated with semicolon. |
+ * use |var| for variables. |
+ * use whitespace. |
+ * 2 spaces for indentation (not one). |
+ */ |
+var CheckUrls=false, |
+ xmlhttp = new ActiveXObject("Msxml2.XMLHTTP"); |
+ |
+// moomin.utilities can be got from http://www.e-media.co.uk/earl/ |
+// var mu=new ActiveXObject("Moomin.Utilities") |
+ |
+var xml = new ActiveXObject("Microsoft.XMLDOM"); |
+xml.async = false; |
+xml.validateOnParse = false; |
+xml.resolveExternals = false; |
+xml.load("index.xml"); |
+xml.save("indexold.xml"); |
+ |
+var faqNode = xml.selectSingleNode("/FAQ"), |
+ Version = faqNode.attributes.getNamedItem("VERSION").nodeValue, |
+ maintainer = "Garrett Smith", |
+ Updated = faqNode.attributes.getNamedItem("DATE").nodeValue; |
+ |
+var str = '<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN" \n' |
+ + '"http://www.w3.org/TR/html4/strict.dtd">\n<html lang="en">\n' |
+ + '<head>\n' |
+ + '<meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">\n' |
+ + '<meta name="DCTERMS.language" scheme="RFC1766" content="en">\n' |
+ + '<meta name="DC.title" content="comp.lang.javascript Frequently Asked Questions">\n' |
+ + '<meta name="DCTERMS.subject" ' |
+ + 'content="Frequently asked questions in the Usenet newsgroup comp.lang.javascript">\n' |
+ + '<meta name="DC.format" content="text/html">\n' |
+ + '<meta name="DC.type" content="Text">\n' |
+ + '<meta name="DC.creator" content="Jim Ley">\n' |
+ + '<meta name="DC.publisher" content="' + maintainer + '">\n' |
+ + '<META name="DC.Publisher.Address" ' |
+ + 'content="dhtmlkitchen@gmail.com">\n' |
+ + '<meta name="DCTERMS.modified" content="' + Updated +'">\n' |
+ + '<meta name="DCTERMS.audience" content="Programmers, web developers">\n' |
+ + '<meta name="DC.description" content="Javascript Frequently Asked Questions">\n' |
+ + '<meta name="DC.identifier" content="http://jibbering.com/faq">\n' |
+ + '<meta name="DC.source" ' |
+ + 'content="http://www.ecma-international.org/publications/standards/Ecma-262.htm">\n' |
+ + '<meta name="DC.source" content="news:comp.lang.javascript">\n' |
+ + '<meta name="DC.source" content="https://developer.mozilla.org/en/JavaScript">\n' |
+ + '<meta name="DC.source" content="http://msdn.microsoft.com/en-us/library/hbxc2t98%28VS.85%29.aspx">\n' |
+ + '<meta name="DC.source" content="http://msdn.microsoft.com/en-us/library/ms533050%28VS.85%29.aspx">\n' |
+ + '<meta name="DC.rights" content="copyright contributors, comp.lang.javascript">\n' |
+ + '<link rel="StyleSheet" href="faq.css" type="text/css" media="screen">\n'; |
+ |
+TitleStr = xml.selectSingleNode("/FAQ/TITLE").firstChild.nodeValue; |
+ |
+str += "<title> "+TitleStr+"</title>\n" |
+ + '</head>\n <body>\n' |
+ + "<h1> "+TitleStr+"</h1>\n" |
+ + "<p>Version "+Version+", Updated "+Updated +", by " + maintainer + "</p>" |
+ + '<div id="nav"><a href="notes/">FAQ Notes</a></div>'; |
+ |
+var contentstr = ""; |
+Contents = xml.selectSingleNode("/FAQ/CONTENTS").selectNodes("CONTENT"); |
+ |
+str += "\n<ul id='faqList'>\n"; |
+ |
+for (var i = 0; i < Contents.length; i++) { |
+ CNode = Contents[i]; |
+ var sectionId = CNode.getAttribute("ID") || "", |
+ title = CNode.getAttribute("TITLE"); |
+ |
+ str += "<li>" + (i+1) + " <a href='#" + sectionId +"'>" + title + "</a>\n"; |
+ |
+ contentstr += "<div id='" + sectionId +"' class='section'>" |
+ + "<h2"+getOldId(CNode)+">" |
+ + (i+1) + " " + title |
+ + "</h2>\n" |
+ + processContentChildren(CNode) |
+ + "</div>"; |
+ |
+ var SubContents = CNode.selectNodes("CONTENT"); |
+ processContentChildren(CNode); |
+ if(SubContents.length > 0) { |
+ str += "\n<ul>\n"; |
+ |
+ // Build a link to a subsection. |
+ // a subsection looks like: |
+ // <h3 id=[FAQ5_7 | getWindowSize]><a name=FAQ5_7></a> ... </h3> |
+ // This allows for items to be moved around in various |
+ // order (index should not matter). |
+ |
+ for (var j = 0; j < SubContents.length; j++) { |
+ var SubCNode = SubContents[j], |
+ subSectionId = SubCNode.getAttribute("ID"), |
+ title = SubCNode.getAttribute("TITLE"), |
+ entryNumber = ""+(i+1)+"."+ (j+1); |
+ |
+ str += "<li>" + entryNumber +" <a href='#"+ subSectionId +"'>" + title + "</a></li>\n"; |
+ |
+ contentstr += "<div id='" + subSectionId + "' class='section'>" |
+ + "<h3" + getOldId(SubCNode) + ">" |
+ + entryNumber + " " + title |
+ + '</h3>' |
+ + processContentChildren(SubCNode ) |
+ + '</div>' |
+ + '\n'; |
+ } |
+ str += "</ul>"; |
+ } |
+ str += "</li>"; |
+} |
+ |
+/** |
+ * If the node contains a "NUMID", |
+ * the content is wrapped in an anchor, e.g. "<a name='" + NUMID. |
+ * Otherwise, returns the content. |
+ */ |
+function getOldId(node) { |
+ var faqSectionIndexString = node.getAttribute("NUMID") || ""; |
+ return (faqSectionIndexString ? |
+ " id='FAQ" + faqSectionIndexString +"'" : ""); |
+} |
+ |
+str += "</ul>" |
+ + contentstr |
+ + "<!--<script src='FAQReader.js' type='text/javascript'><\/script>-->" |
+ + "</body> \n</html> \n"; |
+str = str.replace(/<p><\/p>/gm,"").replace(/<p> <\/p>/gm,""); |
+ |
+// Create the files. |
+var FSO = new ActiveXObject("Scripting.FileSystemObject"); |
+FIL = FSO.CreateTextFile("index"+Version+".html",true); |
+FIL.WriteLine(str); |
+FIL.close(); |
+FIL=FSO.CreateTextFile("index.html",true); |
+FIL.WriteLine(str); |
+FIL.close(); |
+if (CheckUrls) { |
+ xml.save("index.xml"); |
+ xml.save("index"+Version+".xml"); |
+} |
+ |
+function processContentChildren(cNode) { |
+ var allNodes = cNode.selectNodes("*"), |
+ contentstr = "";; |
+ for(var k = 0; k < allNodes.length; k++) { |
+ var node = allNodes[k]; |
+ if(node.tagName == "P") |
+ contentstr += ProcessNode(node); |
+ |
+ // List nodes, for UL, OL, DL. |
+ else if(node.tagName == "LIST") |
+ contentstr += processList(allNodes[k]); |
+ } |
+ return contentstr; |
+} |
+ |
+function ProcessNode(nde) { |
+ var str = " ", p = "", closeP = "", child; |
+ if(nde.tagName == "P") { |
+ str = "<p>\n "; |
+ p = "<p>"; |
+ closeP = "</p>"; |
+ } |
+ for (var i = 0;i < nde.childNodes.length; i++) { |
+ child = nde.childNodes[i]; |
+ switch (child.nodeName) { |
+ case "#comment" : |
+ str += "<!--" + child.data + "-->"; |
+ break; |
+ case "#text" : |
+ // If a text node is empty, do not generate an empty <p> tag. |
+ if(child.nodeValue.replace(/\s+/,'') == "") return " "; |
+ str += child.nodeValue; |
+ break; |
+ case "VER" : |
+ str += Version; |
+ break; |
+ case "UPDATED" : |
+ str += Updated; |
+ break; |
+ case "URL" : |
+ str += makeLink(child); |
+ break; |
+ case "EM" : |
+ var url= child.firstChild.nodeValue; |
+ str+=' <em>'+url+'</em>'; |
+ break; |
+ case "NEWSGROUP" : |
+ var url= child.firstChild.nodeValue; |
+ str+=' <a href="news:'+url+'">'+url+'</a>'; |
+ break; |
+ case "MAILTO" : |
+ var url= child.firstChild.nodeValue; |
+ str+=' <a href="mailto:'+url+'">'+url+'</a>'; |
+ break; |
+ case "MOREINFO" : |
+ str += closeP + ProcessResource(child) + p; |
+ break; |
+ case "UL" : |
+ str+= closeP + " \n<ul> "+ProcessUL(nde.childNodes[i])+"</ul> \n" + p; |
+ break; |
+ case "LI" : |
+ str+="<li> "+ ProcessNode( child ) + "</li>"; |
+ break; |
+ case "CODE" : |
+ str+= closeP + "\n<pre>"+ child.firstChild.nodeValue +"</pre>\n"+p; |
+ break; |
+ case "ICODE" : |
+ str += "<code>"+ child.firstChild.nodeValue+"</code>"; |
+ break; |
+ case "DFN" : |
+ var title = child.attributes.getNamedItem("TITLE"); |
+ title = title && (" title = '" + title.nodeValue +"'") || ""; |
+ str +="\n<dfn" + title + ">" |
+ + child.firstChild.nodeValue + "</dfn>"; |
+ break; |
+ default: |
+ str += child.nodeValue; |
+ break; |
+ } |
+ } |
+ return str+= closeP + " "; |
+} |
+ |
+function makeLink(child) { |
+ var url = child.firstChild.nodeValue, |
+ linkText = child.attributes.getNamedItem("LINKTEXT"), |
+ addstr = checkUrl(url, child); |
+ linkText = linkText && linkText.nodeValue; |
+ return '<a href="'+url+'" '+addstr+'>'+(linkText||url)+'</a>'; |
+} |
+ |
+/** Processing for OL, UL, DL. |
+ * calls processNode. |
+ */ |
+function processList(list) { |
+ var str = "", |
+ header = "", |
+ title = list.getAttribute("TITLE"), |
+ id = list.getAttribute("ID"), |
+ idStr = (id && " id='" + id + "'") || ""; |
+ |
+ if(title) { |
+ header = "\n<h4" + idStr +">" + title + "</h4>\n"; |
+ idStr = ""; // Output id only once. |
+ } |
+ |
+ var type = list.getAttribute("TYPE"); |
+ type = (type || "ul").toLowerCase(); |
+ |
+ str += "\n<" + type + idStr +">"; |
+ |
+ for (var i = 0; i < list.childNodes.length; i++) { |
+ var child = list.childNodes[i], |
+ tagName = child.nodeName; |
+ |
+ // If not a list-type element, |
+ // add it to the header (will appear first). |
+ if(!/(?:LI)|(?:DT)|(?:DD)/.test(tagName)) { |
+ header += ProcessNode(child); |
+ } |
+ else if(tagName !== "#text") { |
+ tagName = tagName.toLowerCase(); |
+ str += "\n <" +tagName +">" + ProcessNode(child) + "</" +tagName +">"; |
+ } |
+ } |
+ return header + str + "</" + type + ">"; |
+} |
+ |
+ function ProcessUL(nde) { |
+ var str="" |
+ for (var i=0;i<nde.childNodes.length;i++) { |
+ |
+ var child = nde.childNodes[i]; |
+ |
+ switch (nde.childNodes[i].nodeName) { |
+ case "#text" : |
+ str+=nde.childNodes[i].nodeValue; |
+ break; |
+ case "VER" : |
+ str+=Version |
+ break; |
+ case "URL" : |
+ str += makeLink(child); |
+ break; |
+ case "NEWSGROUP" : |
+ var url = child.firstChild.nodeValue |
+ str+=' <a href="news:'+url+'">'+url+'</a> \n' |
+ break; |
+ case "MAILTO" : |
+ var url= child.firstChild.nodeValue; |
+ str+=' <a href="mailto:'+url+'">'+url+'</a> \n' |
+ break; |
+ case "UL" : |
+ str+="<ul>\n" + ProcessNode(child) + "\n</ul>\n" |
+ break; |
+ case "LI" : |
+ str+="<li> " + ProcessNode(child) + "</li> \n" |
+ break; |
+ case "CODE" : |
+ str+="</p>\n<pre>"+nde.childNodes[i].firstChild.nodeValue.replace('\r',"<BR> ")+"</pre> \n<p> \n" |
+ break; |
+ case "ICODE" : |
+ str+="<code>"+nde.childNodes[i].firstChild.nodeValue+"</code>\n" |
+ break; |
+ default: |
+ document.write(nde.childNodes[i].nodeName+'<br> \n') |
+ str+=nde.childNodes[i].nodeValue; |
+ break; |
+ } |
+ } |
+ return str += ""; |
+ } |
+ |
+ |
+function ProcessResource(nde) { |
+ var str="<ul class='linkList'>", child; |
+ for (var i = 0; i < nde.childNodes.length; i++) { |
+ child = nde.childNodes[i]; |
+ switch (child.nodeName) { |
+ case "#text" : |
+ if(/[a-zA-Z]/.test(child.nodeValue)) |
+ str += '<li>' + child.nodeValue + '</li>\n'; |
+ break; |
+ case "URL" : |
+ str+='<li>' + makeLink(child) + '</li>\n'; |
+ break; |
+ case "NEWSGROUP" : |
+ var url = child.firstChild.nodeValue; |
+ str += '<li><a href="news:'+url+'">' + url + '</a></li> \n'; |
+ break; |
+ |
+ } |
+ } |
+ return str + "</ul>"; |
+} |
+ |
+ function checkUrl(url,node) { |
+ url=url.split('#')[0] |
+ if (CheckUrls) { |
+ if (url.indexOf('http://')==0) { |
+ xmlhttp.Open("get",url,false) |
+ try { |
+ xmlhttp.Send() |
+ } catch (e) { WScript.Echo(url);return ""; } |
+ stat=xmlhttp.status |
+ node.attributes.getNamedItem("status").nodeValue=stat |
+ if (stat==200) { |
+ source=xmlhttp.responseText |
+ if (url.indexOf('microsoft')!=-1 && source.indexOf('Page Cannot')!=-1) { |
+ //Ugly hack 'cos MSDN don't understand HTTP. |
+ stat=404 |
+ node.attributes.getNamedItem("status").nodeValue=stat |
+ return ' class="nolink" ' |
+ } |
+ contentlength=source.length |
+// oldhash=node.attributes.getNamedItem("hash").nodeValue |
+// hash=mu.MD5(source,"faq") |
+// node.attributes.getNamedItem("hash").nodeValue=hash |
+ classstr="" |
+// if (oldhash!=hash) classstr=' class="updated"' |
+ lm=xmlhttp.getResponseHeader("Last-Modified") |
+ return classstr+' title="'+lm+'" ' |
+ } else { |
+ xmlhttp.Open("get","http://www.google.com/search?q=cache:"+url,false) |
+ xmlhttp.Send() |
+ if (xmlhttp.responseText.indexOf('did not match any documents')==-1) { |
+ return ' class="nolink"> \n<small> \n<a href="http://www.google.com/search?q=cache:'+url+'>(Googles cached copy)</a> \n<small' |
+ } |
+ return ' class="nolink" ' |
+ } |
+ } else { |
+ return "" |
+ } |
+ } else { |
+ return "" |
+ } |
+ |
+ } |
+</SCRIPT> |
+</job> |
Index: cljs/faq.css |
=================================================================== |
--- cljs/faq.css (nonexistent) |
+++ cljs/faq.css (revision 2) |
@@ -0,0 +1,201 @@ |
+/* |
+Updated 2009-06-14 Garrett Smith |
+*/ |
+ |
+ |
+a { |
+ text-decoration: none; |
+ color: #002288; |
+ background: none; |
+} |
+ |
+a:hover { |
+ text-decoration: underline; |
+} |
+ |
+html { |
+ font-family: sans-serif; |
+ font-size: 90%; |
+ background: #F6f6f6; |
+ color : #000; |
+} |
+ |
+body { |
+ margin: 1em; |
+ border-bottom: 1px solid #ccc; |
+} |
+ |
+.preSample { |
+ background-color : #f9eff0; |
+ line-height : 200%; |
+ border : #bb7799 1px solid; |
+} |
+ |
+pre { |
+ font-family : monospace; |
+ background-color : #fFF9f9; |
+ border : #bb7799 1px solid; |
+ color : #440011; |
+ font-size : 100%; |
+ padding : 5px 5px 5px 10px; |
+} |
+ |
+h1 { |
+ font-size : 160%; |
+} |
+ |
+h2 { |
+ font-size : 140%; |
+} |
+ |
+h3 { |
+ font-size : 113%; |
+} |
+ |
+h2 a, h3 a, h2 a:hover, h3 a:hover { |
+ color: inherit; |
+ text-decoration: none; |
+} |
+ |
+.section h3 { |
+ margin-top: 0; |
+} |
+ |
+h4 { |
+ font-size : 110%; |
+} |
+ |
+h5 { |
+ font-size : 100%; |
+} |
+ |
+code { |
+ color : #550011; |
+ font-family : monospace; |
+ margin: 0em 0.1em; |
+} |
+ |
+/** EcmaScript Code Examples */ |
+/* keywords, if, with, var, et c */ |
+.keyword { |
+ color: #00f; |
+ font-weight: 800; |
+} |
+ |
+/* string literals */ |
+.q { |
+ color: #900; |
+} |
+ |
+ul.linkList { |
+ background-color : #eeeeee; |
+ border : #999999 1px solid; |
+ color : #000000; |
+ font-size : 100%; |
+ padding : 0.2em; |
+ list-style: none; |
+} |
+ |
+ul.linkList li { |
+ margin: .2em; |
+} |
+ |
+#faqList { |
+ font-size: 120%; |
+ list-style: none; |
+ padding-left: 0; |
+ margin-left: 0; |
+} |
+ |
+#faqList li { |
+ margin-top: .3em; |
+ margin-bottom: .3em; |
+} |
+ |
+#faqList ul { |
+ font-size: 83%; |
+ list-style: none; |
+ padding-left: 0; |
+ padding-top: 0; |
+ margin-left: 1em; |
+ color: #333; |
+} |
+ |
+.linkListSample { |
+ background-color : #eeeeff; |
+ line-height : 200%; |
+ border : #9999bb 1px solid; |
+} |
+ |
+dd { |
+ margin: 3px 2em; |
+ padding: 0; |
+} |
+ |
+#nav { |
+ clear: both; |
+} |
+ |
+#readerViewToggle { |
+ margin-left: 34%; |
+ text-align: center; |
+ position: absolute; |
+ margin-top: -3em; |
+ background: #fff; |
+ border: 1px solid #CCC; |
+ padding: 0.1em 0.2em; |
+} |
+ |
+#readerViewToggle * { |
+ cursor: pointer; |
+ display: block; |
+ white-space: nowrap; |
+} |
+ |
+#readerViewToggle img { |
+ font-size: 24px; |
+ height: 33px; |
+ width: 27px; |
+ margin: auto; |
+} |
+ |
+.readerView #faqList { |
+ width: 40%; |
+ background: #fcfcfc; |
+ border: 1px solid #eee; |
+ -moz-border-radius: 4px; |
+ -webkit-border-radius: 4px; |
+ padding: 8px; |
+ float: left; |
+ margin-right: 22px; |
+} |
+ |
+.section { |
+ padding-top: 1.2em; |
+} |
+ |
+.readerView .section { |
+ display: none; |
+ float: left; |
+ width:56%; |
+} |
+ |
+#builtInsList dd { |
+ margin-right: 0; |
+ margin-left: 1em; |
+ display: inline; |
+} |
+ |
+#builtInsList dt { |
+ font-weight: 700; |
+} |
+ |
+#pageWarning { |
+ background-color: #fff3dd; |
+ color: #321; |
+ border: 1ex solid #fc9; |
+ font-size: larger; |
+ font-weight: bold; |
+ padding: 1em; |
+ margin: 1em 3em; |
+} |
/cljs/faq.css |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: .settings/org.eclipse.php.core.prefs |
=================================================================== |
--- .settings/org.eclipse.php.core.prefs (nonexistent) |
+++ .settings/org.eclipse.php.core.prefs (revision 2) |
@@ -0,0 +1,2 @@ |
+eclipse.preferences.version=1 |
+include_path=0;/FAQs |
/.settings/org.eclipse.php.core.prefs |
Property changes: |
Added: svn:mime-type |
## -0,0 +1 ## |
+text/plain |
\ No newline at end of property |
Index: .settings/org.eclipse.wst.common.project.facet.core.xml |
=================================================================== |
--- .settings/org.eclipse.wst.common.project.facet.core.xml (nonexistent) |
+++ .settings/org.eclipse.wst.common.project.facet.core.xml (revision 2) |
@@ -0,0 +1,7 @@ |
+<?xml version="1.0" encoding="UTF-8"?> |
+<faceted-project> |
+ <fixed facet="php.component"/> |
+ <fixed facet="php.core.component"/> |
+ <installed facet="php.core.component" version="1"/> |
+ <installed facet="php.component" version="5.3"/> |
+</faceted-project> |