Subversion Repositories FAQs

Compare Revisions

Last modification

Regard whitespace Rev 43 → Rev 44

/trunk/cljs/faq_notes/clj_posts.html
File deleted
Property changes:
Deleted: svn:mime-type
## -1 +0,0 ##
-text/plain
\ No newline at end of property
Index: cljs/faq_notes/not_browser_detect.html
===================================================================
--- cljs/faq_notes/not_browser_detect.html (revision 43)
+++ cljs/faq_notes/not_browser_detect.html (nonexistent)
@@ -1,1413 +0,0 @@
-<!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> &gt; <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 &quot;It works in
-browser XYZ&quot;, 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 &lt; appVersion.length;c++){
- var chr = appVersion.charAt(c);
- if(isNaN(chr)){
- appVersion = appVersion.substring(0, c);
- break;
- }
- }
- if((userAgent.indexOf('webtv') &lt; 0) &amp;&amp;
- (userAgent.indexOf('hotjava') &lt; 0)){
- if(userAgent.indexOf('Opera') &gt;= 0){
- var ind = (userAgent.indexOf('Opera')+6);
- if(((ind+1) &lt; userAgent.length)&amp;&amp;(ind &gt;= 6)){
- isOpera = true;
- var bsVersion = parseInt(userAgent.substring(ind, ind+1));
- if(!isNaN(bsVersion)){
- operaVersion = bsVersion;
- if(operaVersion &gt;= 6){
- isOpera6p = true;
- }else if(operaVersion &gt;= 5){
- isOpera5 = true;
- }
- }
- }
- }else if(appName.indexOf('Microsoft Internet Explorer') &gt;= 0){
- var ind = (userAgent.indexOf('MSIE')+5);
- if(((ind+1) &lt; userAgent.length)&amp;&amp;(ind &gt;= 5)){
- isIE = true;
- var bsVersion = parseInt(userAgent.substring(ind, ind+1));
- if(!isNaN(bsVersion)){
- ieVersion = bsVersion;
- if(ieVersion &gt;= 5){
- isIE5p = true;
- }else if(ieVersion &gt;= 4){
- isIE4 = true;
- }
- }
- }
- }else if(appName.indexOf('Netscape') &gt;= 0){
- if((self.navigator.vendor)&amp;&amp;
- (self.navigator.vendor.indexOf('Netscape') &gt;= 0)&amp;&amp;
- (userAgent.indexOf('Gecko') &gt;= 0)){
- isNet5p = true;
- }else if((userAgent.indexOf('Netscape') &lt; 0)&amp;&amp;
- (userAgent.indexOf('Gecko') &gt;= 0)&amp;&amp;
- (appVersion &gt;= 5)){
- isMozilla1p = true;
- }else if((appVersion &lt; 5)&amp;&amp;
- (userAgent.indexOf('compatible') &lt; 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>&quot;Mozilla/4.0 (compatible; MSIE 5.01; Windows NT)&quot;</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>&quot;userAgent&quot;</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&amp;&amp;!isDOM)?true:false;
-var isIE5p=(document.all&amp;&amp;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(&quot;text&quot;,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 &quot;feature detecting&quot;, 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 &quot;object detecting&quot; 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')&amp;&amp;
- (clipboardData.setData)){
- clipboardData.setData(&quot;text&quot;,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>&quot;undefined&quot;</code>, <code>&quot;object&quot;</code>,
-<code>&quot;function&quot;</code>, <code>&quot;boolean&quot;</code>
-<code>&quot;string&quot;</code> and <code>&quot;number&quot;</code>
-and the test compares the returned string with the string
-<code>&quot;undefined&quot;</code>. The <code>clipboardData</code>
-object is not used unless typeof does not return
-<code>&quot;undefined&quot;</code>.
-</p>
-
-
-<p id="bdFD_8">
-The second test is a type-converting test. The logical AND
-(<code>&amp;&amp;</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=&quot;button&quot;</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">
-&lt;input type=&quot;button&quot;
- value=&quot;copy our contact e-mail address to your clipboard&quot;
- onclick=&quot;copyToClip('info@example.com')&quot;&gt;
-</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">
-&lt;script type=&quot;text/javascript&quot;&gt;
- if((typeof clipboardData != 'undefined')&amp;&amp;
- (clipboardData.setData)&amp;&amp;
- (document.write)){
- document.write('&lt;input type=&quot;button&quot;',
- 'value=&quot;copy our contact e-mail address',
- ' to your clipboard&quot; onclick=&quot;',
- 'copyToClip(\'info@example.com\')&quot;&gt;');
- }
-&lt;/script&gt;
-</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
-&quot;clean degradation&quot; 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 &lt; baseLayers.length;c++){
- if((baseLayers[c])&amp;&amp; <span class="commentJS">//Object at index - c.</span>
- (baseLayers[c].document)&amp;&amp; <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(&quot;ID_string&quot;);
-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 &quot;root&quot; 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
-&quot;root&quot; 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 &quot;root&quot; element, they
-are the preferred values to use. In there absence the problem moves on
-to identifying the &quot;root&quot; 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>&quot;CSS1Compat&quot;</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 &quot;global&quot; 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 &quot;root&quot; 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 &quot;pageXOffset&quot; and &quot;pageYOffset&quot;
- 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 &quot;root&quot; element. First, does the browser
- have a - document.compatMode - string, if it does then
- is its value &quot;BackCompat&quot;, &quot;QuirksMode&quot; or &quot;CSS1Compat&quot;.
- Instead of comparing the string directly it is searched
- for the substring &quot;<span class="initialism" title="Cascading Style Sheet"><abbr title="Cascading Style Sheet">CSS</abbr></span>&quot; which might make the script more
- robust in the face of possible future &quot;CSSnCompat&quot;
- modes, which are unlikely to demand that the &quot;root&quot;
- 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')&amp;&amp;
- (document.compatMode.indexOf('CSS') &gt;= 0)&amp;&amp;
- (document.documentElement)&amp;&amp;
- (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)&amp;&amp;
- (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 &quot;a&quot;. 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:
Deleted: svn:mime-type
## -1 +0,0 ##
-text/plain
\ No newline at end of property
Index: cljs/faq_notes/closures.html
===================================================================
--- cljs/faq_notes/closures.html (revision 43)
+++ cljs/faq_notes/closures.html (nonexistent)
@@ -1,1574 +0,0 @@
-<!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> &gt; <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 &quot;closure&quot; is an expression (typically a function) that
- can have free variables together with an environment that binds
- those variables (that &quot;closes&quot; 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, &quot;Native Object&quot;
-and &quot;Host Object&quot; with a sub-category of native objects called
-&quot;Built-in Object&quot; (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 &quot;testNumber&quot; can be created as:-
-</p>
-
-<pre>
-objectRef.testNumber = 5;
-<span class="commentJS">/* - or:- */</span>
-objectRef[&quot;testNumber&quot;] = 5;
-</pre>
-
-<p>
-The object had no &quot;testNumber&quot; 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[&quot;testNumber&quot;] = 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 &quot;constructor&quot; 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 &quot;constructor&quot; 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( &quot;String_Value&quot; );
-</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 &quot;testString&quot; so it is the value of
-that property, set to &quot;String_Value&quot;, 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
-&quot;testNumber&quot; 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 &quot;toString&quot;
-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
-&quot;madeUpPeoperty&quot; 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 &quot;testNumber&quot; 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
-&quot;testNumber&quot; 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
-&quot;Activation&quot; 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 &quot;arguments&quot;
-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 &quot;variable instantiation&quot; takes place using an object
-that ECMA 262 refers to as the &quot;Variable&quot; 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 &quot;exampleFunction&quot; 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 &quot;ActOuter2&quot; 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
-&quot;ActInner1&quot;), 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-&gt;</span>
-<span class="scopeCh">ActOuter1-&gt;</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 &quot;ActInner2&quot;, the scope chain
-becomes: <span class="scopeCh">ActInner2-&gt;</span>
-<span class="scopeCh">ActOuter2-&gt;</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 = [
- '&lt;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;\"&gt;&lt;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>
- '\"&gt;&lt;\/div&gt;'
- ];
- <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 &quot;circular&quot;
-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 -&gt;</span>
-<span class="scopeCh">function_object.[[scope]] -&gt;</span>
-<span class="scopeCh">scope_chain -&gt;</span>
-<span class="scopeCh">Activation_object.nodeRef -&gt;</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:
Deleted: svn:mime-type
## -1 +0,0 ##
-text/plain
\ No newline at end of property
Index: cljs/faq_notes/type_convert.html
===================================================================
--- cljs/faq_notes/type_convert.html (revision 43)
+++ cljs/faq_notes/type_convert.html (nonexistent)
@@ -1,1319 +0,0 @@
-<!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> &gt; <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>&quot;object&quot;</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">&quot;&quot;<br>(empty<br>string)</th>
- <th class="st">&quot;-1.6&quot;</th>
- <th class="st">&quot;0&quot;</th>
- <th class="st">&quot;1&quot;</th>
- <th class="st">&quot;1.6&quot;</th>
- <th class="st">&quot;8&quot;</th>
- <th class="st">&quot;16&quot;</th>
- <th class="st">&quot;16.8&quot;</th>
- <th class="st">&quot;123e-2&quot;</th>
- <th class="st">&quot;010&quot;<br>(Octal)</th>
- <th class="st">&quot;0x10&quot;<br>(Hex)</th>
- <th class="st">&quot;0xFF&quot;<br>(Hex)</th>
- <th class="st">&quot;-010&quot;</th>
- <th class="st">&quot;-0x10&quot;</th>
- <th class="st">&quot;xx&quot;</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 (&quot;&quot; + 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>&quot;&quot; + 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>&quot;1.23&quot;</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 (&quot;&quot; + 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>&quot;&quot; + 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 &quot;toString&quot; 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
-&quot;host objects&quot; 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">&quot;&quot;<br>(empty<br>string)</th>
- <th class="st">&quot;-1.6&quot;</th>
- <th class="st">&quot;0&quot;</th>
- <th class="st">&quot;1&quot;</th>
- <th class="st">&quot;1.6&quot;</th>
- <th class="st">&quot;8&quot;</th>
- <th class="st">&quot;16&quot;</th>
- <th class="st">&quot;16.8&quot;</th>
- <th class="st">&quot;123e-2&quot;</th>
- <th class="st">&quot;010&quot;<br>(Octal)</th>
- <th class="st">&quot;0x10&quot;<br>(Hex)</th>
- <th class="st">&quot;0xFF&quot;<br>(Hex)</th>
- <th class="st">&quot;-010&quot;</th>
- <th class="st">&quot;-0x10&quot;</th>
- <th class="st">&quot;xx&quot;</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>&quot;123e-2&quot;</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>&quot;34.5em&quot;</code>
-<code>parseFloat</code> would be able to ignore the <code>&quot;em&quot;</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">&quot;&quot;<br>(empty<br>string)</th>
- <th class="st">&quot;-1.6&quot;</th>
- <th class="st">&quot;0&quot;</th>
- <th class="st">&quot;1&quot;</th>
- <th class="st">&quot;1.6&quot;</th>
- <th class="st">&quot;8&quot;</th>
- <th class="st">&quot;16&quot;</th>
- <th class="st">&quot;16.8&quot;</th>
- <th class="st">&quot;123e-2&quot;</th>
- <th class="st">&quot;010&quot;<br>(Octal)</th>
- <th class="st">&quot;0x10&quot;<br>(Hex)</th>
- <th class="st">&quot;0xFF&quot;<br>(Hex)</th>
- <th class="st">&quot;-010&quot;</th>
- <th class="st">&quot;-0x10&quot;</th>
- <th class="st">&quot;xx&quot;</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>&quot;x&quot;</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>&quot;1.23&quot;</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">&quot;&quot;<br>(empty<br>string)</th>
- <th class="st">&quot;-1.6&quot;</th>
- <th class="st">&quot;0&quot;</th>
- <th class="st">&quot;1&quot;</th>
- <th class="st">&quot;1.6&quot;</th>
- <th class="st">&quot;8&quot;</th>
- <th class="st">&quot;16&quot;</th>
- <th class="st">&quot;16.8&quot;</th>
- <th class="st">&quot;123e-2&quot;</th>
- <th class="st">&quot;010&quot;<br>(Octal)</th>
- <th class="st">&quot;0x10&quot;<br>(Hex)</th>
- <th class="st">&quot;0xFF&quot;<br>(Hex)</th>
- <th class="st">&quot;-010&quot;</th>
- <th class="st">&quot;-0x10&quot;</th>
- <th class="st">&quot;xx&quot;</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">&quot;&quot;<br>(empty<br>string)</th>
- <th class="st">&quot;-1.6&quot;</th>
- <th class="st">&quot;0&quot;</th>
- <th class="st">&quot;1&quot;</th>
- <th class="st">&quot;1.6&quot;</th>
- <th class="st">&quot;8&quot;</th>
- <th class="st">&quot;16&quot;</th>
- <th class="st">&quot;16.8&quot;</th>
- <th class="st">&quot;123e-2&quot;</th>
- <th class="st">&quot;010&quot;<br>(Octal)</th>
- <th class="st">&quot;0x10&quot;<br>(Hex)</th>
- <th class="st">&quot;0xFF&quot;<br>(Hex)</th>
- <th class="st">&quot;-010&quot;</th>
- <th class="st">&quot;-0x10&quot;</th>
- <th class="st">&quot;xx&quot;</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>&quot;x&quot;</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">&quot;&quot;<br>(empty<br>string)</th>
- <th class="st">&quot;-1.6&quot;</th>
- <th class="st">&quot;0&quot;</th>
- <th class="st">&quot;1&quot;</th>
- <th class="st">&quot;1.6&quot;</th>
- <th class="st">&quot;8&quot;</th>
- <th class="st">&quot;16&quot;</th>
- <th class="st">&quot;16.8&quot;</th>
- <th class="st">&quot;123e-2&quot;</th>
- <th class="st">&quot;010&quot;<br>(Octal)</th>
- <th class="st">&quot;0x10&quot;<br>(Hex)</th>
- <th class="st">&quot;0xFF&quot;<br>(Hex)</th>
- <th class="st">&quot;-010&quot;</th>
- <th class="st">&quot;-0x10&quot;</th>
- <th class="st">&quot;xx&quot;</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>&quot;8&quot;</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">&quot;&quot;<br>(empty<br>string)</th>
- <th class="st">&quot;-1.6&quot;</th>
- <th class="st">&quot;0&quot;</th>
- <th class="st">&quot;1&quot;</th>
- <th class="st">&quot;1.6&quot;</th>
- <th class="st">&quot;8&quot;</th>
- <th class="st">&quot;16&quot;</th>
- <th class="st">&quot;16.8&quot;</th>
- <th class="st">&quot;123e-2&quot;</th>
- <th class="st">&quot;010&quot;<br>(Octal)</th>
- <th class="st">&quot;0x10&quot;<br>(Hex)</th>
- <th class="st">&quot;0xFF&quot;<br>(Hex)</th>
- <th class="st">&quot;-010&quot;</th>
- <th class="st">&quot;-0x10&quot;</th>
- <th class="st">&quot;xx&quot;</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 &plusmn;
-<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 &plusmn;<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">&quot;&quot;<br>(empty<br>string)</th>
- <th class="st">&quot;-1.6&quot;</th>
- <th class="st">&quot;0&quot;</th>
- <th class="st">&quot;1&quot;</th>
- <th class="st">&quot;1.6&quot;</th>
- <th class="st">&quot;8&quot;</th>
- <th class="st">&quot;16&quot;</th>
- <th class="st">&quot;16.8&quot;</th>
- <th class="st">&quot;123e-2&quot;</th>
- <th class="st">&quot;010&quot;<br>(Octal)</th>
- <th class="st">&quot;0x10&quot;<br>(Hex)</th>
- <th class="st">&quot;0xFF&quot;<br>(Hex)</th>
- <th class="st">&quot;-010&quot;</th>
- <th class="st">&quot;-0x10&quot;</th>
- <th class="st">&quot;xx&quot;</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>&lt;input type=&quot;text&quot;&gt;</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 &amp; 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:
Deleted: svn:mime-type
## -1 +0,0 ##
-text/plain
\ No newline at end of property
Index: cljs/faq_notes/form_access.html
===================================================================
--- cljs/faq_notes/form_access.html (revision 43)
+++ cljs/faq_notes/form_access.html (nonexistent)
@@ -1,729 +0,0 @@
-<!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> &gt; <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 &quot;convenience&quot; 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=&quot;myForm&quot;</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[&quot;myForm&quot;];
-
-<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[&quot;myForm&quot;];
-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=&quot;myControl&quot;</code> can be referenced as:-
-</p>
-
-<pre id="faInC_ex2">
-var controlElement = formElement.elements[&quot;myControl&quot;];
-</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[&quot;myForm&quot;];
-
-<span class="commentJS">/* instead of:- */ </span>
-
-var formElement = document.forms[&quot;myForm&quot;];
-</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=&quot;submit&quot;</code> with
-the <code>NAME</code> &quot;submit&quot;. 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>&quot;submit&quot;</code>. Unfortunately <code>FORM</code> elements
-already have a property with the name <code>&quot;submit&quot;</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=&quot;1&quot;</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[&quot;1&quot;]</code> (by the ECMAScript
-specification the preceding two property accessors are equivalent).
-Unless the control with the name <code>&quot;1&quot;</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 &quot;textField&quot;:
- */</span>
- var el = formRef &amp;&amp; formRef.elements[&quot;textField&quot;];
- <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);
-}
-...
-&lt;form action=&quot;http://example.com/somePage.asp&quot;
- onsubmit=&quot;return validateForm(this);&quot;&gt;
- &lt;input type=&quot;text&quot; name=&quot;textField&quot; value=&quot;&quot;&gt;
- &lt;input type=&quot;submit&quot; name=&quot;Submit_Button&quot; value=&quot;Submit&quot;&gt;
-&lt;/form&gt;
-</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>&quot;textField&quot;</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>&quot;form&quot;</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">
-&lt;form name=&quot;testForm&quot; action=&quot;http://example.com/somePage.jsp&quot;&gt;
- &lt;ul style=&quot;list-style-type:none;&quot;&gt;
- &lt;li&gt;&lt;input type=&quot;radio&quot; name=&quot;radioSet&quot; value=&quot;R1&quot;&gt;option 1&lt;/li&gt;
- &lt;li&gt;&lt;input type=&quot;radio&quot; name=&quot;radioSet&quot; value=&quot;R2&quot;&gt;option 2&lt;/li&gt;
- &lt;li&gt;&lt;input type=&quot;radio&quot; name=&quot;radioSet&quot; value=&quot;R3&quot;&gt;option 3&lt;/li&gt;
- &lt;li&gt;&lt;input type=&quot;radio&quot; name=&quot;radioSet&quot; value=&quot;R4&quot;&gt;option 4&lt;/li&gt;
- &lt;/ul&gt;
- &lt;input type=&quot;submit&quot name=&quot;Submit_Button&quot; value=&quot;Send&quot;&gt;
-&lt;/form&gt;
-</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>&quot;radioSet&quot;</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[&quot;testForm&quot;];
-if(frm){
- radioCollection = frm.elements[&quot;radioSet&quot;];
- 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 &lt; 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[&quot;testForm&quot;];
-if(frm){
- radioCollection = frm.elements[&quot;radioSet&quot;];
- 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 &quot;radioSet&quot;.
- 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 != &quot;number&quot;){
- <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 &lt; 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 != &quot;number&quot;)|| <span class="commentJS">//no length propety:</span>
- <span class="commentJS">/* or:- */</span>
- ((contrlCollection.options)&amp;&amp; <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[&quot;formName&quot;].elements[&quot;field1&quot;].value;
-var txt2 = document.forms[&quot;formName&quot;].elements[&quot;field2&quot;].value;
-var txt3 = document.forms[&quot;formName&quot;].elements[&quot;field3&quot;].value;
-var txt4 = document.forms[&quot;formName&quot;].elements[&quot;field4&quot;].value;
-var txt5 = document.forms[&quot;formName&quot;].elements[&quot;field5&quot;].value;
-</pre>
-
-<p id="faEff_3">
-The shortcut accessors require the resolution of fewer object
-references:-
-</p>
-
-<pre id="faEff_ex2">
-var txt1 = document[&quot;formName&quot;][&quot;field1&quot;].value;
-var txt2 = document[&quot;formName&quot;][&quot;field2&quot;].value;
-var txt3 = document[&quot;formName&quot;][&quot;field3&quot;].value;
-var txt4 = document[&quot;formName&quot;][&quot;field4&quot;].value;
-var txt5 = document[&quot;formName&quot;][&quot;field5&quot;].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[&quot;formName&quot;];
-var txt1 = frm.elements[&quot;field1&quot;].value;
-var txt2 = frm.elements[&quot;field2&quot;].value;
-var txt3 = frm.elements[&quot;field3&quot;].value;
-var txt4 = frm.elements[&quot;field4&quot;].value;
-var txt5 = frm.elements[&quot;field5&quot;].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[&quot;formName&quot;].elements;
-var txt1 = frmEls[&quot;field1&quot;].value;
-var txt2 = frmEls[&quot;field2&quot;].value;
-var txt3 = frmEls[&quot;field3&quot;].value;
-var txt4 = frmEls[&quot;field4&quot;].value;
-var txt5 = frmEls[&quot;field5&quot;].value;
-</pre>
-
-<p id="faEff_7">
-With the original long form accessor the resolution starts with
-resolving the <code>&quot;document&quot;</code> identifier. The
-identifier is first looked for among the local variables of the
-function (as a named property of the internal
-&quot;Variable&quot; 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>&quot;document&quot;</code> gets to the
-global object (at the end of the scope chain) it will find a property
-called <code>&quot;document&quot;</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>&quot;forms&quot;</code> and that is located as a property of the
-<code>document</code>. Then the <code>&quot;formName&quot;</code>
-property is identified in the <code>forms</code> collection. Next the
-<code>&quot;elements&quot;</code> property of the form is located,
-followed by the control name in that object and finally the
-<code>&quot;value&quot;</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>&quot;value&quot;</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:
Deleted: svn:mime-type
## -1 +0,0 ##
-text/plain
\ No newline at end of property