Annotation of books/www/chapters/ch05.html, revision 1.12

1.12    ! petejc      1:     <style type="text/css">
        !             2:       div.c15 {font-weight: bold; text-align: center}
        !             3:       div.c14 {text-align: center}
        !             4:     </style>
        !             5: 
        !             6:     <h2>Chapter 5</h2>
        !             7:     <h1><a name="77037"></a> Scripting Mozilla</h1>
        !             8:     <p>In Mozilla, scripting plays important roles in the XPFE.
        !             9:     Whether developers refer to script access and security, user
        !            10:     interface logic, XPCOM object invocation, or script execution
        !            11:     in element event handlers, scripting is so integral to
        !            12:     application development that Mozilla, as a development
        !            13:     platform, would be inconceivable without it.</p>
        !            14:     <p>The core scripting language used in Mozilla is JavaScript.
        !            15:     Although it has had a reputation as an unsophisticated language
        !            16:     used mostly in web pages, JavaScript is more like a first-tier
        !            17:     programming language. Modularity, good exception handing,
        !            18:     regular expression enhancement, and number formatting are just
        !            19:     some features of the new JavaScript 1.5,<a name="b260"></a><a
        !            20:     href="#260">[*]</a> which is based on the ECMA-262 standard.<a
        !            21:     name="b261"></a><a href="#261">[*]</a> JavaScript 2.0, due
        !            22:     sometime late in 2002, promises to be an even bigger promotion
        !            23:     of the language.</p>
        !            24:     <p>Three distinct levels of JavaScript are identified in this
        !            25:     chapter. A user interface level manipulates content through the
        !            26:     DOM, a client layer calls on the services provided by XPCOM,
        !            27:     and, finally, an application layer is available in which
        !            28:     JavaScript can create an XPCOM component. The following section
        !            29:     describes these levels in detail.</p>
        !            30:     <h2><a name="77038"></a> Faces of JavaScript in Mozilla</h2>
        !            31:     <p>As you have already 
        !            32:     <!--INDEX scripting:JavaScript, overview --> 
        !            33:     <!--INDEX JavaScript:overview --> seen in some examples in this
        !            34:     book, the user interface uses JavaScript extensively to create
        !            35:     behavior and to glue various widgets together into a coherent
        !            36:     whole. When you add code to the event handler of one element to
        !            37:     manipulate another-for example, when you update the value of a
        !            38:     textbox using a XUL button-you take advantage of this first
        !            39:     "level" of scriptability. In this role, JavaScript uses the
        !            40:     Document Object Model (DOM) to access parts of the user
        !            41:     interface as a hierarchical collection of objects. The section
        !            42:     <a href="#77054">"Adding Scripts to the UI</a>," later in this
        !            43:     chapter, discusses this highest level of scripting.</p>
        !            44:     <p>At a second level, JavaScript glues the entire user
        !            45:     interface to the XPCOM libraries beneath, which create the
        !            46:     application core. At this level, XPConnect (see the section <a
        !            47:     href="#77066">"What Is XPConnect?</a>" later in this chapter)
        !            48:     provides a bridge that makes these components "scriptable,"
        !            49:     which means that they can be invoked from JavaScript and used
        !            50:     from the user interface layer. When JavaScript calls methods
        !            51:     and gets data from scriptable components, it uses this second
        !            52:     layer of scriptability.</p>
        !            53:     <p>Finally, at the third and ultimate level of Mozilla
        !            54:     scripting, JavaScript can be used as a "first-order" language
        !            55:     for creating the application core itself, for writing software
        !            56:     components or libraries whose services are called. We discuss
        !            57:     this third level of scripting and provide a long example in the
        !            58:     section <a href="ch08.html#77065">"Creating a JavaScript XPCOM
        !            59:     Component</a>" in <a href="ch08.html#77048">Chapter 8</a>.</p>
        !            60:     <p>When you use JavaScript in these contexts, the application
        !            61:     architecture looks something like <a href="#77002">Figure
        !            62:     5-1</a>, in which scripting binds the user interface to the
        !            63:     application core through XPConnect and can reside as a software
        !            64:     component using such technologies as XPIDL and XPCOM.</p>
        !            65:     <div class="c14">
        !            66:       <img src="foo.gif">
        !            67:     </div>
        !            68:     <p><i>Figure 5-1: <a name="77002"></a></i> <i>Scripting in
        !            69:     Mozilla</i></p>
        !            70:     <h2><a name="77039"></a> JavaScript and the DOM</h2>
        !            71:     <p>In the application 
        !            72:     <!--INDEX DOM (Document Object Model):overview --> layer of
        !            73:     Mozilla, there is little distinction between a web page and the
        !            74:     graphical user interface. Mozilla's implementation of the DOM
        !            75:     is fundamentally the same for both XUL and HTML. In both cases,
        !            76:     state changes and events are propagated through various DOM
        !            77:     calls, meaning that the UI itself is content-not unlike that of
        !            78:     a web page. In application development, where the difference
        !            79:     between application "chrome" and rendered content is typically
        !            80:     big, this uniformity is a significant step forward.</p>
        !            81:     <h3><a name="77040"></a> What Is the DOM?</h3>
        !            82:     <p>The DOM is an API used to access HTML and XML documents. It
        !            83:     does two things for web developers: provides a structural
        !            84:     representation of the document and defines the way the
        !            85:     structure should be accessed from script. In the Mozilla XPFE
        !            86:     framework, this functionality allows you to manipulate the user
        !            87:     interface as a structured group of nodes, create new UI and
        !            88:     content, and remove elements as needed.</p>
        !            89:     <p>Because it is designed to access arbitrary HTML and XML, the
        !            90:     DOM applies not only to XUL, but also to MathML, SVG, and other
        !            91:     XML markup. By connecting web pages and XML documents to
        !            92:     scripts or programming languages, the DOM is not a particular
        !            93:     application, product, or proprietary ordering of web pages.
        !            94:     Rather, it is an <i>API-</i>an interface that vendors must
        !            95:     implement if their products are to conform to the W3C DOM
        !            96:     standard. Mozilla's commitment to standards ensures that its
        !            97:     applications and tools do just that.</p>
        !            98:     <p>When you use JavaScript to create new elements in an HTML
        !            99:     file or change the attributes of a XUL <tt>button</tt>, you
        !           100:     access an object model in which these structures are organized.
        !           101:     This model is the DOM for that document or data. The DOM
        !           102:     provides a context for the scripting language to operate in.
        !           103:     The specific context for web and XML documents-the top-level
        !           104:     <tt>window</tt> object, the elements that make up a web
        !           105:     document, and the data stored in those elements as children-is
        !           106:     standardized in several different specifications, the most
        !           107:     recent of which is the upcoming DOM Level 3 standard.</p>
        !           108:     <h3><a name="77041"></a> The DOM Standards and Mozilla</h3>
        !           109:     <p>The DOM <!--INDEX DOM (Document Object Model):levels --> 
        !           110:     <!--INDEX standards, DOM levels --> specifications are split
        !           111:     into different levels overseen by the W3C. Each level provides
        !           112:     its own features and Mozilla has varying, but nearly complete,
        !           113:     levels of support for each. Currently, Mozilla's support for
        !           114:     the DOM can be summarized as follows:</p>
        !           115:     <ul>
        !           116:       <li>DOM Level 1: Excellent</li>
        !           117:       <li>DOM Level 2: Good</li>
        !           118:       <li>DOM Level 3: Poor; under construction</li>
        !           119:     </ul>
        !           120:     <p>Mozilla strives to be standards-compliant, but typically
        !           121:     reaches full support only when those standards have become
        !           122:     recommendations rather than working drafts. Currently, Level 1
        !           123:     and Level 2 are recommendations and Level 3 is a working
        !           124:     draft.</p>
        !           125:     <p>Standards like the DOM make Mozilla an especially attractive
        !           126:     software development kit (SDK) for web developers. The same
        !           127:     layout engine that renders web content also draws the GUI and
        !           128:     pushes web development out of the web page into the application
        !           129:     chrome. The DOM provides a consistent, unified interface for
        !           130:     accessing all the documents you develop, making the content and
        !           131:     chrome accessible for easy cross-platform development and
        !           132:     deployment.</p>
        !           133:     <h3><a name="77042"></a> DOM Methods and Properties</h3>
        !           134:     <p>Methods in <!--INDEX DOM (Document Object Model):methods -->
        !           135:     <!--INDEX methods:DOM --> the DOM allow you to access and
        !           136:     manipulate any element in the user interface or in the content
        !           137:     of a web page. Getting and setting attributes, creating
        !           138:     elements, hiding elements, and appending children all involve
        !           139:     direct manipulation of the DOM. The DOM mediates all
        !           140:     interaction between scripts and the interface itself, so even
        !           141:     when you do something as simple as changing an image when the
        !           142:     user clicks a button, you use the DOM to register an event
        !           143:     handler with the <tt>button</tt> and DOM attributes on the
        !           144:     <tt>image</tt> element to change its source.</p>
        !           145:     <p>The DOM Level 1 and Level 2 Core specifications contain
        !           146:     multiple interfaces, including <i>Node</i>, <i>NodeList</i>,
        !           147:     <i>Element</i>, and <i>Document</i>. The following sections
        !           148:     describe some interface methods used to manipulate the object
        !           149:     model of application chrome, documents, or metadata in Mozilla.
        !           150:     The <i>Document</i> and <i>Element</i> interfaces, in
        !           151:     particular, contain useful methods for XUL developers.</p>
        !           152:     <h4><a name="77043"></a> Using dump( ) to print to STDOUT</h4>
        !           153:     <p>The code <!--INDEX STDOUT, printing and --> 
        !           154:     <!--INDEX printing, STDOUT --> <!--INDEX dump( ) method --> 
        !           155:     <!--INDEX DOM (Document Object Model):methods:printing STDOUT -->
        !           156:     <!--INDEX methods:DOM:printing STDOUT --> samples in this
        !           157:     chapter use a method called <tt>dump( )</tt> to print data to
        !           158:     STDOUT. This method is primarily used for debugging your code
        !           159:     and is turned on using a <tt>PREF</tt>. You can turn this
        !           160:     <tt>PREF</tt> on using the following code:</p>
        !           161: <pre>
        !           162: const PREFS_CID      = "@mozilla.org/preferences;1";
1.1       david     163: const PREFS_I_PREF   = "nsIPref";
                    164: const PREF_STRING    = "browser.dom.window.dump.enabled";
                    165: try {
                    166: var Pref        = new Components.Constructor(PREFS_CID, PREFS_I_PREF);
                    167: var pref        = new Pref( );
                    168: pref.SetBoolPref(PREF_STRING, true);
1.12    ! petejc    169: } catch(e) {}
        !           170: </pre>
        !           171:     <p>This code is necessary only if you are doing development
        !           172:     with a release distribution build of Mozilla. If you are using
        !           173:     a debug or nightly build, this <tt>PREF</tt> can be set from
        !           174:     the preferences panel by selecting Edit &gt; Preferences &gt;
        !           175:     Debug &gt; Enable JavaScript dump( ) output.</p>
        !           176:     <h4><a name="77044"></a> getElementById</h4>
        !           177:     <p><tt>getElementById(aId)</tt> is 
        !           178:     <!--INDEX elements:referencing --> 
        !           179:     <!--INDEX referencing:elements --> 
        !           180:     <!--INDEX getElementById( ) method --> 
        !           181:     <!--INDEX DOM (Document Object Model):methods:referencing elements -->
        !           182:     <!--INDEX methods:DOM:referencing elements --> perhaps the most
        !           183:     commonly used DOM method in any programming domain. This is a
        !           184:     convenient way to get a reference to an element object by
        !           185:     passing that element's <tt>id</tt> as an argument, where the
        !           186:     <tt>id</tt> acts as a unique identifier for that element.</p>
        !           187:     <p>DOM calls like this are at the heart of Mozilla UI
        !           188:     functionality. <tt>getElementById</tt> is the main programmatic
        !           189:     entry point into the chrome and is essential for any dynamic
        !           190:     manipulation of XUL elements. For example, to get a box element
        !           191:     in script (i.e., to get a reference to it so you can call its
        !           192:     methods or read data from it), you must refer to it by using
        !           193:     the box <tt>id</tt>:</p>
        !           194: <pre>
        !           195: &lt;box id="my-id" /&gt;
        !           196: </pre>
        !           197:     <p>Since the return value of <tt>getElementById</tt> is a
        !           198:     reference to the specified element object, you usually assign
        !           199:     it to a variable like this:</p>
        !           200: <pre>
        !           201: var boxEl = document.getElementById('my-id');
1.1       david     202: dump("boxEl="+boxEl+"\n");
1.12    ! petejc    203: console output: boxEl=[object XULElement]
        !           204: </pre>
        !           205:     <p>Once you have the box element available as <tt>boxEl</tt>,
        !           206:     you can use other DOM methods like <tt>getAttribute</tt> and
        !           207:     <tt>setAttribute</tt> to change its layout, its position, its
        !           208:     state, or other features.</p>
        !           209:     <h4><a name="77045"></a> getAttribute</h4>
        !           210:     <p>Attributes <!--INDEX attributes:referencing --> 
        !           211:     <!--INDEX referencing:attributes --> 
        !           212:     <!--INDEX getAttribute( ) method --> 
        !           213:     <!--INDEX DOM (Document Object Model):methods:referencing attributes -->
        !           214:     <!--INDEX methods:DOM:referencing attributes --> are properties
        !           215:     that are defined directly on an element. XUL elements have
        !           216:     attributes such as <tt>disabled</tt>, <tt>height</tt>,
        !           217:     <tt>style</tt>, <tt>orient</tt>, and <tt>label</tt>.</p>
        !           218: <pre>
        !           219: &lt;box id="my-id" foo="hello 1" bar="hello 2" /&gt;
        !           220: </pre>
        !           221:     <p>In the snippet above, the strings "my-id," "hello 1," and
        !           222:     "hello 2" are values of the box element attributes. Note that
        !           223:     Gecko does not enforce a set of attributes for XUL elements.
        !           224:     XUL documents must be well-formed, but they are not validated
        !           225:     against any particular XUL DTD or schema. This lack of
        !           226:     enforcement means that attributes can be placed on elements ad
        !           227:     hoc. Although this placement can be confusing, particularly
        !           228:     when you look at the source code for the Mozilla browser
        !           229:     itself, it can be very helpful when you create your own
        !           230:     applications and want to track the data that interests you.</p>
        !           231:     <p>Once you have an object assigned to a variable, you can use
        !           232:     the DOM method <tt>getAttribute</tt> to get a reference to any
        !           233:     attribute in that object. The <tt>getAttribute</tt> method
        !           234:     takes the name of the desired attribute as a string. For
        !           235:     example, if you add an attribute called <tt>foo</tt> to a box
        !           236:     element, you can access that attribute's value and assign it to
        !           237:     a variable:</p>
        !           238: <pre>
        !           239: &lt;box id="my-id" foo="this is the foo attribute" /&gt;
1.1       david     240: &lt;script&gt;
                    241: var boxEl = document.getElementById('my-id');
1.12    ! petejc    242:  var foo   = boxEl.getAttribute('foo');
        !           243:  dump(foo+'\n');
        !           244: &lt;/script&gt;
        !           245: </pre>
        !           246:     <p>The <tt>dump</tt> method outputs the string "this is the foo
        !           247:     attribute," which is the value of the attribute <tt>foo</tt>.
        !           248:     You can also add or change existing attributes with the
        !           249:     <tt>setAttribute</tt> DOM method.</p>
        !           250:     <h4><a name="77046"></a> setAttribute</h4>
        !           251:     <p>The <tt>setAttribute</tt> 
        !           252:     <!--INDEX attributes:changing values --> 
        !           253:     <!--INDEX setAttribute( ) method --> 
        !           254:     <!--INDEX DOM (Document Object Model):methods:changing attribute values -->
        !           255:     <!--INDEX methods:DOM:changing attribute values --> method
        !           256:     changes an existing attribute value. This method is useful for
        !           257:     changing the state of an element-its visibility, size, order
        !           258:     within a parent, layout and position, style, etc. It takes two
        !           259:     arguments: the attribute name and the new value.</p>
        !           260: <pre>
        !           261: &lt;box id="my-id" foo="this is the foo attribute" /&gt;
1.1       david     262: &lt;script&gt;
                    263: boxEl=document.getElementById('my-id');
                    264: boxEl.setAttribute('foo', 'this is the foo attribute changed');
                    265: var foo = boxEl.getAttribute('foo');
                    266: dump(foo+'\n');
1.12    ! petejc    267: &lt;/script&gt;
        !           268: </pre>
        !           269:     <p>The script above outputs the string "this is the foo
        !           270:     attribute changed" to the console. You can also use
        !           271:     <tt>setAttribute</tt> to create a new attribute if it does not
        !           272:     already exist:</p>
        !           273: <pre>
        !           274: &lt;box id="my-id" /&gt;
1.1       david     275: &lt;script&gt;
                    276: boxEl=document.getElementById('my-id');
                    277: boxEl.setAttribute('bar', 'this is the new attribute bar');
1.12    ! petejc    278: &lt;/script&gt;
        !           279: </pre>
        !           280:     <p>By setting an attribute that doesn't already exist, you
        !           281:     create it dynamically, adding a value to the hierarchical
        !           282:     representation of nodes that form the current document object.
        !           283:     After this code is executed, the <tt>boxEl</tt> element is the
        !           284:     same as an element whose <tt>bar</tt> attribute was hardcoded
        !           285:     into the XUL:</p>
        !           286: <pre>
        !           287: &lt;box id="my-id" bar="this is the new attribute bar" /&gt;
        !           288: </pre>
        !           289:     <p>These sorts of ad hoc changes give you complete control over
        !           290:     the state of the application interface.</p>
        !           291:     <h4><a name="77047"></a> createElement</h4>
        !           292:     <p>If you <!--INDEX elements:creating --> 
        !           293:     <!--INDEX createElement( ) method --> 
        !           294:     <!--INDEX DOM (Document Object Model):methods:creating elements -->
        !           295:     <!--INDEX methods:DOM:creating elements --> need to dynamically
        !           296:     create an element that doesn't already exist-for example, to
        !           297:     add a new row to a table displaying rows of information, you
        !           298:     can use the method <tt>createElement</tt>. To create and add a
        !           299:     text element to your box example, for example, you can use the
        !           300:     following code:</p>
        !           301: <pre>
        !           302: &lt;box id="my-id" /&gt;
1.1       david     303: &lt;script&gt;
                    304: boxEl = document.getElementById('my-id');
                    305: var textEl  = document.createElement('description');
                    306: boxEl.appendChild(textEl);
1.12    ! petejc    307: &lt;/script&gt;
        !           308: </pre>
        !           309:     <p>Once you create the new element and assign it to the
        !           310:     <tt>textEl</tt> variable, you can use <tt>appendChild</tt> to
        !           311:     insert it into the object tree. In this case, it is appended to
        !           312:     <tt>boxEl</tt>, which becomes the insertion point.</p>
        !           313:     <blockquote>
        !           314:       <div class="c15">
        !           315:         NOTE
        !           316:       </div>
        !           317:       <p>For mixed namespace documents like XUL and HTML, you can
        !           318:       use a variation of <tt>createElement</tt> called
        !           319:       <tt>createElementNS</tt>. To create a mixed namespace
        !           320:       element, use this code:</p>
        !           321:     </blockquote>
        !           322:     var node = document.createElementNS('<a href=
        !           323:     "http://www.w3.org/1999.xhtml">http://www.w3.org/1999.xhtml</a>',
        !           324:     'html:div'); 
        !           325:     <blockquote>
        !           326:       <p>Namespace variations for other functions include
        !           327:       <tt>setAttributeNS</tt>, <tt>getElementsByTagNameNS</tt>, and
        !           328:       <tt>hasAttributeNS</tt>.</p>
        !           329:     </blockquote>
        !           330:     <h4><a name="77048"></a> createTextNode</h4>
        !           331:     <p>In <!--INDEX text nodes, creating --> 
        !           332:     <!--INDEX createTextNode( ) method --> 
        !           333:     <!--INDEX DOM (Document Object Model):methods:creating text nodes -->
        !           334:     <!--INDEX methods:DOM:creating text nodes --> addition to
        !           335:     setting the <tt>label</tt> attribute on an element, you can
        !           336:     create new text in the interface by using the DOM method
        !           337:     <tt>createTextNode</tt>, as shown in the following example:</p>
        !           338: <pre>
        !           339: &lt;description id="explain" /&gt;
1.1       david     340: &lt;script&gt;
                    341: var description = document.getElementById("explain");
                    342: if (description) {
                    343: if (!description.childNodes.length) {
                    344: var textNode = document.createTextNode("Newly text");
                    345: description.appendChild(textNode);
                    346: }
                    347: else if (description.childNodes.length == 1 ) {
                    348: description.childNodes[0].nodeValue = "Replacement text";
                    349: }
                    350: }
1.12    ! petejc    351: &lt;/script&gt;
        !           352: </pre>
        !           353:     <p>Notice the use of <tt>appendChild</tt>. This method,
        !           354:     discussed next, is used to insert the new element or text node
        !           355:     into the DOM tree after it is created. Create-and-append is a
        !           356:     common two-step process for adding new elements to the object
        !           357:     model.</p>
        !           358:     <h4><a name="77049"></a> appendChild</h4>
        !           359:     <p>To dynamically <!--INDEX elements:adding dynamically --> 
        !           360:     <!--INDEX appendChild( ) method --> 
        !           361:     <!--INDEX DOM (Document Object Model):methods:adding elements dynamically -->
        !           362:     <!--INDEX methods:DOM:adding elements dynamically --> add an
        !           363:     element to a document, you need to use the method
        !           364:     <tt>appendChild( )</tt>. This method adds a newly created
        !           365:     element to an existing parent node by appending to it. If a
        !           366:     visible widget is added, this change is visible in the
        !           367:     interface immediately.</p>
        !           368: <pre>
        !           369: &lt;groupbox id="my-id" /&gt;
1.1       david     370: &lt;script&gt;
                    371: var existingEl  = document.getElementById('my-id');
                    372: var captionEl   = document.createElement('caption');
                    373: existingEl.appendChild(captionEl);
                    374: captionEl.setAttribute('label', 'This is a new caption');
                    375: captionEl.setAttribute('style', 'color: blue;');
1.12    ! petejc    376: &lt;/script&gt;
        !           377: </pre>
        !           378:     <p>This example creates a new element, gets an existing parent
        !           379:     element from the document, and then uses <tt>appendChild(
        !           380:     )</tt> to insert that new element into the document. It also
        !           381:     uses <tt>setAttribute</tt> to add an attribute value and some
        !           382:     CSS style rules, which can highlight the new element in the
        !           383:     existing interface.</p>
        !           384:     <h4><a name="77050"></a> cloneNode</h4>
        !           385:     <p>For <!--INDEX nodes:copying --> 
        !           386:     <!--INDEX cloneNode( ) method --> 
        !           387:     <!--INDEX DOM (Document Object Model):methods:copying nodes -->
        !           388:     <!--INDEX methods:DOM:copying nodes --> elements that already
        !           389:     exist, a copy method allows you to duplicate elements to avoid
        !           390:     having to recreate them from scratch. <tt>cloneNode</tt>, which
        !           391:     is a method on the <tt>element</tt> object rather than the
        !           392:     <tt>document</tt>, returns a copy of the given node.</p>
        !           393: <pre>
        !           394: &lt;script&gt;
1.1       david     395: // this is untested --pete
                    396: var element = document.getElementById('my-id');
                    397: var clone = element.cloneNode(false);
                    398: dump(`element='+element+'\n');
                    399: dump(`clone='+clone+'\n');
1.12    ! petejc    400: &lt;/script&gt;
        !           401: </pre>
        !           402:     <p>The method takes a Boolean-optional parameter that specifies
        !           403:     whether the copy is "deep." Deep copies duplicate all
        !           404:     descendants of a node as well as the node itself.</p>
        !           405:     <h4><a name="77051"></a> getElementsByTagName</h4>
        !           406:     <p>Another <!--INDEX elements:arrays, returning --> 
        !           407:     <!--INDEX getElementsByTagName( ) method --> 
        !           408:     <!--INDEX DOM (Document Object Model):methods:returning element arrays -->
        !           409:     <!--INDEX methods:DOM:returning element arrays --> very useful
        !           410:     method is <tt>getElementsByTagName</tt>. This method returns an
        !           411:     array of elements of the specified type. The argument used is
        !           412:     the string <i>element type</i>. "box," for example, could be
        !           413:     used to obtain an array of all boxes in a document. The array
        !           414:     is zero-based, so the elements start at 0 and end with the last
        !           415:     occurrence of the element in the document. If you have three
        !           416:     boxes in a document and want to reference each box, you can do
        !           417:     it as follows:</p>
        !           418: <pre>
        !           419: &lt;box id="box-one" /&gt;
1.1       david     420: &lt;box id="box-two" /&gt;
                    421: &lt;box id="box-three" /&gt;
                    422: &lt;script&gt;
                    423: document.getElementsByTagName('box')[0];
                    424: document.getElementsByTagName('box')[1];
                    425: document.getElementsByTagName('box')[2];
1.12    ! petejc    426: &lt;/script&gt;
        !           427: </pre>
        !           428:     <p>Or you can get the array and index into it like this:</p>
        !           429: <pre>
        !           430: var box = document.getElementsByTagName('box');
        !           431: </pre>
        !           432:     <p>box[0], the first object in the returned array, is a XUL
        !           433:     box.</p>
        !           434:     <p>To see the number of boxes on a page, you can use the
        !           435:     <tt>length</tt> property of an array:</p>
        !           436: <pre>
        !           437: var len = document.getElementsByTagName('box').length;
1.5       petejc    438: dump(len+'\n');
1.12    ! petejc    439: console output: 3
        !           440: </pre>
        !           441:     <p>To output the <tt>id</tt> of the box:</p>
        !           442: <pre>
        !           443: &lt;box id="box-one" /&gt;
1.1       david     444: &lt;box id="box-two" /&gt;
                    445: &lt;box id="box-three" /&gt;
                    446: &lt;script&gt;
                    447: var el      = document.getElementsByTagName('box');
                    448: var tagId   = el[0].id;
                    449: dump(tagId+"\n");
                    450: &lt;/script&gt;
1.12    ! petejc    451: console output: box-one
        !           452: </pre>
        !           453:     <p>To get to an attribute of the second box:</p>
        !           454: <pre>
        !           455: &lt;box id="box-one" /&gt;
1.1       david     456: &lt;box id="box-two" foo="some attribute for the second box" /&gt;
                    457: &lt;box id="box-three" /&gt;
                    458: &lt;script&gt;
                    459: var el        = document.getElementsByTagName('box');
                    460: var att       = el[1].getAttribute('foo');
                    461: dump(att      +"\n");
                    462: &lt;/script&gt;
1.12    ! petejc    463: console output: some attribute for the second box
        !           464: </pre>
        !           465:     <p><tt>getElementsByTagName</tt> is a handy way to obtain DOM
        !           466:     elements without using <tt>getElementById</tt>. Not all
        !           467:     elements have <tt>id</tt> attributes, so other means of getting
        !           468:     at the elements must be used occasionally.<a name="b262"></a><a
        !           469:     href="#262">[*]</a></p>
        !           470:     <h4><a name="77052"></a> Getting an element object and its
        !           471:     properties</h4>
        !           472:     <p>In addition <!--INDEX properties:elements:viewing --> 
        !           473:     <!--INDEX elements:properties:viewing --> to a basic set of
        !           474:     attributes, an element may have many properties. These
        !           475:     properties don't typically appear in the markup for the
        !           476:     element, so they can be harder to learn and remember. To see
        !           477:     the properties of an element object node, however, you can use
        !           478:     a JavaScript <tt>for</tt> <tt>in</tt> loop to iterate through
        !           479:     the list, as shown in <a href="#77012">Example 5-1</a>.</p>
        !           480:     <p><i>Example 5-1: <a name="77012"></a></i> <i>Printing element
        !           481:     properties to the console</i></p>
        !           482: <pre>
        !           483:  &lt;box id="my-id" /&gt;
1.1       david     484:  &lt;script&gt;
                    485:    var el = document.getElementById('my-id');
                    486:    for (var list in el)
                    487:      dump("property  = "+list+"\n");
                    488:  &lt;/script&gt;
                    489:  console output(subset):
                    490:  property = id
                    491:  property = className
                    492:  property = style
                    493:  property = boxObject
                    494:  property = tagName
                    495:  property = nodeName
1.12    ! petejc    496:  . . .
        !           497: </pre>
        !           498:     <p>Note the implicit functionality in the <tt>el</tt> object
        !           499:     itself: when you iterate over the object reference, you ask for
        !           500:     all members of the class of which that object is an instance.
        !           501:     This simple example "spells" the object out to the console.
        !           502:     Since the DOM recognizes the window as another element (albeit
        !           503:     the root element) in the Document Object Model, you can use a
        !           504:     similar script in <a href="#77014">Example 5-2</a> to get the
        !           505:     properties of the window itself.</p>
        !           506:     <p><i>Example 5-2: <a name="77014"></a></i> <i>Printing the
        !           507:     window properties</i></p>
        !           508: <pre>
        !           509:  &lt;script&gt;
1.1       david     510:    var el        = document.getElementById('test-win');
                    511:    for(var list in el)
                    512:      dump("property  = "+list+"\n");
                    513:  &lt;/script&gt;
1.12    ! petejc    514:  &lt;/td&gt;console output(subset):
1.1       david     515:  property = nodeName
                    516:  property = nodeValue
                    517:  property = nodeType
                    518:  property = parentNode
                    519:  property = childNodes
                    520:  property = firstChild
1.12    ! petejc    521:  . . .
        !           522: </pre>
        !           523:     <p>The output in <a href="#77014">Example 5-2</a> is a small
        !           524:     subset of all the DOM properties associated with a XUL window
        !           525:     and the other XUL elements, but you can see all of them if you
        !           526:     run the example. Analyzing output like this can familiarize you
        !           527:     with the interfaces available from <tt>window</tt> and other
        !           528:     DOM objects.</p>
        !           529:     <h4><a name="77053"></a> Retrieving elements by property</h4>
        !           530:     <p>You can also use a 
        !           531:     <!--INDEX properties:elements:returning --> 
        !           532:     <!--INDEX elements:properties:returning --> DOM method to
        !           533:     access elements with specific properties by using
        !           534:     <tt>getElementsByAttribute</tt>. This method takes the name and
        !           535:     value of the attribute as arguments and returns an array of
        !           536:     nodes that contain these attribute values:</p>
        !           537: <pre>
        !           538: &lt;checkbox id="box-one" /&gt;
1.1       david     539: &lt;checkbox id="box-two" checked="true"/&gt;
                    540: &lt;checkbox id="box-three" checked="true"/&gt;
                    541: &lt;script&gt;
                    542: var chcks = document.getElementsByAttribute("checked", "true");
                    543: var count = chcks.length;
                    544: dump(count + " items checked \n");
1.12    ! petejc    545: &lt;/script&gt;
        !           546: </pre>
        !           547:     <p>One interesting use of this method is to toggle the state of
        !           548:     elements in an interface, as when you get all menu items whose
        !           549:     <tt>disabled</tt> attribute is set to true and set them to
        !           550:     false. In the xFly sample, you can add this functionality with
        !           551:     a few simple updates. In the <i>xfly.js</i> file in the xFly
        !           552:     package, add the function defined in <a href="#77016">Example
        !           553:     5-3</a>.</p>
        !           554:     <p><i>Example 5-3: <a name="77016"></a></i> <i>Adding toggle
        !           555:     functionality to xFly</i></p>
        !           556: <pre>
        !           557:  function toggleCheck( ) {
1.1       david     558:    // get the elements before you make any changes
                    559:    var chex   = document.getElementsByAttribute("disabled", "true");
                    560:    var unchex = document.getElementsByAttribute("disabled", "false");
                    561:    for (var i=0; i&lt;chex.length; i++)
1.12    ! petejc    562:        chex&lt;/td&gt;[i].setAttributte("checked", "false");
1.1       david     563:    for (var i=0; i&lt;unchex.length; i++)
1.12    ! petejc    564:        unchex&lt;/td&gt;[i].setAttributte("checked", "true");
        !           565:  }
        !           566: </pre>
        !           567:     <p>Although this example doesn't update elements whose
        !           568:     <tt>disabled</tt> attribute is not specified, you can call this
        !           569:     function from a new menu item and have it update all menus
        !           570:     whose checked state you do monitor, as shown in <a href=
        !           571:     "#77018">Example 5-4</a>.</p>
        !           572:     <p><i>Example 5-4: <a name="77018"></a></i> <i>Adding Toggle
        !           573:     menus to xFly</i></p>
        !           574: <pre>
        !           575:  &lt;menubar id="appbar"&gt;
1.1       david     576:    &lt;menu label="File"&gt;
                    577:       &lt;menupopup&gt;
                    578:         &lt;menuitem label="New"/&gt;
                    579:         &lt;menuitem label="Open"/&gt;
                    580:       &lt;/menupopup&gt;
                    581:    &lt;/menu&gt;
                    582:    &lt;menu label="Edit"&gt;
                    583:       &lt;menupopup&gt;
                    584:         &lt;menuitem label="Toggle" oncommand="toggleCheck( );" /&gt;
                    585:       &lt;/menupopup&gt;
                    586:    &lt;/menu&gt;
                    587:    &lt;menu label="Fly Types"&gt;
                    588:       &lt;menupopup&gt;
                    589:         &lt;menuitem label="House" disabled="true" /&gt;
                    590:         &lt;menuitem label="Horse" disabled="true" /&gt;
                    591:         &lt;menuitem label="Fruit" disabled="false" /&gt;
                    592:       &lt;/menupopup&gt;
                    593:    &lt;/menu&gt;
1.12    ! petejc    594:  &lt;/menubar&gt;
        !           595: </pre>
        !           596:     <p>When you add this to the xFly application window (from <a
        !           597:     href="ch02.html#77034">Example 2-10</a>, for example, above the
        !           598:     basic <tt>vbox</tt> structure), you get an application menu bar
        !           599:     with a menu item, Toggle, that reverses the checked state of
        !           600:     the three items in the "Fly Types" menu, as seen in <a href=
        !           601:     "#77004">Figure 5-2</a>.</p>
        !           602:     <div class="c14">
        !           603:       <img src="foo.gif">
        !           604:     </div>
        !           605:     <p><i>Figure 5-2: <a name="77004"></a></i> <i>Toggling the
        !           606:     state of menu items in xFly</i></p>
        !           607:     <p>The following section explains more about hooking scripts up
        !           608:     to the interface. Needless to say, when you use a method like
        !           609:     <tt>getElementsByAttribute</tt> that operates on all elements
        !           610:     with a particular attribute value, you must be careful not to
        !           611:     grab elements you didn't intend (like a button elsewhere in the
        !           612:     application that gets disabled for other purpose).</p>
        !           613:     <h2><a name="77054"></a> Adding Scripts to the UI</h2>
        !           614:     <p>Once you are comfortable with how JavaScript works in the
        !           615:     context of the user interface layer and are familiar with some
        !           616:     of the primary DOM methods used to manipulate the various
        !           617:     elements and attributes, you can add your own scripts to your
        !           618:     application. Though you can use other techniques to get scripts
        !           619:     into the UI, one of the most common methods is to use Mozilla's
        !           620:     event model, which is described in the next few sections.</p>
        !           621:     <h3><a name="77055"></a> Handling Events from a XUL
        !           622:     Element</h3>
        !           623:     <p><i>Events</i> are input 
        !           624:     <!--INDEX scripts:adding to UI, event handling and --> 
        !           625:     <!--INDEX event handling:adding scripts to UI --> messages 
        !           626:     <!--INDEX XUL (XML-based User-interface Language):elements:event handling -->
        !           627:     that pass information from the user interface to the
        !           628:     application code. Capturing this information, or <i>event
        !           629:     handling</i>, is how you usually tell scripts when to start and
        !           630:     stop.</p>
        !           631:     <p>When the user clicks a XUL button, for instance, the button
        !           632:     "listens" for the click event, and may also handle that event.
        !           633:     If the button itself does not handle the event (e.g., by
        !           634:     supplying executable JavaScript in an event handler attribute),
        !           635:     then the event "bubbles," or travels further up into the
        !           636:     hierarchy of elements above the button. The event handlers in
        !           637:     <a href="#77016">Example 5-3</a> use simple inline JavaScript
        !           638:     to show that the given event (e.g., the window loading in the
        !           639:     first example, the button getting clicked in the second, and so
        !           640:     on) was fired and handled.</p>
        !           641:     <p>As in HTML, predefined event handlers are available as
        !           642:     attributes on a XUL element. These attributes are entry points
        !           643:     where you can hook in your JavaScript code, as these examples
        !           644:     show. Note that event handler attributes are technically a
        !           645:     shortcut, for which the alternative is to register event
        !           646:     listeners explicitly to specified elements. The value of these
        !           647:     on[event] event handler attributes is the inline JavaScript
        !           648:     that should be executed when that event is triggered. <a href=
        !           649:     "#77020">Example 5-5</a> shows some basic button activation
        !           650:     events.</p>
        !           651:     <p><i>Example 5-5: <a name="77020"></a></i> <i>Basic event
        !           652:     handler attributes</i></p>
        !           653: <pre>
        !           654:  &lt;window onload="dump('this window has loaded\n');" /&gt;
1.1       david     655:  &lt;button label="onclick-test"
                    656:     onclick="dump('The event handler onclick has just been used\n');" /&gt;
                    657:  &lt;button label="oncommand-test"
                    658:     oncommand="dump('The event handler oncommand has just been used\n');" /&gt;
                    659:  &lt;menulist id="custom"
1.12    ! petejc    660:     onchange="doMyCustomFunction( );" /&gt;
        !           661: </pre>
        !           662:     <p>While the window and button events in <a href=
        !           663:     "#77020">Example 5-5</a> carry out some inline script, there is
        !           664:     a variation with the <tt>onchange</tt> handler attached to the
        !           665:     <tt>menulist</tt> element. <tt>onchange</tt> contains a
        !           666:     JavaScript function call whose definition may live in the XUL
        !           667:     document itself or in an external file that is included by
        !           668:     using the <tt>src</tt> attribute on a <tt>script</tt>
        !           669:     element:</p>
        !           670: <pre>
        !           671: &lt;script type="application/x-javascript" src="chrome://mypackage/content/myfile.js" /&gt;
        !           672: </pre>
        !           673:     <p>A large basic set of event handler attributes is available
        !           674:     for use on XUL elements (and HTML elements). <a href=
        !           675:     "appc.html#77003">Appendix C</a> has a full listing of these
        !           676:     events along with explanations. The following subset 
        !           677:     <!--INDEX attributes:event handling:XUL elements --> shows the
        !           678:     potential for script interaction when the UI uses event
        !           679:     handlers:</p>
        !           680: <pre>
        !           681: onabort
1.1       david     682: onblur
                    683: onerror
                    684: onfocus
                    685: onchange
                    686: onclick
                    687: oncontextmenu
                    688: ondestroy
                    689: onload
                    690: onpaint
                    691: onkeydown
                    692: onkeypress
                    693: onkeyup
                    694: onunload
                    695: onmousemove
                    696: onmouseout
                    697: onmouseover
                    698: onmouseup
                    699: onmousedown
                    700: onrest
                    701: onresize
                    702: onscroll
                    703: onselect
1.12    ! petejc    704: onsubmit
        !           705: </pre>
        !           706:     <p>Some of these event handlers work only on particular
        !           707:     elements, such as <tt>window</tt>, which listens for the
        !           708:     <tt>load</tt> event, the <tt>paint</tt> event, and other
        !           709:     special events.</p>
        !           710:     <p>To see all event handler attributes on a particular element,
        !           711:     you can execute the short script in <a href="#77022">Example
        !           712:     5-6</a>, which uses the <tt>for</tt> <tt>in</tt> loop in
        !           713:     JavaScript to iterate over the members of an object-in this 
        !           714:     <!--INDEX attributes:event handling:viewing for elements -->
        !           715:     case, a XUL element.</p>
        !           716:     <p><i>Example 5-6: <a name="77022"></a></i> <i>Getting event
        !           717:     handler attributes from an element</i></p>
        !           718: <pre>
        !           719:  &lt;script type="application/x-javascript"&gt;
1.1       david     720:    function listElementHandlers(aObj)
                    721:    {
                    722:      if(!aObj)
                    723:        return null;
                    724:      for(var list in aObj)
                    725:        if(list.match(/^on/))
                    726:          dump(list+'\n');
                    727:    }
                    728:  &lt;/script&gt;
1.12    ! petejc    729:  &lt;button label="oncommand" oncommand="listElementHandlers(this);" /&gt;
        !           730: </pre>
        !           731:     <p>The function you added in <a href="#77018">Example 5-4</a>
        !           732:     is also an example of event handler code in an application's
        !           733:     interface.</p>
        !           734:     <h3><a name="77056"></a> Events and the Mozilla Event
        !           735:     Model</h3>
        !           736:     <p>The event model in Mozilla is the general framework for how
        !           737:     events work and move around in the user interface. As you've
        !           738:     already seen, events tend to rise up through the DOM
        !           739:     hierarchy-a natural process referred to as event propagation or
        !           740:     event bubbling. The next two sections describe event
        !           741:     propagation and its complement, event capturing.</p>
        !           742:     <h4><a name="77057"></a> Event propagation and event
        !           743:     bubbling</h4>
        !           744:     <p>This availability of events in 
        !           745:     <!--INDEX event handling:bubbling --> 
        !           746:     <!--INDEX bubbling (event handling) --> 
        !           747:     <!--INDEX hierarchy:event bubbling --> 
        !           748:     <!--INDEX elements:event handling, bubbling --> nodes above the
        !           749:     element of origin is known as event propagation or event
        !           750:     bubbling. Event bubbling means you can handle events anywhere
        !           751:     above the event-raising element in the hierarchy. When events
        !           752:     are handled by elements that did not initiate those events, you
        !           753:     must determine which element below actually raised the event.
        !           754:     For example, if an event handler in a menu element handles an
        !           755:     event raised by one of the menu items, then the menu should be
        !           756:     able to identify the raising element and take the appropriate
        !           757:     action, as shown in <a href="#77024">Example 5-7</a>. In this
        !           758:     example, a JavaScript function determines which
        !           759:     <tt>menuitem</tt> was selected and responds appropriately.</p>
        !           760:     <p><i>Example 5-7: <a name="77024"></a></i> <i>Event
        !           761:     propagation</i></p>
        !           762: <pre>
        !           763:  &lt;script type="application/x-javascript"&gt;
1.1       david     764:  function doCMD(el) {
                    765:      v = el.getAttribute("label")
                    766:      switch (v) {
                    767:        case "New":
                    768:          alert('New clicked');
                    769:           break;
                    770:        case "Open":
                    771:          alert('Open clicked');
                    772:          break;
                    773:        case "Close":
                    774:          alert('Close clicked');
                    775:          break;
                    776:      }
                    777:  }
                    778:  &lt;/script&gt;
                    779:  ...
                    780:  &lt;menu class="menu" label="File" oncommand="doCMD(event.target)"&gt;
                    781:    &lt;menupopup&gt;
                    782:      &lt;menuitem label="New" /&gt;
                    783:      &lt;menuitem label="Open" /&gt;
                    784:      &lt;menuitem label="Close" /&gt;
                    785:    &lt;/menupopup&gt;
1.12    ! petejc    786:  &lt;/menu&gt;
        !           787: </pre>
        !           788:     <p>The event handler in the parent node menu finds out which
        !           789:     child <tt>menuitem</tt> was actually clicked by using
        !           790:     <tt>event.target</tt> and takes action accordingly. Let's walk
        !           791:     through another possible scenario. If a user of an application
        !           792:     selects an item from a menu list, you could get the node of
        !           793:     that item by using <tt>event.target</tt>. Your script could
        !           794:     then abstract that item's value or other information, if
        !           795:     necessary.</p>
        !           796:     <h5><a name="77058"></a> Trapping events</h5>
        !           797:     <p>When an <!--INDEX event handling:trapping --> 
        !           798:     <!--INDEX trapping events --> event is raised, it is typically
        !           799:     handled by any node interested in it as it continues its way up
        !           800:     the DOM hierarchy. In some cases, you may want to handle an
        !           801:     event and then prevent it from bubbling further up, which is
        !           802:     where the DOM Event 
        !           803:     <!--INDEX DOM (Document Object Model):event handling, trapping events -->
        !           804:     <!--INDEX stopPropagation( ) method --> method
        !           805:     <tt>stopPropagation( )</tt> comes in handy.</p>
        !           806:     <p><a href="#77026">Example 5-8</a> demonstrates how event
        !           807:     bubbling can be arrested very simply. When the XUL document in
        !           808:     <a href="#77026">Example 5-8</a> loads, an event listener is
        !           809:     registered with a <tt>row</tt> in the tree. The event listener
        !           810:     handles the event by executing the function <tt>stopEvent(
        !           811:     )</tt>. This function calls an event object method,
        !           812:     <tt>stopPropagation</tt>, which keeps the event from bubbling
        !           813:     further up into the DOM. Note that the tree itself has an
        !           814:     <tt>onclick</tt> event handler that should display a message
        !           815:     when clicked. However, the <!--INDEX stopEvent( ) method -->
        !           816:     <tt>stopEvent( )</tt> method has stopped propagation, so after
        !           817:     the data in the table is updated, the event phase is
        !           818:     effectively ended. In this case, the function was used to trap
        !           819:     the event and handle it only there.</p>
        !           820:     <p><i>Example 5-8: <a name="77026"></a></i> <i>stopPropagation(
        !           821:     ) event function</i></p>
        !           822: <pre>
        !           823:  &lt;?xml version="1.0"?&gt;
1.1       david     824:  &lt;!DOCTYPE  window&gt;
                    825:  &lt;window id="test-win"
1.12    ! petejc    826:    xmlns="<a href=
        !           827: "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul</a>"
1.1       david     828:    orient="vertical"
                    829:    onload="load( );"&gt;
                    830:  &lt;script type="application/x-javascript"&gt;
                    831:    function load( ) {
                    832:      el = document.getElementById("t");
                    833:      el.addEventListener("click", stopEvent, false);
                    834:    }
1.12    ! petejc    835:    &lt;/td&gt;function stopEvent(e) {
1.1       david     836:      // this ought to keep t-daddy from getting the click.
                    837:      e.stopPropagation( );
                    838:    }
                    839:  &lt;/script&gt;
                    840:  &lt;tree&gt;
                    841:    &lt;!-- tree columns definition omitted --&gt;
                    842:    &lt;treechildren flex="1" &gt;
                    843:      &lt;treeitem id="t-daddy"
1.12    ! petejc    844:        &lt;/td&gt;onclick="alert('t-daddy');"  // this event is never fired
1.1       david     845:        container="true" parent="true"&gt;
                    846:        &lt;treerow id="t"&gt;
                    847:          &lt;treecell label="O'Reilly" id="t1" /&gt;
1.12    ! petejc    848:          &lt;treecell label="<a href=
        !           849: "http://www.oreilly.com">http://www.oreilly.com</a>" id="t2" /&gt;
1.1       david     850:        &lt;/treerow&gt;
                    851:       &lt;/treeitem&gt;
                    852:    &lt;/treechildren&gt;
                    853:  &lt;/tree&gt;
1.12    ! petejc    854:  &lt;/window&gt;
        !           855: </pre>
        !           856:     <h4><a name="77059"></a> Capturing events</h4>
        !           857:     <p>Event <!--INDEX event handling:capturing events --> 
        !           858:     <!--INDEX capturing events --> capturing is the complement of
        !           859:     event bubbling. The DOM provides the <tt>addEventListener</tt>
        !           860:     method for creating event listeners on nodes that do not
        !           861:     otherwise supply them. When you register an event listener on
        !           862:     an ancestor of the event target (i.e., any node above the
        !           863:     event-raising element in the node hierarchy), you can use event
        !           864:     capturing to handle the event in the ancestor before it is
        !           865:     heard in the target itself or any intervening nodes.</p>
        !           866:     <p>To take advantage of event capturing (or event bubbling with
        !           867:     elements that do not already have event listeners), you must
        !           868:     add an event listener to the element that wants to capture
        !           869:     events occurring below it. Any XUL element may use the DOM
        !           870:     <tt>addEventListener</tt> 
        !           871:     <!--INDEX addEventListener( ) method --> 
        !           872:     <!--INDEX registering:elements, event capturing --> 
        !           873:     <!--INDEX elements:registering, event capturing --> 
        !           874:     <!--INDEX listeners, event capturing --> method to register
        !           875:     itself to capture events. The syntax for using this method in
        !           876:     XUL is shown here:</p>
        !           877: <pre>
        !           878: XULelement = document.getElementById("id of XULelement");
1.1       david     879: XULelement.addEventListener("event name", "event handler code",
1.12    ! petejc    880: useCapture bool);
        !           881: </pre>
        !           882:     <p>The event handler code argument can be inline code or the
        !           883:     name of a function. The <tt><!--INDEX useCapture parameter -->
        !           884:     useCapture</tt> parameter specifies whether the event listener
        !           885:     wants to use event capturing or be registered to listen for
        !           886:     events that bubble up the hierarchy normally. In <a href=
        !           887:     "#77006">Figure 5-3</a>, the alert dialog invoked by the
        !           888:     <tt>menuitem</tt> itself is not displayed, since the root
        !           889:     <tt>window</tt> element used event capture to handle the event
        !           890:     itself.</p>
        !           891:     <div class="c14">
        !           892:       <img src="foo.gif">
        !           893:     </div>
        !           894:     <p><i>Figure 5-3: <a name="77006"></a></i> <i>Event
        !           895:     capturing</i></p>
        !           896:     <p>An <tt><!--INDEX onload event handler --> onload</tt> 
        !           897:     <!--INDEX event handling:onload handler --> event handler for a
        !           898:     XUL window can also register a <tt>box</tt> element to capture
        !           899:     all click events that are raised from its child elements:</p>
        !           900: <pre>
        !           901: var bbox = document.getElementById("bigbox");
1.1       david     902: if (bbox) {
                    903: bbox.addEventListener("click", "alert('captured')", true);
                    904: }
                    905: ...
                    906: &lt;box id="bigbox"&gt;
                    907: &lt;menu label="File"&gt;
                    908: &lt;menupopup&gt;
                    909: &lt;menuitem label="New" onclick="alert('not captured')" /&gt;
                    910: ...
                    911: &lt;menupopup&gt;
                    912: &lt;/menu&gt;
1.12    ! petejc    913: &lt;/box&gt;
        !           914: </pre>
        !           915:     <h3><a name="77060"></a> Changing an Element's CSS Style Using
        !           916:     JavaScript</h3>
        !           917:     <p>Much of 
        !           918:     <!--INDEX CSS (Cascading Style Sheets):styles, changing with JavaScript -->
        !           919:     <!--INDEX styles:CSS, changing with JavaScript --> 
        !           920:     <!--INDEX JavaScript:Cascading Style Sheets and:changing styles -->
        !           921:     <!--INDEX scripting:CSS styles, changing --> what makes the
        !           922:     Mozilla UI both flexible and programmable is its ability to
        !           923:     dynamically alter the CSS style rules for elements at runtime.
        !           924:     For example, if you have a button, you can toggle its
        !           925:     visibility by using a simple combination of JavaScript and CSS.
        !           926:     Given a basic set of buttons like this:</p>
        !           927: <pre>
        !           928: &lt;button id="somebutton" class="testButton" label="foo" /&gt;
1.1       david     929: &lt;spacer flex="1" /&gt;
                    930: &lt;button id="ctlbutton"
                    931: class="testButton"
                    932: label="make disappear"
1.12    ! petejc    933: oncommand="disappear( );" /&gt;
        !           934: </pre>
        !           935:     <p>as well as a stylesheet import statement at the top of the
        !           936:     XUL like this:</p>
        !           937: <pre>
        !           938: &lt;?xml-stylesheet href="test.css" type="text/css"?&gt;
        !           939: </pre>
        !           940:     <p>and a simple CSS file in your <i>chrome/xfly/content</i>
        !           941:     directory called <i>test.css</i> that contains the following
        !           942:     style rule:</p>
        !           943: <pre>
        !           944: #somebutton[hidden="true"]{ display: none; }
1.1       david     945: .testButton{
                    946: border            : 1px outset #cccccc;
                    947: background-color  : #cccccc;
                    948: padding           : 4px;
                    949: margin            : 50px;
1.12    ! petejc    950: }
        !           951: </pre>
        !           952:     <p>You can call <tt>
        !           953:     <!--INDEX setAttribute( ) method:calling at runtime -->
        !           954:     setAttribute</tt> in your script to hide the button at
        !           955:     runtime.</p>
        !           956: <pre>
        !           957: &lt;script&gt;
1.1       david     958: function disappear( ){
                    959: return document.getElementById('somebutton').setAttribute('hidden', true);
                    960: }
1.12    ! petejc    961: &lt;/script&gt;
        !           962: </pre>
        !           963:     <p>The previous code snippet makes a visible button disappear
        !           964:     by setting its <tt>hidden</tt> attribute to true. Adding a few
        !           965:     more lines, you can toggle the visibility of the button, also
        !           966:     making it appear if it is hidden:</p>
        !           967: <pre>
        !           968: &lt;script&gt;
1.1       david     969: function disappear( ){
                    970: const defaultLabel  = "make disappear";
                    971: const newLabel      = "make reappear";
                    972: var button          = document.getElementById('somebutton');
                    973: var ctlButton       = document.getElementById('ctlbutton');
                    974: if(!button.getAttribute('hidden')) {
                    975: button.setAttribute('hidden', true);
                    976: ctlButton.setAttribute('label', newLabel);
                    977: } else  {
                    978: button.removeAttribute('hidden');
                    979: ctlButton.setAttribute('label', defaultLabel);
                    980: }
                    981: return;
                    982: }
1.12    ! petejc    983: &lt;/script&gt;
        !           984: </pre>
        !           985:     <p>Another useful application of this functionality is to
        !           986:     collapse elements such as toolbars, boxes, and iframes in your
        !           987:     application.</p>
        !           988:     <p>The <tt>setAttribute</tt> method can also be used to update
        !           989:     the element's <tt>class</tt> attribute with which style rules
        !           990:     are so often associated. <tt>toolbarbutton-1</tt> and
        !           991:     <tt>button-toolbar</tt> are two different classes of button.
        !           992:     You can change a button from a <tt>toolbarbutton-1-</tt>the
        !           993:     large button used in the browser-to a standard toolbar button
        !           994:     using the following DOM code:</p>
        !           995: <pre>
        !           996: // get the Back button in the browser
1.1       david     997: b1 = document.getElementById("back-button");\
1.12    ! petejc    998: b1.setAttribute("class", "button-toolbar");
        !           999: </pre>
        !          1000:     <p>This dynamically demotes the Back button to an ordinary
        !          1001:     toolbar button. Code such as this assumes, of course, that you
        !          1002:     know the classes that are used to style the various widgets in
        !          1003:     the interface.</p>
        !          1004:     <p>You can also set the <tt>style</tt> attribute directly using
        !          1005:     the DOM:</p>
        !          1006: <pre>
        !          1007: el = document.getElementById("some-element");
        !          1008: el.setAttribute("style", "background-color:darkblue;");
        !          1009: </pre>
        !          1010:     <p>Be aware, however, that when you set the <tt>style</tt>
        !          1011:     attribute in this way, you are overwriting whatever style
        !          1012:     properties may already have been defined in the <tt>style</tt>
        !          1013:     attribute. If the document referenced in the snippet above by
        !          1014:     the ID <tt>some-element</tt> has a <tt>style</tt> attribute in
        !          1015:     which the font size is set to 18pc, for example, that
        !          1016:     information is erased when the style attribute is manipulated
        !          1017:     in this way.</p>
        !          1018:     <h3><a name="77061"></a> Creating Elements Dynamically</h3>
        !          1019:     <p>Using the <!--INDEX elements:creating dynamically --> 
        !          1020:     <!--INDEX XUL (XML-based User-interface Language):elements:creating dynamically -->
        !          1021:     <tt>createElement</tt> method in XUL lets you accomplish things
        !          1022:     similar to <tt>document.write</tt> in HTML, with which you can
        !          1023:     create new pages and parts of a web page. In <a href=
        !          1024:     "#77028">Example 5-9</a>, <tt>
        !          1025:     <!--INDEX createElement( ) method:dynamic element creation -->
        !          1026:     createElement</tt> is used to generate a menu dynamically.</p>
        !          1027:     <p><i>Example 5-9: <a name="77028"></a></i> <i>Dynamic menu
        !          1028:     generation</i></p>
        !          1029: <pre>
        !          1030:  &lt;?xml version="1.0"?&gt;
1.1       david    1031:  &lt;?xml-stylesheet href="test.css" type="text/css"?&gt;
                   1032:  &lt;!DOCTYPE  window&gt;
                   1033:  &lt;window id="test-win"
1.12    ! petejc   1034:          xmlns="<a href=
        !          1035: "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul</a>"
1.1       david    1036:          title="test"
                   1037:          style="
                   1038:          min-width : 200px;
                   1039:          min-height: 200px;"&gt;
                   1040:  &lt;script&gt;
1.12    ! petejc   1041:  &lt;!&lt;/td&gt;[CDATA[
1.1       david    1042:  function generate( ){
                   1043:    var d           = document;
                   1044:    var popup       = d.getElementById('menupopup');
                   1045:    var menuitems   = new Array('menuitem_1',
                   1046:                       'menuitem_2', 'menuitem_3',
                   1047:                       'menuitem_4', 'menuitem_5');
                   1048:    var l           = menuitems.length;
                   1049:    var newElement;
                   1050:    for(var i=0; i&lt;l; i++)
                   1051:    {
                   1052:      newElement = d.createElement('menuitem');
1.12    ! petejc   1053:      newElement.setAttribute('id', menuitems&lt;/td&gt;[i]);
        !          1054:      newElement.setAttribute('label', menuitems&lt;/td&gt;[i]);
1.1       david    1055:      popup.appendChild(newElement);
                   1056:    }
                   1057:    return true;
                   1058:  }
                   1059:  ]]&gt;
                   1060:  &lt;/script&gt;
                   1061:  &lt;menu label="a menu"&gt;
                   1062:    &lt;menupopup id="menupopup"&gt;
                   1063:    &lt;/menupopup&gt;
                   1064:  &lt;/menu&gt;
                   1065:  &lt;spacer flex="1" /&gt;
                   1066:  &lt;button id="ctlbutton" class="testButton" label="generate" oncommand="generate( );" /&gt;
1.12    ! petejc   1067:  &lt;/window&gt;
        !          1068: </pre>
        !          1069:     <p>The JavaScript function <tt>
        !          1070:     <!--INDEX generate( ) function --> generate( )</tt> in <a href=
        !          1071:     "#77028">Example 5-9</a> gets the <tt>menupopup</tt> as the
        !          1072:     parent element for the new elements, creates five
        !          1073:     <tt>menuitems</tt> in an array called <tt>menuitems</tt>, and
        !          1074:     stores five string ID names for those <tt>menuitems</tt>.</p>
        !          1075:     <p>The variable <i>l</i> is the length of the array. The
        !          1076:     variable <tt>newElement</tt> is a placeholder for elements
        !          1077:     created by using the <tt>createElement</tt> method inside of
        !          1078:     the <tt>for</tt> loop. <tt>generate( )</tt> assigns
        !          1079:     <tt>newElement</tt> on each iteration of the loop and creates a
        !          1080:     new <tt>menuitem</tt> each time, providing a way to dynamically
        !          1081:     generate a list of menu choices based on input data or user
        !          1082:     feedback. Try this example and experiment with different
        !          1083:     sources of data, such as a menu of different auto
        !          1084:     manufacturers, different styles on group of boxes that come
        !          1085:     from user selection, or tabular data in a tree.</p>
        !          1086:     <h3><a name="77062"></a> Sharing Data Between Documents</h3>
        !          1087:     <p>As the scale of your application development increases and
        !          1088:     your applications grow new windows and components, you may
        !          1089:     become interested in passing data around and ensuring that the
        !          1090:     data remains in scope. Misunderstanding that scope often leads
        !          1091:     to problems when beginning Mozilla applications.</p>
        !          1092:     <h4><a name="77063"></a> Scope in Mozilla</h4>
        !          1093:     <p>The general <!--INDEX documents:sharing data:scope --> 
        !          1094:     <!--INDEX sharing data, scope --> 
        !          1095:     <!--INDEX scope, sharing data between documents --> rule is
        !          1096:     that all scripts pulled in by the base XUL document and scripts
        !          1097:     included in overlays of this document are in the same scope.
        !          1098:     Therefore, any global variables you declare in any of these
        !          1099:     scripts can be used by any other scripts in the same scope. The
        !          1100:     decision to put a class structure or more sophisticated design
        !          1101:     in place is up to you.</p>
        !          1102:     <p>The relationship of a parent and child window indicates the
        !          1103:     importance of storing data in language constructs that can be
        !          1104:     passed around. This code shows a common way for a parent to
        !          1105:     pass data to a window it spawns:</p>
        !          1106: <pre>
        !          1107: var obj = new Object ( );
1.1       david    1108: obj.res = "";
                   1109: window.openDialog("chrome://xfly/content/foo.xul", 'foo_main',
                   1110: "chrome,resizable,scrollbars,dialog=yes,close,modal=yes",
1.12    ! petejc   1111: obj);
        !          1112: </pre>
        !          1113:     <h4><a name="77064"></a> Using the window.arguments array</h4>
        !          1114:     <p>The previous <!--INDEX window.arguments array --> 
        !          1115:     <!--INDEX arrays, sharing data between documents;window.arguments array -->
        !          1116:     <!--INDEX documents:sharing data:window.arguments array -->
        !          1117:     code snippet creates a new JavaScript object, <tt>obj</tt>, and
        !          1118:     assigns the value of an empty string to that object's
        !          1119:     <tt>res</tt> property. The object is then passed by reference
        !          1120:     to the new window as the last parameter of the <tt>openDialog(
        !          1121:     )</tt> method so it can be manipulated in the scope of the
        !          1122:     child window:</p>
        !          1123: <pre>
        !          1124: function onOk( ) {
1.1       david    1125: window.arguments[0].res  = "ok";
                   1126: return;
                   1127: }
                   1128: function onCancel( ) {
                   1129: window.arguments[0].res  = "cancel";
                   1130: return;
1.12    ! petejc   1131: }
        !          1132: </pre>
        !          1133:     <p>In that child window, the object is available as an indexed
        !          1134:     item in the special <tt>window.arguments</tt> array. This array
        !          1135:     holds a list of the arguments passed to a window when it is
        !          1136:     created. window.arguments[0] is a reference to the first
        !          1137:     argument in the <tt>openDialog( )</tt> parameter list that is
        !          1138:     not a part of the input parameters for that method,
        !          1139:     window.arguments[1] is the second argument, and so on. Using
        !          1140:     <tt>window.arguments</tt> is the most common way to pass
        !          1141:     objects and other data around between documents.</p>
        !          1142:     <p>When the user clicks a button in the displayed dialog (i.e.,
        !          1143:     the OK or Cancel button), one of the functions sets a value to
        !          1144:     the <tt>res</tt> property of the passed-in object. The object
        !          1145:     is in the scope of the newly created window. When control is
        !          1146:     passed back to the script that launched the window, the return
        !          1147:     value can be checked:</p>
        !          1148: <pre>
        !          1149: if (obj.res != "ok") {
1.1       david    1150: dump("User has cancelled the dialog");
                   1151: return;
1.12    ! petejc   1152: }
        !          1153: </pre>
        !          1154:     <p>In this case, a simple dump statement prints the result, but
        !          1155:     you can also test the result in your application code and fork
        !          1156:     accordingly.</p>
        !          1157:     <h2><a name="77065"></a> XPConnect and Scriptable
        !          1158:     Components</h2>
        !          1159:     <p>At the second level of scripting, XPConnect binds JavaScript
        !          1160:     and the user interface to the application core. Here,
        !          1161:     JavaScript can access all XPCOM components that implement
        !          1162:     scriptable libraries and services through a special global
        !          1163:     object whose methods and properties can be used in JavaScript.
        !          1164:     Consider these JavaScript snippets from the Mozilla source
        !          1165:     code:</p>
        !          1166: <pre>
        !          1167: // add filters to the file picker
1.1       david    1168: fp.appendFilters( nsIFilePicker.HTML );
                   1169: // display a directory in the file picker
                   1170: fp.displayDirectory ( dir );
                   1171: // read a line from an open file
                   1172: file.readLine(tmpBuf, 1024, didTruncate);
                   1173: // create a new directory
                   1174: this.fileInst.create( DIRECTORY, parseInt(permissions) );
1.12    ! petejc   1175: retval=OK;
        !          1176: </pre>
        !          1177:     <p>The <tt>filepicker</tt>, <tt>file</tt>, and
        !          1178:     <tt>localfile</tt> components that these JavaScript objects
        !          1179:     represent are a tiny fraction of the components available via
        !          1180:     XPConnect to programmers in Mozilla. This section describes how
        !          1181:     to find these components, create the corresponding JavaScript
        !          1182:     objects, and use them in your application programming.</p>
        !          1183:     <h3><a name="77066"></a> What Is XPConnect?</h3>
        !          1184:     <p>Until now, <!--INDEX XPConnect:overview --> 
        !          1185:     <!--INDEX scripting:XPConnect, overview --> scripting has
        !          1186:     referred to scripting the DOM, manipulating various elements in
        !          1187:     the interface, and using methods available in Mozilla
        !          1188:     JavaScript files. However, for real applications like the
        !          1189:     Mozilla browser itself, this may be only the beginning. The UI
        !          1190:     must be hooked up to the application code and services (i.e.,
        !          1191:     the application's actual functionality) to be more than just a
        !          1192:     visual interface. This is where XPConnect and XPCOM come
        !          1193:     in.</p>
        !          1194:     <p>Browsing the Web, reading email, and parsing XML files are
        !          1195:     examples of application-level services in Mozilla. They are
        !          1196:     part of Mozilla's lower-level functionality. This functionality
        !          1197:     is usually written and compiled in platform-native code and
        !          1198:     typically written in C++. This functionality is also most often
        !          1199:     organized into modules, which take advantage of Mozilla's
        !          1200:     cross-platform component object model (XPCOM), and are known as
        !          1201:     <i><!--INDEX XPCOM components --> XPCOM components</i>. The
        !          1202:     relationship of these components and the application services
        !          1203:     they provide to the interface is shown in <a href=
        !          1204:     "#77008">Figure 5-4</a>.</p>
        !          1205:     <div class="c14">
        !          1206:       <img src="foo.gif">
        !          1207:     </div>
        !          1208:     <p><i>Figure 5-4: <a name="77008"></a></i> <i>How XPConnect
        !          1209:     fits into the application model</i></p>
        !          1210:     <p>In Mozilla, XPConnect is the bridge between JavaScript and
        !          1211:     XPCOM components. The XPConnect technology wraps natively
        !          1212:     compiled components with JavaScript objects. XPCOM, Mozilla's
        !          1213:     own cross-platform component technology, is the framework on
        !          1214:     top of which these scriptable components are built. Using
        !          1215:     JavaScript and XPConnect, you can create instances of these
        !          1216:     components and use their methods and properties as you do any
        !          1217:     regular JavaScript object, as described here. You can access
        !          1218:     any or all of the functionality in Mozilla in this way.</p>
        !          1219:     <p><a href="ch08.html#77048">Chapter 8</a> describes more about
        !          1220:     the XPConnect technology and how it connects components to the
        !          1221:     interface. It also describes the components themselves and
        !          1222:     their interfaces, the XPCOM technology, and how you can create
        !          1223:     your own XPCOM components.</p>
        !          1224:     <h4><a name="77067"></a> Creating XPCOM objects in script</h4>
        !          1225:     <p><a href="#77030">Example 5-10</a> demonstrates 
        !          1226:     <!--INDEX XPCOM:methods:JavaScript implementation --> 
        !          1227:     <!--INDEX JavaScript:XPCOM objects, 
        !          1228:     creating --> the creation and use of an 
        !          1229:     <!--INDEX XPCOM:components --> XPCOM component in JavaScript.
        !          1230:     In this example, the script instantiates the
        !          1231:     <tt>filepicker</tt> object and then uses it to display a file
        !          1232:     picker dialog with all of the file filters selected. To run
        !          1233:     this example, add the function to your <i>xfly.js</i> file and
        !          1234:     call it from an event handler on the "New" menu item you added
        !          1235:     in <a href="ch03.html#77042">Example 3-5</a>. Example 5-10<a
        !          1236:     name="77030"></a> <i>Scriptable component example</i></p>
        !          1237: <pre>
        !          1238:  // chooseApp:  Open file picker and prompt user for application.
1.1       david    1239:  chooseApp: function( ) {
                   1240:    var nsIFilePicker = Components.interfaces.nsIFilePicker;
                   1241:    var fp =
1.12    ! petejc   1242:       Components.classes&lt;/td&gt;["@mozilla.org/filepicker;1"].
1.1       david    1243:           createInstance( nsIFilePicker );
                   1244:    fp.init( this.mDialog,
                   1245:       this.getString( "chooseAppFilePickerTitle" ),
                   1246:       nsIFilePicker.modeOpen );
                   1247:    fp.appendFilters( nsIFilePicker.filterAll );
                   1248:    if ( fp.show( ) == nsIFilePicker.returnOK &amp;&amp; fp.file ) {
                   1249:    this.choseApp   = true;
                   1250:    this.chosenApp  = fp.file;
                   1251:    // Update dialog.
                   1252:    this.updateApplicationName(this.chosenApp.unicodePath);
1.12    ! petejc   1253:  }
        !          1254: </pre>
        !          1255:     <p>Note the first two lines in the function and the way they
        !          1256:     work together to create the <tt>fp</tt> <tt>filepicker</tt>
        !          1257:     object. The first line in the function assigns the name of the
        !          1258:     <i>nsFile-picker</i> interface to the <tt>nsIFilePicker</tt>
        !          1259:     variable in JavaScript. This variable is used in the second
        !          1260:     line, where the instance is created from the component to
        !          1261:     specify which interface on that component should be used.
        !          1262:     Discovering and using library interfaces is an important aspect
        !          1263:     of XPCOM, where components always implement at least two
        !          1264:     interfaces.</p>
        !          1265:     <p>In <a href="#77032">Example 5-11</a>, an HTML file (stored
        !          1266:     locally, since it wouldn't have the required XPConnect access
        !          1267:     as a remote file because of security boundaries) loaded in
        !          1268:     Mozilla instantiates a Mozilla sound component and plays a
        !          1269:     sound with it. Go ahead and try it. Example 5-11<a name=
        !          1270:     "77032"></a> <i>Scripting components from HTML</i></p>
        !          1271: <pre>
        !          1272:  &lt;html&gt;
1.1       david    1273:  &lt;head&gt;
                   1274:  &lt;title&gt;Sound Service Play Example&lt;/title&gt;
                   1275:  &lt;/head&gt;
                   1276:  &lt;body&gt;
                   1277:  &lt;script&gt;
                   1278:    netscape.security.PrivilegeManager.enablePrivilege("UniversalXPConnect");
1.12    ! petejc   1279:    var url = Components.classes&lt;/td&gt;["@mozilla.org/network/standard-
1.1       david    1280:        url;1"].createInstance( );
                   1281:    url = url.QueryInterface(Components.interfaces.nsIURL);
                   1282:    url.spec = "resource:/res/samples/test.wav";
1.12    ! petejc   1283:    var sample = Components.classes&lt;/td&gt;["@mozilla.org/sound;1"].createInstance( );
1.1       david    1284:    sample = sample.QueryInterface(Components.interfaces.nsISound);
                   1285:  &lt;/script&gt;
                   1286:  &lt;form name="form"&gt;
                   1287:    &lt;input type="button" value="Play Sound" onclick="sample.play(url);"&gt;
                   1288:  &lt;form&gt;
                   1289:  &lt;/body&gt;
1.12    ! petejc   1290:  &lt;/html&gt;
        !          1291: </pre>
        !          1292:     <p>As in <a href="#77030">Example 5-10</a>, the classes[ ]
        !          1293:     array on the special Mozilla <tt>Components</tt> object refers
        !          1294:     to a particular component-in this case, the <tt>sound</tt>
        !          1295:     component-by contract ID. All XPCOM objects must have a
        !          1296:     contract ID that uniquely identifies them with the domain, the
        !          1297:     component name, and a version number ["@mozilla.org/sound;1"],
        !          1298:     respectively. See the <a href="ch08.html#77058">"XPCOM
        !          1299:     Identifiers</a>" section in <a href="ch08.html#77048">Chapter
        !          1300:     8</a> for more information about this.</p>
        !          1301:     <h4><a name="77068"></a> Finding components and interfaces</h4>
        !          1302:     <p>Most <!--INDEX XPCOM:components:locating and viewing -->
        !          1303:     components are scripted in Mozilla. In fact, the challenge is
        !          1304:     not to find cases when this scripting occurs (which you can
        !          1305:     learn by searching LXR for the <tt>Components</tt>), but to
        !          1306:     find Mozilla components that don't use scriptable components.
        !          1307:     Finding components and interfaces in Mozilla and seeing how
        !          1308:     they are used can be useful when writing your own
        !          1309:     application.</p>
        !          1310:     <p>The Mozilla <!--INDEX Component Viewer development tool -->
        !          1311:     Component Viewer is a great tool for discovering components and
        !          1312:     provides a convenient UI for seeing components and looking at
        !          1313:     their interfaces from within Mozilla. The Component Viewer can
        !          1314:     be built as an extension to Mozilla (see "cview" in the
        !          1315:     extensions directory of the Mozilla source), or it can be
        !          1316:     downloaded and installed as a separate 
        !          1317:     <!--INDEX web sites:Component Viewer --> XPI from <i><a href=
        !          1318:     "http://www.hacksrus.com/~ginda/cview/">http://www.hacksrus.com/~ginda/cview/</a></i>.
        !          1319:     <a href="appb.html#77021">Appendix B</a> describes the
        !          1320:     Component Viewer in more detail.</p>
        !          1321:     <p>Commonly used XPCOM objects in the browser and other Mozilla
        !          1322:     applications include file objects, RDF services, URL objects,
        !          1323:     and category managers.</p>
        !          1324:     <h4><a name="77069"></a> Selecting the appropriate interface
        !          1325:     from the component</h4>
        !          1326:     <p>In all cases, 
        !          1327:     <!--INDEX XPCOM:components:interfaces, selecting --> 
        !          1328:     <!--INDEX interfaces:XPCOM:components, selecting --> the way to
        !          1329:     get the object into script is to instantiate it with the
        !          1330:     special <tt>classes</tt> object and use the <tt>createInstance(
        !          1331:     )</tt> method on the class to select the interface you want to
        !          1332:     use. These two steps are often done together, as in the
        !          1333:     following example, which gets the component with the contract
        !          1334:     ID <tt>ldap-connection;1</tt>, instantiates an object from the
        !          1335:     <i>nsILDAPConnection</i> interface, and then calls a method on
        !          1336:     that object:</p>
        !          1337: <pre>
        !          1338: var connection = Components.classes
1.1       david    1339: ["@mozilla.org/network/ldap-connection;1"].
                   1340: createInstance(Components.interfaces.nsILDAPConnection);
                   1341: connection.init(queryURL.host, queryURL.port, null,
1.12    ! petejc   1342: generateGetTargetsBoundCallback( ));
        !          1343: </pre>
        !          1344:     <p>These two common processes-getting a component and selecting
        !          1345:     one of its interfaces to assign to an object-can also be
        !          1346:     separated into two different statements:</p>
        !          1347: <pre>
        !          1348: // get the ldap connection component
1.1       david    1349: var connection = Components.classes
1.5       petejc   1350: ["@mozilla.org/network/ldap-connection;1"];
1.1       david    1351: // create an object from the nsILDAPConnection interface;
                   1352: connection.createInstance(Components.interfaces.nsILDAPConnection);
                   1353: // call the init( ) method on that object
                   1354: connection.init(queryURL.host, queryURL.port, null,
1.12    ! petejc   1355: generateGetTargetsBoundCallback( ));
        !          1356: </pre>
        !          1357:     <p>Mozilla constantly uses these processes. Wherever
        !          1358:     functionality is organized into XPCOM objects (and most of it
        !          1359:     is), these two statements bring that functionality into
        !          1360:     JavaScript as high-level and user-friendly JavaScript
        !          1361:     objects.</p>
        !          1362:     <h2><a name="77070"></a> JavaScript Application Code</h2>
        !          1363:     <p>There are 
        !          1364:     <!--INDEX JavaScript:application programming:overview --> 
        !          1365:     <!--INDEX application programming, JavaScript:overview --> two
        !          1366:     ways to use JavaScript in the third, deepest level of
        !          1367:     application programming. The first is to organize your
        !          1368:     JavaScript into libraries so your functions can be reused,
        !          1369:     distributed, and perhaps collaborated upon.</p>
        !          1370:     <p>The second way is to write a JavaScript component, create a
        !          1371:     separate interface for that component, and compile it as an
        !          1372:     XPCOM component whose methods and data can be accessed from
        !          1373:     XPConnect (using JavaScript). This kind of application
        !          1374:     programming is described in <a href="ch08.html#77048">Chapter
        !          1375:     8</a>, which includes examples of creating new interfaces,
        !          1376:     implementing them in JavaScript or C++, and compiling, testing,
        !          1377:     and using the resulting component in the Mozilla interface.</p>
        !          1378:     <p>This section introduces the library organization method of
        !          1379:     JavaScript application programming. The JSLib code discussed
        !          1380:     here is a group of JavaScript libraries currently being
        !          1381:     developed by Mozilla contributors and is especially useful for
        !          1382:     working with the XPFE and other aspects of the Mozilla
        !          1383:     application/package programming model. When you include the
        !          1384:     right source files at the top of your JavaScript and/or XUL
        !          1385:     file, you can use the functions defined in JSLib libraries as
        !          1386:     you would use any third-party library or built-in functions.
        !          1387:     You may even want to contribute to the JSLib project yourself
        !          1388:     if you think functionality is missing and as your Mozilla
        !          1389:     programming skills grow.</p>
        !          1390:     <h3><a name="77071"></a> JavaScript Libraries</h3>
        !          1391:     <p>The open <!--INDEX JSLib libraries --> 
        !          1392:     <!--INDEX JavaScript:application programming:JSLib --> 
        !          1393:     <!--INDEX application programming, JavaScript:JSLib --> source
        !          1394:     JSLib project makes life easier for developers. The JSLib
        !          1395:     package implements some of the key XPCOM components just
        !          1396:     discussed and wraps them in simpler, JavaScript interfaces,
        !          1397:     which means that you can use the services of common XPCOM
        !          1398:     components without having to do any of the instantiation,
        !          1399:     interface selection, or glue code yourself. Collectively, these
        !          1400:     interfaces are intended to provide a general-purpose library
        !          1401:     for Mozilla application developers. To understand what JSLib
        !          1402:     does, consider the following short snippet from the JSLib
        !          1403:     source file <i>jslib/io/file.js</i>, which implements a
        !          1404:     <tt>close( )</tt> function for open file objects and provides a
        !          1405:     handy way to clean up things when you finish editing a file in
        !          1406:     the filesystem.</p>
        !          1407: <pre>
        !          1408: /********************* CLOSE ********************************
1.1       david    1409: * void close( )                                              *
                   1410: *                                                           *
                   1411: * void file close                                           *
                   1412: * return type void(null)                                    *
                   1413: * takes no arguments closes an open file stream and         *
                   1414: * deletes member var instances of objects                   *
                   1415: *   Ex:                                                     *
                   1416: *     var p='/tmp/foo.dat';                                 *
                   1417: *     var f=new File(p);                                    *
                   1418: *     fopen( );                                              *
                   1419: *     f.close( );                                            *
                   1420: *                                                           *
                   1421: *   outputs: void(null)                                     *
                   1422: ************************************************************/
                   1423: File.prototype.close = function( )
                   1424: {
                   1425: /***************** Destroy Instances *********************/
                   1426: if(this.mFileChannel)   delete this.mFileChannel;
                   1427: if(this.mInputStream)   delete this.mInputStream;
                   1428: if(this.mTransport)     delete this.mTransport;
                   1429: if(this.mMode)          this.mMode=null;
                   1430: if(this.mOutStream) {
                   1431: this.mOutStream.close( );
                   1432: delete this.mOutStream;
                   1433: }
                   1434: if(this.mLineBuffer)     this.mLineBuffer=null;
                   1435: this.mPosition           = 0;
                   1436: /***************** Destroy Instances *********************/
                   1437: return;
1.12    ! petejc   1438: }
        !          1439: </pre>
        !          1440:     <p>To use the <tt>close</tt> method as it's defined here,
        !          1441:     import the <i>file.js</i> source file into your JavaScript,
        !          1442:     create a file object (as shown in the examples below), and call
        !          1443:     its <tt>close( )</tt> method.</p>
        !          1444:     <blockquote>
        !          1445:       <hr>
        !          1446:       <b>xpcshell</b> 
        !          1447:       <p>Most <!--INDEX xpcshell --> <!--INDEX shells:xpcshell --> 
        !          1448:       <!--INDEX JavaScript:xpcshell --> examples in this section
        !          1449:       are in <i>xpcshell</i>, but using these libraries in your
        !          1450:       user interface JavaScript is just as easy. You can access
        !          1451:       these libraries from a XUL file, as the section <a href=
        !          1452:       "#77077">"Using the DirUtils class</a>," later in this
        !          1453:       chapter, demonstrates.</p>
        !          1454:       <p>xpcshell is the command-line interpreter to JavaScript and
        !          1455:       XPConnect. This shell that uses XPConnect to call and
        !          1456:       instantiate scriptable XPCOM interfaces. It is used primarily
        !          1457:       for debugging and testing scripts.</p>
        !          1458:       <p>To run xpcshell, you need to go to the Mozilla <i>bin</i>
        !          1459:       directory or have that folder in your PATH. For each
        !          1460:       platform, enter:</p>
        !          1461:       <p>Windows:</p>
        !          1462: <pre>
        !          1463: xpcshell.exe
        !          1464: </pre>
        !          1465:       Unix: 
        !          1466: <pre>
        !          1467: ./run-mozilla.sh ./xpcshell
        !          1468: </pre>
        !          1469:       To run xpcshell on Unix, you need to supply environment
        !          1470:       variables that the interpreter needs. You can use the
        !          1471:       <i>run-mozilla.sh</i> shell script that resides in the
        !          1472:       Mozilla <i>bin</i> directory. 
        !          1473: <pre>
        !          1474: $ ./run-mozilla.sh ./xpcshell
        !          1475: </pre>
        !          1476:       To see the available options for xpcshell, type this:
        !          1477:       <hr>
        !          1478:     </blockquote>
        !          1479:     $ ./run-mozilla.sh ./xpcshell --help JavaScript-C 1.5
        !          1480:     pre-release 4a 2002-03-21 usage: xpcshell [-s] [-w] [-W] [-v
        !          1481:     version] [-f scriptfile] [scriptfile] [scriptarg...]  The two
        !          1482:     most important parameters here are -w, which enables warnings
        !          1483:     output, and -s, which turns on strict mode.
        !          1484:     <hr>
        !          1485:     <p>The source files for JSLib are well annotated and easy to
        !          1486:     read. JSLib provide easy-to-use interfaces for creating
        !          1487:     instances of components (e.g., File objects), performing
        !          1488:     necessary error checking, and ensuring proper usage. To use a
        !          1489:     function like the one just shown, simply include the source
        !          1490:     file you need in your XUL:</p>
        !          1491: <pre>
        !          1492: &lt;script type="application/x-JavaScript"
        !          1493: src="chrome://jslib/content/jslib.js" /&gt;
        !          1494: </pre>
        !          1495:     <p>Then you can include the specific library files you need in
        !          1496:     your JavaScript code by using the include method:</p>
        !          1497: <pre>
        !          1498: include("chrome://jslib/content/io/file.js");
        !          1499: include("chrome://jslib/content/zip/zip.js");
        !          1500: </pre>
        !          1501:     <h4><a name="77072"></a> Installing JSLib</h4>
        !          1502:     <p>To use the <!--INDEX installation:JSLib --> 
        !          1503:     <!--INDEX JSLib libraries:installing --> 
        !          1504:     <!--INDEX JavaScript:application programming:installing 
        !          1505:     JSLib --> 
        !          1506:     <!--INDEX application programming, JavaScript:installing JSLib -->
        !          1507:     JavaScript libraries, install the JSLib package in Mozilla. The
        !          1508:     package is available as a tarball, a zip file, or as CVS
        !          1509:     sources. The easiest way to obtain it is to install it from the
        !          1510:     Web using Mozilla's XPInstall technology, described in <a href=
        !          1511:     "ch06.html#77063">Chapter 6</a>.</p>
        !          1512:     <p>Using your Mozilla browser, go to <i><a href=
        !          1513:     "http://jslib.mozdev.org/installation.html">http://jslib.mozdev.org/installation.html</a></i>
        !          1514:     and click the installation hyperlink. The link uses XPInstall
        !          1515:     to install JSLIB and make it available to you in Mozilla. To
        !          1516:     test whether it is installed properly, type the following code
        !          1517:     in your shell:</p>
        !          1518: <pre>
        !          1519: ./mozilla -chrome chrome://jslib/content/
        !          1520: </pre>
        !          1521:     <p>You should see a simple window that says "welcome to
        !          1522:     jslib."</p>
        !          1523:     <h4><a name="77073"></a> The JSLib libraries</h4>
        !          1524:     <p>Currently <!--INDEX classes:JSLib --> 
        !          1525:     <!--INDEX JSLib libraries:classes --> 
        !          1526:     <!--INDEX JavaScript:application programming:JSLib classes --> 
        !          1527:     <!--INDEX application programming, JavaScript:JSLib classes -->
        !          1528:     available JavaScript functions in the JSLib package are divided
        !          1529:     into different modules that, in turn, are divided into
        !          1530:     different classes defined in source files such as
        !          1531:     <i>file.js</i>, <i>dir.js</i>, and <i>fileUtils.js</i>. <a
        !          1532:     href="#77010">Table 5-1</a> describes the basic classes in the
        !          1533:     JSLib package's I/O module and describes how they are used.</p>
        !          1534:     <p><i>Table 5-1: <a name="77010"></a></i><i>JSLib
        !          1535:     classes</i></p>
        !          1536:     <table width="100%" border="1">
        !          1537:       <tbody>
        !          1538:         <tr>
        !          1539:           <td><b>Class / (filename)</b></td>
        !          1540:           <td><b>Description</b></td>
        !          1541:         </tr>
        !          1542:         <tr>
        !          1543:           <td>File / (<i>file.js</i>)</td>
        !          1544:           <td>Contains most routines associated with the File
        !          1545:           object (implementing <tt>nsIFile</tt>). The library is
        !          1546:           part of the jslib I/O module.</td>
        !          1547:         </tr>
        !          1548:         <tr>
        !          1549:           <td>FileUtils / (<i>fileUtils.js</i>)</td>
        !          1550:           <td>The chrome registry to local file path conversion,
        !          1551:           file metadata, etc.</td>
        !          1552:         </tr>
        !          1553:         <tr>
        !          1554:           <td>Dir / (<i>dir.js</i>)</td>
        !          1555:           <td>Directory creation; variations of directory
        !          1556:           listings.</td>
        !          1557:         </tr>
        !          1558:         <tr>
        !          1559:           <td>DirUtils / (<i>dirUtils.js</i>)</td>
        !          1560:           <td>Paths to useful Mozilla directories and files such as
        !          1561:           <i>chrome</i>, <i>prefs</i>, <i>bookmarks</i>,
        !          1562:           <i>localstore</i>, etc.</td>
        !          1563:         </tr>
        !          1564:       </tbody>
        !          1565:     </table>
        !          1566:     <br>
        !          1567:     <br>
        !          1568:      
        !          1569:     <h4><a name="77074"></a> Using the File class</h4>
        !          1570:     <p>The JSLib <tt>File</tt> <!--INDEX classes:JSLib:File --> 
        !          1571:     <!--INDEX File class, JSLib --> 
        !          1572:     <!--INDEX JSLib libraries:File class --> 
        !          1573:     <!--INDEX JavaScript:application programming:JSLib File class -->
        !          1574:     <!--INDEX application programming, JavaScript:JSLib File class -->
        !          1575:     class exposes most local file routines from the <i>nsIFile</i>
        !          1576:     interface. The <tt>File</tt> class is part of the JSLib I/O
        !          1577:     module, and is defined in <i>jslib/io/file.js</i>. Here is how
        !          1578:     you load the library from xpcshell:</p>
        !          1579: <pre>
        !          1580: $ ./run-mozilla.sh ./xpcshell -w -s
1.5       petejc   1581: js&gt; load('chrome/jslib/jslib.js');
1.1       david    1582: *********************
                   1583: JS_LIB DEBUG IS ON
                   1584: *********************
1.12    ! petejc   1585: js&gt;
        !          1586: </pre>
        !          1587:     <p>Once JSLib is loaded, you can load the <tt>File</tt> module
        !          1588:     with an <tt>include</tt> statement:</p>
        !          1589: <pre>
        !          1590: js&gt; include(`chrome://jslib/content/io/file.js');
1.1       david    1591: *** Chrome Registration of package: Checking for contents.rdf at
                   1592: resource:/chrome/jslib/
                   1593: *** load: filesystem.js OK
                   1594: *** load: file.js OK
                   1595: true
1.12    ! petejc   1596: js&gt;
        !          1597: </pre>
        !          1598:     <p>Note that <i>file.js</i> loads <i>filesystem.js</i> in turn.
        !          1599:     The class <tt>FileSystem</tt> in <i>filesystem.js</i> is the
        !          1600:     base class for the <tt>File</tt> object. You can also load
        !          1601:     <i>file.js</i> by using the top-level construct
        !          1602:     <tt>JS_LIB_PATH</tt>:</p>
        !          1603: <pre>
        !          1604: js&gt; include(JS_LIB_PATH+'io/file.js');
        !          1605: </pre>
        !          1606:     <p>Once you have the <i>file.js</i> module loaded, you can
        !          1607:     create an instance of a <tt>File</tt> object and call methods
        !          1608:     on it to manipulate the file and path it represents:</p>
        !          1609: <pre>
        !          1610: js&gt; var f = new File('/tmp/foo');
1.1       david    1611: js&gt; f;
                   1612: [object Object]
                   1613: js&gt; f.help; // listing of everything available to the object
                   1614: . . .
                   1615: js&gt; f.path;
                   1616: /tmp/foo
                   1617: js&gt; f.exists( );   // see if /tmp/foo exists
                   1618: false
                   1619: js&gt; f.create( );   // it doesn't, so create it.
                   1620: js&gt; f.exists( );
                   1621: true
                   1622: js&gt; f.isFile( );   // is it a file?
                   1623: true
                   1624: js&gt; f.open('w');  // open the file for writing
                   1625: true
                   1626: js&gt; f.write('this is line #1\n');
                   1627: true
                   1628: js&gt; f.close( );
                   1629: js&gt; f.open( );     // open the file again and
                   1630: js&gt; f.read( );     // read back the data
                   1631: // you can also use default flag 'r' for reading
                   1632: this is line #1
1.12    ! petejc   1633: js&gt; f.close( );
        !          1634: </pre>
        !          1635:     <p>You can also assign the contents of the file to a variable
        !          1636:     for later use, iterative loops through the file contents, or
        !          1637:     updates to the data:</p>
        !          1638: <pre>
        !          1639: js&gt; f.open( );
1.1       david    1640: true
                   1641: js&gt; var contents = f.read( );
                   1642: js&gt; f.close( );
                   1643: js&gt; print(contents);
                   1644: this is line #1
                   1645: js&gt;
                   1646: // rename the file
                   1647: js&gt; f.move(`/tmp/foo.dat');
                   1648: foo.dat
                   1649: filesystem.js:move successful!
                   1650: js&gt; f.path;
1.12    ! petejc   1651: /tmp/foo.dat
        !          1652: </pre>
        !          1653:     <p>These examples show some ways the JSLib <tt>File</tt> object
        !          1654:     can manipulate local files. Using these interfaces can make
        !          1655:     life a lot easier by letting you focus on creating your Mozilla
        !          1656:     application without having to implement XPCOM <tt>nsIFile</tt>
        !          1657:     objects manually from your script.</p>
        !          1658:     <h4><a name="77075"></a> Using the FileUtils class</h4>
        !          1659:     <p>To create an <!--INDEX classes:JSLib:FileUtils --> 
        !          1660:     <!--INDEX FileUtils class, JSLib --> 
        !          1661:     <!--INDEX JSLib libraries:FileUtils class --> 
        !          1662:     <!--INDEX JavaScript:application programming:JSLib FileUtils class -->
        !          1663:     <!--INDEX application programming, JavaScript:JSLib FileUtils class -->
        !          1664:     instance of the <tt>FileUtils</tt> class, use the
        !          1665:     <tt>FileUtils</tt> constructor:</p>
        !          1666: <pre>
        !          1667: js&gt; var fu = new FileUtils( );
1.1       david    1668: js&gt; fu;
1.12    ! petejc   1669: [object Object]
        !          1670: </pre>
        !          1671:     <p>Then look at the object by calling its <tt>help</tt>
        !          1672:     method:</p>
        !          1673: <pre>
        !          1674: js&gt; fu.help;
        !          1675: </pre>
        !          1676:     <p>The difference between using the <i>File</i> and
        !          1677:     <i>FileUtils</i> interfaces is that methods and properties on
        !          1678:     the latter are <i>singleton</i> and require a path argument,
        !          1679:     while the <i>FileUtils</i> utilities are general purpose and
        !          1680:     not bound to any particular file. The <i>FileUtils</i>
        !          1681:     interface has several handy I/O utilities for converting,
        !          1682:     testing, and using URLs, of which this example shows a few:</p>
        !          1683: <pre>
        !          1684: js&gt; fu.exists('/tmp');
1.1       david    1685: true
                   1686: // convert a chrome path to a url
                   1687: js&gt; fu.chromeToPath('chrome://jslib/content/');
                   1688: /usr/src/mozilla/dist/bin/chrome/jslib/jslib.xul
                   1689: // convert a file URL path to a local file path
                   1690: js&gt; fu.urlToPath('file:///tmp/foo.dat');
1.12    ! petejc   1691: /tmp/foo.dat
        !          1692: </pre>
        !          1693:     <p>Most methods on the <tt>FileUtils</tt> objects are identical
        !          1694:     to the methods found in <i>file.js</i>, except they require a
        !          1695:     path argument. Another handy method in the <tt>FileUtils</tt>
        !          1696:     class is <tt>spawn</tt>, which spawns an external executable
        !          1697:     from the operating system. It's used as follows:</p>
        !          1698: <pre>
        !          1699: js&gt; fu.spawn('/usr/X11R6/bin/Eterm');
        !          1700: </pre>
        !          1701:     <p>This command spawns a new Eterm with no argument. To open an
        !          1702:     Eterm with vi, you could also use this code:</p>
        !          1703: <pre>
        !          1704: js&gt; fu.spawn('/usr/X11R6/bin/Eterm', ['-e/usr/bin/vi']);
        !          1705: </pre>
        !          1706:     <p>Checking to see if three different files exist would take
        !          1707:     several lines when using the File class, but the
        !          1708:     <tt>FileUtils</tt> class is optimized for this type of check,
        !          1709:     as the following listing shows:</p>
        !          1710: <pre>
        !          1711: js&gt; var fu=new FileUtils( );
1.1       david    1712: js&gt; fu.exists('/tmp');
                   1713: true
                   1714: js&gt; fu.exists('/tmp/foo.dat');
                   1715: true
                   1716: js&gt; fu.exists('/tmp/foo.baz');
1.12    ! petejc   1717: false
        !          1718: </pre>
        !          1719:     <p>You need to initialize the <tt>FileUtils</tt> class only
        !          1720:     once to use its members and handle local files robustly.</p>
        !          1721:     <h4><a name="77076"></a> Using the Dir class</h4>
        !          1722:     <p>The <tt>Dir</tt> <!--INDEX classes:JSLib:Dir --> 
        !          1723:     <!--INDEX Dir class, JSLib --> 
        !          1724:     <!--INDEX JSLib libraries:Dir class --> 
        !          1725:     <!--INDEX JavaScript:application programming:JSLib Dir class -->
        !          1726:     <!--INDEX application programming, JavaScript:JSLib Dir class -->
        !          1727:     class is custom-made for working with directory structures on a
        !          1728:     local filesystem. To create an instance of the <tt>Dir</tt>
        !          1729:     class, call its constructor and then its <tt>help</tt> method
        !          1730:     to see the class properties:</p>
        !          1731: <pre>
        !          1732: js&gt; var d = new Dir('/tmp');
        !          1733: js&gt; d.help;
        !          1734: </pre>
        !          1735:     <p><tt>Dir</tt> inherits from the same base class as
        !          1736:     <tt>File</tt>, which is why it looks similar, but it implements
        !          1737:     methods used specifically for directory manipulation:</p>
        !          1738: <pre>
        !          1739: js&gt; d.path;
1.1       david    1740: /tmp
                   1741: js&gt; d.exists( );
                   1742: true
                   1743: js&gt; d.isDir( );
1.12    ! petejc   1744: true
        !          1745: </pre>
        !          1746:     <p>The methods all work like those in the <tt>File</tt> and
        !          1747:     <tt>FileUtils</tt> classes, so you can append a new directory
        !          1748:     name to the object, see if it exists, and create it if (it does
        !          1749:     not) by entering:</p>
        !          1750: <pre>
        !          1751: js&gt; d.append('newDir');
1.1       david    1752: /tmp/newDir
                   1753: js&gt; d.path;
                   1754: /tmp/newDir
                   1755: js&gt; d.exists( );
                   1756: false
                   1757: js&gt; d.create( );
                   1758: js&gt; d.exists( );
1.12    ! petejc   1759: true
        !          1760: </pre>
        !          1761:     <h4><a name="77077"></a> Using the DirUtils class</h4>
        !          1762:     <p>Note that <!--INDEX classes:JSLib:DirUtils --> 
        !          1763:     <!--INDEX DirUtils class, JSLib --> 
        !          1764:     <!--INDEX JSLib libraries:DirUtils class --> 
        !          1765:     <!--INDEX JavaScript:application programming:JSLib DirUtils class -->
        !          1766:     <!--INDEX application programming, JavaScript:JSLib DirUtils class -->
        !          1767:     some methods in the <tt>DirUtils</tt> class cannot be called
        !          1768:     from xpcshell and instead must be called from a XUL window into
        !          1769:     which the proper JSLib source file was imported. The following
        !          1770:     XUL file provides two buttons that display information in
        !          1771:     textboxes about the system directories:</p>
        !          1772: <pre>
        !          1773: &lt;?xml version="1.0"?&gt;
1.1       david    1774: &lt;?xml-stylesheet href="chrome://global/skin" type="text/css"?&gt;
1.12    ! petejc   1775: &lt;window xmlns="<a href=
        !          1776: "http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul">http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul</a>"
        !          1777: xmlns:html="<a href=
        !          1778: "http://www.w3.org/1999/xhtml">http://www.w3.org/1999/xhtml</a>"
1.1       david    1779: id="dir-utils-window"
                   1780: orient="vertical"
                   1781: autostretch="never"&gt;
                   1782: &lt;script type="application/x-javascript" src="chrome://jslib/content/io/dirUtils.js"/&gt;
                   1783: &lt;script&gt;
                   1784: var du = new DirUtils( );
                   1785: function getChromeDir( ) {
                   1786: cd = du.getChromeDir( );
                   1787: textfield1 = document.getElementById("tf1");
                   1788: textfield1.setAttribute("value", cd);
                   1789: }
                   1790: function getMozDir( ) {
                   1791: md =   du.getMozHomeDir( );
                   1792: textfield2 = document.getElementById("tf2");
                   1793: textfield2.setAttribute("value", md);
                   1794: }
                   1795: &lt;/script&gt;
                   1796: &lt;box&gt;
                   1797: &lt;button id="chrome" onclick="getChromeDir( );" label="chrome" /&gt;
                   1798: &lt;textbox id="tf1" value="chrome dir" /&gt;
                   1799: &lt;/box&gt;
                   1800: &lt;box&gt;
                   1801: &lt;button id="moz" onclick="getMozDir( );" label="mozdir" /&gt;
                   1802: &lt;textbox id="tf2" value="moz dir" /&gt;
                   1803: &lt;/box&gt;
1.12    ! petejc   1804: &lt;/window&gt;
        !          1805: </pre>
        !          1806:     <hr>
        !          1807:     <hr>
        !          1808:     <a name="260"></a><a href="#b260">[Back]</a> <a name=
        !          1809:     "77034"></a> This book does not pretend to give a complete
        !          1810:     overview of JavaScript. You can view the full JavaScript 1.5
        !          1811:     reference online at <i><a href=
        !          1812:     "http://developer.netscape.com/docs/manuals/index.html?content=javascript.html">
        !          1813:     http://developer.netscape.com/docs/manuals/index.html?content=javascript.html</a></i>.
        !          1814:     
        !          1815:     <hr>
        !          1816:     <a name="261"></a><a href="#b261">[Back]</a> <a name=
        !          1817:     "77035"></a> The third edition of the EMCA-262 EMCAScript
        !          1818:     Language Specification can be found at <i><a href=
        !          1819:     "http://www.ecma.ch/ecma1/STAND/ECMA-262.HTM">http://www.ecma.ch/ecma1/STAND/ECMA-262.HTM</a>.</i>
        !          1820:     
        !          1821:     <hr>
        !          1822:     <a name="262"></a><a href="#b262">[Back]</a> <a name=
        !          1823:     "77036"></a> You can use other DOM methods, but these methods
        !          1824:     are most commonly used in the XPFE. Mozilla's support for the
        !          1825:     DOM is so thorough that you can use the W3C specifications as a
        !          1826:     list of methods and properties available to you in the chrome
        !          1827:     and in the web content the browser displays. The full W3C
        !          1828:     activity pages, including links to the specifications
        !          1829:     implemented by Mozilla, can be found at <i><a href=
        !          1830:     "http://www.w3.org/DOM/">http://www.w3.org/DOM/</a></i> . 
        !          1831:     <hr>
        !          1832:     <br>
        !          1833:     <br>
        !          1834:     File a <a href=
        !          1835:     "http://mozdev.org/bugs/enter_bug.cgi?product=books">Bug</a>
        !          1836:     for chapter 5. <!-- ?php require(NOTES); ? -->
        !          1837:     <?php $post_to_list=NO; $author='reviewers@mozdev.org'; $target_page='ch05'; require(NOTES); ?>

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>