1 <ibex-doc title="The Ibex Reference">
5 by <link url="mailto:adam@ibex.org" text="Adam Megacz"/>
7 <!-- ----------------------------------------------------------------------- -->
8 <section title="Preface">
10 This document is a <b>reference</b>. It is not a
11 <b>specification</b> or a
14 This document does not guide the user gently through examples (as a
15 tutorial would), and it doesn't provide enough detail and formality
16 for a third party to construct a compatible re-implementation of the
17 Ibex Core (as a specification would).
19 Rather, the goal of this document is to completely describe every
20 aspect of the environment that the Ibex Core provides to client
21 applications, from the bottom up. If you want to be an Ibex expert,
22 this is the right document to read. It is assumed that you are already
23 familiar with XML and with either JavaScript or ECMAscript. If
24 you are not familiar with ECMAscript, some reference materials are
25 provided in <link section="Appendix G"/>
27 The <i>shoehorn sequence</i> (how the Ibex Core gets onto the
28 client's computer, and how it knows where to download the initial .ibex
29 from) is not described in this document, since it will be different
30 for every platform that Ibex is ported to.
32 If you need to use or rely on some behavior you notice in the Ibex
33 Core, but which is not clearly defined here, please post to <link
34 url="http://lists.ibex.org/listinfo/users" text="the users mailing list"/>.
38 <!-- ----------------------------------------------------------------------- -->
39 <section title="Key Concepts">
41 <section title="Definitions">
43 <definition term="The Core">
44 Ibex itself; the native code (or Java bytecode) that runs on
45 the client. This term does not include the <i>shoehorn</i>
46 or the <i>UI</i></definition>
48 <definition term="The UI / The Application">
49 a set of files (mostly XML, JavaScript, and PNG images)
50 bundled up in a zip archive, ending with the "..ibex"
51 extension. Together, these files specify the appearance and
52 behavior of the application's user interface. Sometimes
53 we'll refer to this as the ".ibex" to be clear that we're
54 talking about the actual zip archive, rather than its visual
55 appearance when rendered on the screen.</definition>
57 <definition term="The Server">
58 We will use the term "the server" to refer to any other
59 computer which the client makes XML-RPC or SOAP calls
60 to. Note that it is possible for the client and server to be
61 the same machine.</definition>
63 <definition term="The Shoehorn">
64 this is a very small piece of code that is downloaded the
65 first time a client uses Ibex. It downloads the Ibex core,
66 verifies its signature, and launches it with the appropriate
67 parameters indicating where to find the initial UI. The
68 Shoehorn works differently on every platform, and is outside
69 the scope of this document.</definition>
71 <definition term="put/write">
72 In ECMAscript, when you change the value of a property on an
73 object, you are <i>putting</i> to that property, or
74 <i>writing</i> to it. For example, the ECMAscript expression
75 "<tt>foo.bar = 5</tt>" <i>puts</i> the value 5 to the bar
76 property on object foo.</definition>
78 <definition term="get/read">
79 In ECMAscript, when you access the value of a property on an
80 object, you are <i>getting</i> that property, or
81 <i>reading</i> from it. For example, the ECMAscript
82 expression "<tt>return (3 + foo.bar)</tt>" <i>gets</i> the
83 value of bar property on object foo and then adds 3 to it
84 before returning the result.</definition>
86 <definition term="JavaScript">
87 We will use the terms JavaScript and ECMAScript
88 interchangeably in this document. The Ibex interpreter is not
89 completely ECMA-compliant, however (see <link
90 section="Appendix C"/> for details). </definition>
94 <section title="Surfaces">
96 Each top-level window in an Ibex UI is called a
97 <i>surface</i>. There are two kinds of surfaces: <i>frames</i>, which
98 usually have a platform-specific titlebar and border, and
99 <i>windows</i>, which never have any additional platform-specific
102 Whenever we refer to the size or position of a surface, we are
103 referring to the size or position of the UI-accessible portion of the
104 surface; this does not include any platform-specific decorations. This
105 means that if you set the position of a frame to (0,0), the
106 platform-specific titlebar will actually be off the screen on most
107 platforms (it will be above and to the left of the top-left corner of
110 Surfaces are not actual JavaScript objects; you cannot obtain a
111 reference to a surface. However, each surface is uniquely identified
112 by its <i>root box</i>, described in the next section.
116 <section title="Boxes">
118 A <i>box</i> is the fundamental unit from which all Ibex user
119 interfaces are built. Boxes can contain other boxes (known as
120 <i>children</i>). Each Surface has a single box associated with it
121 called the <i>root box</i>; the root box and its children (and its
122 children's children, and so on) form the surface's <i>box tree</i>.
124 There are three ways to think of a box: as a rendered visualization on
125 the screen (the "Visual Representation"), as a JavaScript object (the
126 "Object Representation"), and as an XML tag (the "XML
129 <font color=red>FIXME: diagram here</font>
131 All three representations are equally valid, and being able to figure
132 out what an action in one representation would mean in terms of the other
133 two representations is crucial to a solid understanding of Ibex.
137 <section title="The Object Representation">
139 Each box is a full-fledged ECMAscript object, and can store key-value
140 pairs as properties. Some of these keys have special meaning, which
141 will be explained later. Each box's numeric properties hold its
146 <section title="The Visual Representation">
148 Each box occupies a rectangular region on the surface. The visual
149 appearance of a surface is created by rendering each box in its tree.
150 Unless the <tt>clip</tt> attribute is <tt>false</tt>, each box will
151 clip its childrens' visual representations to its own, so that the
152 children appear "confined to" the parent. Children are rendered after
153 their parents so they appear "on top of" their parents (they obscure
156 Each box has two major visual components, each with subcomponents:
158 <font color=red>FIXME: diagram</font>
160 <list type="unordered">
162 A <b>path</b>, which consists of zero or more lines and
163 curves. The path may be filled with a color, gradient, or
164 texture, and may be stroked with a line of a given thickness
165 and color. If the path is not specified, it defaults to the
166 perimiter of the box.
168 The path has an associated <b>strokecolor</b>, which is a
171 The path has an associated <b>strokewidth</b>, which is a
172 number specifying the width of the stroke.
174 The path also has a <b>fill</b>, which is either a color, gradient, or
177 A single line of <b>text</b>, which can be rendered in
178 different fonts, colors, and sizes.
180 The text has an associated <b>font</b>, which currently can be
181 any font supported by the <link url="http://www.freetype.org"
182 text="FreeType2"/> library.
184 The text also has an associated <b>fontsize</b>
186 The text is drawn in an associated <b>textcolor</b>
190 These eight components plus the size of a box fully specify its
191 appearance. Every single box you see in Ibex is drawn only on the
192 basis of these components and its size.
196 <section title="The XML Representation">
198 A template (discussed in the next section) is an XML file which acts
199 as a blueprint for constructing a tree of boxes. We call this
200 construction process <i>applying</i>, since unlike
201 <i>instantiation</i>, you always apply a template to a pre-existing
202 box, and you can apply multiple templates to the same box. Each XML
203 tag corresponds to a single box, or to another template which will be
204 applied to that box. For example, a <tt>scrollbar</tt> template, when
205 applied, will construct a tree of boxes which has the visual
206 appearance and behavior of a scrollbar.
208 Although it is useful to think of the XML tags as being boxes, keep in
209 mind that the XML representation is only a blueprint for constructing
210 a tree of JavaScript objects. Once the template has been
211 instantiated, the XML is effectively "thrown away", and JavaScript code is
212 free to alter the boxes.
216 <section title="Templates">
218 Each template is an XML document whose root element
219 is <tt><ibex></tt>. Any text content of the root element is
220 ignored, and may safely be used for comments. The root element may
221 have any of the following elements as children, each of which may
222 appear no more than once, and which must appear in this order:
224 Here is a sample Ibex file:
227 <ibex xmlns="ibex.widget" xmlns:lib="ibex.lib">
228 This is a sample Ibex file. Text up here is ignored.
229 Copyright (C) 2004 Mustapha Mond.
231 // code here will be executed only once
234 <box id="container"/>
237 /* This has to be commented out or else it
238 will be treated as a script */
247 <section title="Applying an XML tag to a box">
249 The following description of the box application is extremely detailed
250 and precise; it is intended for UI designers who need to know the
251 exact order in which each event happens. <font color=RED>FIXME:
252 easier description</font>. While this whole process sounds very
253 complex, it actually works pretty intuitively. The description below
254 is given in great detail since most applications will wind up being
255 unintentionally dependent on subtle features of this process.
256 However, most of the time you can just pretend that the XML tags and
257 the boxes are the same thing.
259 To apply an XML tag <b>X</b> to a box <b>B</b>, perform the following
260 operations, in this order:
262 <list type="ordered">
264 Allocate a fresh scope <b>s</b> whose parent scope is
267 Process each child element or text segment of <b>X</b> in the
268 order they appear in the document: For each <i>text
269 segment</i> <b>t</b>:
271 Treat <b>t</b> a JavaScript script, and execute it
272 with <b>s</b> as the root scope.
274 For each <i>child element</i> <b>x</b> of <b>X</b>:
276 Create a new box <b>b</b>.
278 If the name of tag <b>x</b> is not <tt>"box"</tt> (in the
279 default XML namespace), prepend the tag's namespace
280 identifier uri (if any) to the name of the tag, and use
281 the result as a key to retrieve a property from the root
282 stream (defined later). Interpret the resulting stream as
283 a template and apply that template to <b>b</b>.
285 (recursively) apply <b>x</b> to <b>b</b>.
287 If <b>x</b> has an <tt>id</tt> attribute, declare a variable
288 in <b>s</b> whose name is the value of the <tt>id</tt>
289 attribute, prefixed with the <tt>$</tt> character, and whose
292 Copy any <tt>$</tt>-variables created during the application
293 of <b>x</b> into scope <b>s</b>.
295 Append <b>b</b> as the last child of <b>B</b>.
297 Apply any attributes on <b>X</b> to <b>B</b>, except for
298 <tt>id</tt>. Since XML specifies that the order of attributes
299 cannot be significant, Ibex processes attributes in
300 alphabetical order by attribute name. For example, if
301 <b>X</b> has the attribute <tt>foo="bar"</tt>, then the
302 equivalent of the statement <tt>B.foo="bar";</tt> will be
303 performed, with the following exceptions:
305 If the value portion of the attribute is the string
306 <tt>"true"</tt>, put the boolean <tt>true</tt>. If the
307 value is <tt>"false"</tt>, put the boolean <tt>false</tt>.
309 If the value is a valid ECMAscript number, put it as a
310 number (instead of a string).
312 If the value begins with a dollar sign (<tt>$</tt>),
313 retrieve the value of the corresponding variable in
314 <b>s</b> and use that value instead.
316 If the value begins with a dot (<tt>.</tt>), prepend the
317 attributes' namespace identifier uri (if any) and
318 interpret the remainder as a property to be retrieved from
319 the root stream (defined later).
322 The last two steps are referred to as the <i>initialization</i> of the
323 node. There are two important aspects of this ordering to be aware of:
325 <list type="unordered">
327 A given box will be fully initialized before its parent is
328 given a reference to that box. This way, parents can be
329 certain that they will never wind up accessing a box when it
330 is in a partially-initialized state.
332 Attributes are applied <i>after</i> scripts are run so that
333 the attributes will trigger any <i>traps</i> (defined later)
334 placed by the script.
340 <section title="Life Cycle of an Ibex Application">
342 A user begins by specifying the URL of an Ibex application run.
343 Usually this is done by visiting a web page which uses the
344 <i>shoehorn</i> to install the core if it is not already on the user's
345 machine, but you can also supply the URL on the command line.
347 The Ibex Core downloads the .ibex for the application, loads it, applies
348 the <tt>main.ibex</tt> template and renders it onto the screen, running
349 any associated ECMAscript code.
351 The user interacts with the application by clicking and moving the
352 mouse, and by pressing keys on the keyboard. These actions trigger
353 fragments of JavaScript code which are designated to handle events.
354 This JavaScript code can then relay important information back to the
355 server using XML-RPC or SOAP, or it can modify the structure and
356 properties of the user interface to change its appearance, thereby
357 giving feedback to the user.
360 DIAGRAM: graphic here showing the circular feedback cycle.
363 The Ibex core quits when the last remaining surface has been destroyed.
368 <!-- ----------------------------------------------------------------------- -->
369 <section title="Layout and Rendering">
371 The size and position of every other box is determined
372 by its properties, its childrens' sizes, and its parent's size and position.
373 Box layout and rendering happens in four phases: <i>packing</i>,
374 <i>constraining</i>, <i>placing</i>, and <i>rendering</i>. The Core is careful to only
375 perform a phase on a box if the box has changed in a way that
376 invalidates the work done the last time that phase was performed.
378 packing and constraining phases are performed in a single traversal of
379 the tree (packing is preorder, constraining is postorder), and the
380 placing and rendering phases are performed in a second traversal of
381 the tree (first placing, then rendering, both preorder).
383 For brevity, the rest of this chapter deals only with width and
384 columns. Height and rows is treated identically and independently.
385 Also, it is important to note that the term <i>minimum width</i> is
386 not the same thing as the property <tt>minwidth</tt>, although they
389 <section title="The size of the root box">
391 When the user resizes a window, Ibex changes the root box's
392 <tt>maxwidth</tt> and <tt>maxheight</tt> to match the size chosen by
393 the user and then determines the root box's size using the same sizing
394 rules it uses for other boxes.
396 Ibex will always attempt to prevent the
397 user from making the surface smaller than the root box's
398 <tt>minwidth</tt> and <tt>minheight</tt>. If the <tt>hshrink</tt> or
399 <tt>vshrink</tt> flag is set, Ibex will try to prevent the user from
400 resizing the surface at all. However, not all platforms give Ibex
401 enough control to do this.
405 <section title="The alignment point">
407 When talking about positioning, we will often refer to the
408 <i>alignment point</i>.
410 <list type="unordered">
412 If the <tt>align</tt> property is <tt>"center"</tt>, then the
413 alignment point is the center of the box.
415 If the <tt>align</tt> property is <tt>"topleft"</tt>,
416 <tt>"bottomleft"</tt>, <tt>"topright"</tt>, or
417 <tt>"bottomright"</tt>, then the alignment point is
418 corresponding corner of the box.
420 If the <tt>align</tt> property is <tt>"top"</tt>,
421 <tt>"bottom"</tt>, <tt>"right"</tt>, or <tt>"left"</tt>, then
422 the alignment point is middle of the corresponding edge of the
427 <font color=red>FIXME: diagram</font>
429 When positioning a child box, the alignment point is determined by the
430 <i>parent's</i> <tt>align</tt> property. When positioning a visual
431 element (a texture, path, or text string) within a box, the alignment
432 point is determined by the <i>box's own</i> <tt>align</tt> property.
434 A simple way to think about this is that whenever there are two boxes
435 involved in the decision, you should use the parent's alignment point.
439 <section title="Packing">
441 of <i>cells</i> is created within the parent. If the parent's
442 <tt>cols</tt> property is set to 0, the cell grid has an infinite
443 number of columns. Either <tt>cols</tt> or <tt>rows</tt> must be
446 If a child's <tt>visible</tt> property is <tt>false</tt>, it does
447 not occupy any cells (and is not rendered). Otherwise, each child
448 occupies a rectangular set of cells <tt>child.colspan</tt> cells
449 wide and <tt>child.rowspan</tt> cells high.
451 The Core iterates over the cells in the grid in the following
452 order: if <tt>rows</tt> is 0, the Core iterates across each column
453 before proceeding to the next row; otherwise rows come before
454 columns. At each cell, the Core attempts to place the <i>first
455 remaining unplaced child's</i> top-left corner in that cell (with
456 the child occupying some set of cells extending down and to the
457 right of that cell). If the parent has a fixed number of columns
458 and the child's <tt>colspan</tt> exceeds that limit, the child is
459 placed in column zero regardless, but only occupies the available
460 set of cells (it does not "hang off the end" of the box).
462 <img src="image/layout.png">
467 <box id="2" rowspan="2" />
468 <box id="3" colspan="2" />
470 <box id="5" colspan="2" />
474 Notes on the layout example:
476 <list type="ordered">
478 Box '3' doesn't fit in the gap after '2', nor in the gaps either
479 side of '2' on the next row, hence it is pushed onto the 3rd row.
481 Box '4' would fit in the gaps around '2', but must be placed
482 <i>after</i> it's preceeding box, '3'.
488 <section title="Constraining">
490 <list type="ordered">
492 Each box's minimum width is computed recursively as the
495 Its <tt>minwidth</tt>
497 The width of the box's <tt>text</tt> (after applying the
498 box's <tt>transform</tt>).
500 The width of the box's path (after applying the box's
501 <tt>transform</tt>) <i>if the box is <tt>packed</tt></i>.
503 The width of the bounding box enclosing the box's cells.
506 The minimum width of each cell is computed as the minimum
507 width of the box occupying it divided by the box's
510 If a box's <tt>hshrink</tt> property is set to
511 <tt>true</tt>, the box's maximum width is the same as its
512 minimum width; otherwise it is the box's
515 The maximum width of each cell is the <tt>maxwidth</tt> of
516 the box occupying it divided by the box's
523 <section title="Placing">
525 <list type="ordered">
527 Each column's <i>actual width</i> is set to the maximum
528 <i>minimum width</i> of all the cells in that column.
529 <b>NOTE:</b> although a column or row can be sized smaller
530 than its "minimum width" or larger than its "maximum width", a
531 box will <i>never</i> be smaller than its <tt>minwidth</tt> or
532 larger than its <tt>maxwidth</tt>.
534 Each column's maximum width is the largest maximum width of
535 the cells in that column, but no smaller than the column's
538 The <i>slack</i> is the difference between the parent's width
539 and the sum of its columns' actual width. The slack is
540 divided equally among the columns. Any column which has
541 exceeded its maximum width is set to its maximum width, and
542 the difference is returned to the slack. This process is
543 repeated until the slack is zero or all columns are at their
546 Next, the rows and columns are positioned within the parent
547 box. The rows and columns are transformed according to the
548 parent's <tt>transform</tt> property, and the bounding box of
549 the resulting cells are placed such that the cells' alignment
550 point coincides with the parent's alignment point (both
551 alignment points are determined by the parent's <tt>align</tt>
552 property). <font color=red>FIXME: diagram</font>
554 <b>Packed boxes:</b> Each packed box's actual position
555 and size is then set to the aggregation of the actual sizes of
556 the cells it spans. If this size exceeds the box's maximum
557 width, the box is sized to its maximum width and centered
558 horizontally within the space occupied by its cells.
559 <b>Non-packed boxes</b>: each non-packed box is transformed
560 according to the parent's <tt>transform</tt> property and then
561 positioned so that its alignment point is <tt>(child.x,
562 child.y)</tt> pixels from the parent's alignment point (both
563 alignment points are determined by the parent's <tt>align</tt>
570 <section title="Rendering">
572 Boxes are rendered in a depth-first, pre-order traversal. Note that
573 this may cause a non-packed box to overlap its siblings.
575 <list type="ordered">
577 If the box's <tt>transform</tt> property is non-null, the
578 coordinate space is transformed accordingly for the rest of
579 this phase and for the rendering of all children.
581 If the box is packed and has a non-<tt>null</tt> path, the
582 path is translated such that the alignment point of the path's
583 bounding box coincides with the box's alignment point (both
584 alignment points are determined by the box's <tt>align</tt>
587 If a box has a path, that path is filled with the color,
588 gradient, or image specified by the <tt>fill</tt> property and
589 stroked with the color and width specified by the
590 <tt>strokecolor</tt> and <tt>strokewidth</tt> properties.
592 If the box has a non-<tt>null</tt> <tt>text</tt> attribute,
593 the text is rendered in <tt>font</tt> with size
594 <tt>fontsize</tt> and color <tt>textcolor</tt>. The text is
595 then translated such that the alignment point of the text's
596 bounding box coincides with the box's alignment point (both
597 alignment points are determined by the box's <tt>align</tt>
600 The box's children are rendered (pre-prder traversal).
608 <!-- ----------------------------------------------------------------------- -->
609 <section title="Box Properties">
611 <section title="Rendering Properties">
613 Every box has several special properties which control how it is
614 drawn. In general, if you put an
615 invalid value to a special property, no action will be taken -- the
618 <property name="strokecolor" type="string" default="clear">
619 If the value is a 5-character hex string (<tt>#RGB</tt>),
620 7-character hex string (<tt>#RRGGBB</tt>), 9-character hex
621 string (<tt>#AARRGGBB</tt>), the box's stroke color will be set
623 If the value is one of the <link url="http://www.color.org/ICC-1A_1999-04.PDF" text="ICC"/> colors
624 (the same set of color names supported by SVG), the stroke
625 color be set to that color.
626 If the value is <tt>null</tt>, the stroke color will be set to
627 clear (<tt>#00000000</tt>).
630 <property name="strokewidth" type="int" default="1">
631 The width (in pixels) to stroke the path with.
634 <property term="fill">
635 This property can be set to any of the values specified for
636 <tt>strokecolor</tt>.
637 Alternatively, if the value written is an object, its stream
638 will be read and interpreted as a PNG, GIF, or JPEG image,
639 which will become the texture for this box, and the box's
640 <tt>minwidth</tt> and <tt>minheight</tt> properties will be
641 automatically set to the dimensions of the image.
644 <property name="path" type="string" default="""">
645 The box's path. The grammar and feature set
646 supported are identical to that specified in <link url="http://www.w3.org/TR/SVG11/paths.html" text="SVG 1.1, section
650 <property name="text" type="string" default="""">
651 The box's text; writing <tt>null</tt> to this property sets it
655 <property name="font" type="stream" default="<tt>.ibex.font.sansserif</tt>">
656 When an object is written to this property, its stream is read
657 using the <link url="http://www.freetype.org" text="freetype2
658 library"/>, and the resulting font is used to render the
662 <property name="fontsize" type="number" default="<tt>10</tt>">
663 The size (in points) to render the text.
666 <property name="textcolor" type="number" default="black">
667 The color in which to render the font; accepts the same values as <tt>strokecolor</tt>.
672 <section title="Layout Properties">
674 <property name="shrink" type="boolean" default="<tt>false</tt>">
675 If set to <tt>true</tt>, this box will shrink
676 (horizontally/vertically/both) to the smallest size allowed by
677 its children and the bounding box of its path.
680 <property name="x" type="integer" default="<i>varies</i>">
681 If the box is a root box, this is the (x/y)-coordinate of the
682 surface; otherwise it is the distance between the parent's
683 alignment point and this box's alignment point.
686 <property name="globalx" type="integer" default="<i>varies</i>">
687 The distance between this box's (left/top) edge and the root
688 box's (left/top) edge. A put to this property has the same
689 effect as a put to the (<tt>x</tt>/<tt>y</tt>) property,
690 except that it is relative to the root box rather than to this
691 box's parent. <font color=red>FIXME is this fakeable? How is
692 distance measured?</font>
695 <property name="minwidth" type="integer" default="<tt>0</tt>">
696 The desired minimum width and height.
699 <property name="maxwidth" type="integer" default="<tt>ibex.maxint</tt>">
700 The desired maximum width and height.
703 <property name="width" type="integer" default="<i>varies</i>">
704 When read, this is the (width/height) of this box. Writing to
705 this property is equivalent to writing to <i>both</i> the
706 minimum and maximum (width/height).
709 <property name="cols" type="integer" default="<tt>0</tt>">
710 The number of (columns/rows) in which to lay out the children of this
711 box. If set to zero, the number of (columns/rows) is unconstrained.
712 Either <tt>rows</tt> or <tt>cols</tt> must be zero. If
713 <tt>0</tt> is written to <tt>cols</tt> when <tt>rows</tt> is
714 <tt>0</tt>, the write is ignored. If a nonzero value is
715 written to <tt>cols</tt> when <tt>rows</tt> is nonzero,
716 <tt>rows</tt> is set to <tt>0</tt>, and vice versa.
719 <property name="colspan" type="integer" default="<tt>1</tt>">
720 The number of (columns/rows) that this box spans within its parent.
723 <property name="align" type="string" default="<tt>"center"</tt>">
724 Determines the box's alignment point for positioning its text,
725 texture, path, and children.
728 <property name="visible" type="boolean" default="<tt>true</tt>">
729 If set to false, this box will be rendered as if its width and
730 height were zero. If this is a root box, the associated surface
732 When reading from this property, the value
733 <tt>false</tt> will be returned if this box <i>or any of its
734 ancestors</i> is not visible. Thus it is possible to write
735 <tt>true</tt> to a box's <tt>visible</tt> property and then
736 read back <tt>false</tt>.
739 <property name="packed" type="boolean" default="<tt>true</tt>">
740 The layout strategy for this box.
745 <section title="Child Control Properties">
747 During a box initialization, script-private references to a box's
748 descendants with <tt>id</tt> attributes are placed on the box. These
749 references allow scripts on that box to easily refer to descendant
750 nodes created by the template in which the script appears. For
751 example, these two blocks of code have exactly the same effect:
755 <box id="foo"/> <box/>
756 $foo.color = "red"; var $foo = this[0];
761 The following special properties control how a box's children are laid
762 out. If a box has a non-null redirect target, reads and writes to these
763 properties will be forwarded to the redirect target.
765 The <tt>redirect</tt> attribute is very useful for hiding the
766 internal structure of a widget, and for allowing widgets to act as
767 "smart" containers for other widgets. For example, a menu widget might
768 have an invisible child as its redirect target; this way, when boxes
769 representing items on the menu are added as children of the menu
770 widget, they do not appear until the menu is pulled down.
772 <property name="numeric properties" type="int" default="">
773 The <i>n</i>th child of box <tt>b</tt> can be accessed by reading from
774 <tt>b[n]</tt>. The <i>n</i>th child can be removed by writing
775 <tt>null</tt> to <tt>b[n]</tt> (the child will become parentless). A
776 new child can be inserted <i>before</i> the <i>n</i>th child by
777 writing it to <tt>b[n]</tt>; if the value written is already a child of
778 <tt>b</tt>, it will be removed from <tt>b</tt> first. It is important
779 to note that this behavior is different from ECMAscript arrays --
780 writing a non-<tt>null</tt> value to <tt>b[n]</tt> does not eliminate
781 the <i>n</i>th child; it merely shifts it over one position.
782 <b>Note:</b> Unlike most JavaScript objects, enumerating a Box's
783 properties with the JavaScript <tt>for..in</tt> construct will
784 enumerate <i>only</i> the box's children and not any other properties.
787 <property name="clip" type="boolean" default="<tt>true</tt>">
788 If <tt>true</tt>, the visual representation of this box's
789 children will be clipped to the boundaries of this box.
790 <b>Note:</b> setting this property to <tt>false</tt> imposes a
791 substantial performance penalty.
794 <property name="numchildren" type="integer" default="<tt>0</tt>">
795 The number of children this box has.
798 <property name="redirect" type="box" default="<tt>thisbox</tt>">
799 Writing to this property sets the box's redirect
800 target. This property cannot be read from, and can only be
804 <property name="surface" type="" default="<tt>null</tt>">
805 If this box has a parent, this property returns
806 <tt><i>parent</i>.surface</tt>; otherwise it returns null.
807 This property is a simple building block that the widget
808 library uses to implement more complex functionality such as
809 focus control and popups.
814 <section title="Other Box Properties">
816 <property name="cursor" type="string" default="<tt>null</tt>">
817 The shape that the cursor should take when inside this
818 box. Valid values are: <tt>"default"</tt>, <tt>"wait"</tt>,
819 <tt>"crosshair"</tt>, <tt>"text"</tt>, <tt>"hand"</tt>, and
820 <tt>"move"</tt>, as well as resizing cursors<tt>"east"</tt>,
821 <tt>"west"</tt>, <tt>"north"</tt>, <tt>"south"</tt>,
822 <tt>"northwest"</tt>, <tt>"northeast"</tt>,
823 <tt>"southwest"</tt>, and <tt>"southeast"</tt>. Note that on
824 some platforms, resize cursors for opposite directions (such
825 as <tt>northwest</tt> and <tt>southeast</tt> are the
827 If a box's cursor is <tt>null</tt>, its parent's cursor will
828 be used. If the root box's cursor is null, the
829 <tt>"default"</tt> cursor will be used.
832 <property name="mouse.x" type="integer" default="<i>varies</i>">
833 The (horizontal/vertical) distance between the mouse cursor and this
834 box's (left/top) edge. Puts to this property are ignored. This
835 value will not be updated if the mouse is outside the root
836 box of the surface and no button was pressed when it left.
839 <property name="mouse.inside" type="boolean" default="<tt>false</tt>">
840 True if the mouse is inside the rendered region of this box or
841 any of its children. This value will be false if the mouse is
842 inside a portion of this box which is covered up by one of
843 this box's siblings, or one of its ancestors' descendants. Puts
844 to this value are ignored.
847 <property name="static" type="object" default="N/A">
848 Reading from this property will return the parent scope used
849 to execute the <tt><static/></tt> block of the template
850 in which the currently-executing code resides.
853 <property name="thisbox" type="box" default="<tt> </tt>">
854 Returns a reference to the box itself.
855 If <tt>null</tt> is written to this property, and this box is
856 the root box of a surface, the box will be detached and the
857 surface destroyed. If this box has a parent, it will be
858 detached from its parent.
861 <property name="indexof()" type="function" default="<tt> </tt>">
862 This property is actually a function; invoking
863 <tt>parent.indexof(child)</tt> will return the numerical index
864 of <tt>child</tt> in <tt>parent</tt> if <tt>child</tt> is a
865 child of <tt>parent</tt> (or <tt>parent</tt>'s redirect
866 target), and <tt>-1</tt> otherwise. Writing to this property
870 <property name="childadded" type=" " default="<tt> </tt>">
872 These properties are meant to be trapped on <font
873 color=red>FIXME defined later?</font>. Placing a trap on
874 <tt>childadded/childremoved</tt> lets a box receive
875 notification when a child is added/removed. In either
876 situation, the child will be passed as an argument to the trap
877 function <i>after</i> the addition or removal has been
880 Note that if the parent's redirect target is set to another
881 box, these traps will only be invoked when children are
882 manipulated by reading and writing to the parent. Reads and
883 writes directly to the redirect target will <i>not</i> trigger
886 Note also that these traps are still triggered if a box's
887 <tt>redirect</tt> target is <i>null</i>. This is useful for
888 boxes that need to accept children and then relocate them
894 <section title="Notification Properties">
896 The following properties are used to notify a box of changes specific
897 to that particular box.
899 <property name="Enter">
900 The value <tt>true</tt> is written to this property when the mouse enters the box.
903 <property name="Leave">
904 The value <tt>true</tt> is written to this property when the mouse leaves the box.
907 <property name="SizeChange">
908 The value <tt>true</tt> is put to this property after the size
914 <section title="Root Box Properties">
916 The following special properties are only meaningful on the root box
919 <property name="Focused">
920 The value <tt>true</tt> is put to this property on the root box
921 when the surface gains the input focus, and <tt>false</tt> when
922 the surface loses the input focus. Reading from this value will
923 return <tt>true</tt> if the surface is focused and <tt>false</tt>
924 if it is not. Putting <tt>true</tt> to this property will
925 <i>not</i> cause the surface to "steal" the input focus from other
929 <property name="Maximized">
930 The value <tt>true</tt> is put to this property on the root box
931 when the surface is maximized, and <tt>false</tt> when the surface
932 is un-maximized. Reading from this value will return <tt>true</tt>
933 if the surface is maximized and <tt>false</tt> if it is
934 not. Putting <tt>true</tt> to this property will maximize the
935 window, and putting <tt>false</tt> to this property will
936 unmaximize the window.
937 Note that not all platforms support maximization.
940 <property name="Minimized">
941 The value <tt>true</tt> is put to this property on the root box
942 when the surface is minimized, and <tt>false</tt> when the surface
943 is unminimized. Reading from this value will return <tt>true</tt>
944 if the surface is minimized and <tt>false</tt> if it is
945 not. Putting <tt>true</tt> to this property will minimize the
946 window, and putting <tt>false</tt> will unminimize it.
949 <property name="Close">
950 When the user attempts to close a surface, the value
951 <tt>true</tt> will be put to this property. Scripts may trap
952 this property <font color=red>FIXME defined later?</font> to
953 prevent the window from closing. Putting the value
954 <tt>true</tt> to this property on a root box has the same
955 effect as putting <tt>null</tt> to the <tt>thisbox</tt>
959 <property name="icon">
960 The surface's icon. This is usually displayed on the titlebar of a
961 window. The value should be the stream name of a PNG image. Note
962 that not all platforms support this property.
965 <property name="titlebar">
966 The surface's titlebar text. Note that not all platforms support
967 this property. Only ASCII characters 0x20-0x7F are permitted.
974 <!-- ----------------------------------------------------------------------- -->
975 <section title="Streams">
977 <section title="Every object has a stream...">
979 Every object has a <i>stream</i> associated with it. A stream is a
980 sequence of bytes that can be read or written to.
982 By default an object has an empty stream (zero bytes). However, some objects
983 (returned from special methods on the <tt>ibex</tt> object) have
984 streams yielding data read from an url, file, or a component of a zip
985 archive. In a future release, the stream associated with a box will
986 be an .ibex template which, when applied, will fully reconstitute the
991 <section title="...but streams are not objects">
993 Despite the ubiquity of streams, you cannot actually reference a
994 stream, since it is not an object. Instead, you simply reference the
995 object it belongs to. If you are familiar with Java, this is similar
996 to how every Java object has a monitor associated with it, but you
997 cannot directly manipulate the monitor (you can't pass around a
998 reference to just the monitor).
1000 In the rest of the section we will sometimes refer to "getting
1001 properties from a stream" or "passing a stream to a function"; this is
1002 just shorthand for saying to perform those actions on the object the
1007 <section title="Creating Streams from URLs">
1009 You can create a stream from a URL by calling
1012 var r = ibex.stream.url("http://...");
1015 This will return an object whose stream draws data from the specified
1016 URL. Streams are loaded lazily whenever possible.
1020 <section title="Getting Substreams">
1022 Most stream objects let you access
1023 substreams using the usual JavaScript operators <tt>[]</tt> and
1024 <tt>.</tt>, as well as the <tt>for..in</tt> syntax.
1027 // r1 and r2 are equivalent but not equal (!=)
1028 var r1 = ibex.stream.url("http://www.ibex.org/foo/bar.html");
1029 var r2 = ibex.stream.url("http://www.ibex.org/foo")["bar.html"];
1034 <section title="The Root Stream">
1036 The empty-string property on the <tt>ibex</tt> object is called the
1037 <i>root stream</i>. You can access this object as <tt>ibex..</tt> or
1038 <tt>ibex[""]</tt>. Additionally, any expression which starts with a
1039 dot is treated as property to be retrieved from the root stream. The
1040 following three expressions are equivalent:
1050 <section title="Static Blocks">
1052 You can access variables within the static block of a template by
1053 appending a double period (<tt>..</tt>) and the variable name to the
1054 stream used to load that template:
1057 <!-- org/ibex/themes/monopoly/scrollbar.ibex -->
1063 ibex.log.print(org.ibex.themes.monopoly.scrollbar..foo); // prints "12"
1068 <section title="Formatting Streams">
1070 If you attempt to send a stream as part of an XML-RPC call, the
1071 stream will be read in its entirity, Base64-encoded, and transmitted
1072 as a <tt><base64/></tt> element.
1074 Ibex supports two special URL protocols. The first is <tt>data:</tt>,
1075 which inteprets the rest of the URL as a Base64 encoded sequence of
1076 bytes to use as a source. The other is <tt>utf8:</tt> which
1077 interpretets the rest of the string as a Unicode character sequence to
1078 be UTF-8 encoded as a string of bytes to use as a source.
1081 var r5 = ibex.stream.url("data:WFWE876WEh99sd76f");
1082 var r6 = ibex.stream.url("utf8:this is a test");
1085 You can read a UTF-8 encoded string from a stream like this:
1088 var myString = ibex.stream.fromUTF(ibex.stream.url("utf8:this is a test"));
1090 You can also parse XML from a stream using SAX like this:
1093 ibex.stream.xml.sax(ibex.stream.url("http://foo.com/foo.xml"),
1094 { beginElement : function(tagname, attributeKeyValuePairs) { ... },
1095 endElement : function(tagname) { ... },
1096 content : function(contentString) { ... }
1097 whitespace : function(whitespaceString) { ... }
1105 <!-- ----------------------------------------------------------------------- -->
1106 <section title="The Ibex object">
1108 The <tt>ibex</tt> object is present in the top-level scope of every
1109 script. It has the following properties:
1111 <section title="General">
1113 <table class="props">
1114 <tr><td><tt>ibex.box</tt></td> <td>reading from this property returns a new box</td></tr>
1115 <tr><td><tt>ibex.clone(o)</tt></td> <td>creates a clone of object <i>o</i></tr>
1116 <tr><td><tt>ibex.bless(s)</tt></td> <td>returns a blessed clone of stream <i>s</i></tr>
1121 <section title="ECMA Library Objects">
1123 <table class="props">
1124 <tr><td><tt>ibex.date</tt></td> <td>reading from this property returns a new date</td></tr>
1125 <tr><td><tt>ibex.math</tt></td> <td>this object contains the ECMA math functions</td></tr>
1126 <tr><td><tt>ibex.regexp(s)</tt></td> <td>return a regexp object corresponding to string <i>s</i></td></tr>
1127 <tr><td><tt>ibex.string</tt></td> <td>this object contains the ECMA string manipulation functions</td></tr>
1132 <section title="Logging">
1134 <property name="ibex.log.debug(m, o)">
1135 log the debug message <i>m</i>, optionally dumping object
1139 <property name="ibex.log.info(m, o)">
1140 log the informational message <i>m</i>, optionally dumping
1144 <property name="ibex.log.warn(m, o)">
1145 log the warning message <i>m</i>, optionally dumping object
1149 <property name="ibex.log.error(m, o)">
1150 log the error message <i>m</i>, optionally dumping object
1157 <!-- ----------------------------------------------------------------------- -->
1158 <section title="User Interface">
1160 <property name="ibex.ui.browser(u)">
1161 opens a new browser window with URL <i>u</i>
1164 <property name="ibex.ui.key.control">
1165 true if the control key is depressed
1168 <property name="ibex.ui.key.shift">
1169 true if the shift key is depressed
1172 <property name="ibex.ui.key.alt">
1173 true if the alt key is depressed
1176 <property name="ibex.ui.key.name.alt">
1177 the name of the "alt" key (usually either "alt", "meta", or
1181 <property name="ibex.ui.clipboard">
1182 the contents of the clipboard; can be read and written to
1185 <property name="ibex.ui.maxdim">
1186 the maximum dimension of any UI element; usually
1187 2<sup>31</sup>, but may be smaller
1190 <property name="ibex.ui.screen.width">
1191 the width of the screen, in pixels
1194 <property name="ibex.ui.screen.height">
1195 the height of the screen, in pixels
1198 <property name="ibex.ui.mouse.button">
1199 either 0, 1, 2, or 3, indicating the mouse button currently
1203 <property name="ibex.ui.frame">
1204 when a box is written to this property, it becomes the root
1208 <property name="ibex.ui.window">
1209 when a box is written to this property, it becomes the root
1213 <property name="ibex.ui.font.serif">
1214 an object whose stream is a a builtin serif font
1217 <property name="ibex.ui.font.sansserif">
1218 an object whose stream is a builtin sans-serif font
1221 <property name="ibex.ui.font.monospace">
1222 an object whose stream is a a builtin fixed-width font
1225 <section title="Networking">
1227 <property name="ibex.net.http">
1228 <font color=red><i>not yet implemented</font>
1231 <property name="ibex.net.rpc.xml(u)">
1232 return an XML-RPC call object with endpoint URL <i>u</i>
1235 <property name="ibex.net.rpc.soap(u,">
1236 return a SOAP call object with endpoint URL <i>u</i>,
1237 SoapAction <i>a</i>, and XML Namespace <i>n</i>
1242 <section title="Threads">
1244 <property name="ibex.thread">
1245 when a function is written to this property, a new thread is
1249 <property name="ibex.thread.yield()">
1250 yield the current thread
1253 <property name="ibex.thread.sleep(n)">
1254 sleep for <i>n</i> milliseconds
1259 <section title="Streams">
1261 <property name="ibex.stream.url(u)">
1262 returns a new object whose stream is drawn from URL <i>u</i>
1265 <property name="ibex.stream.unzip(s)">
1266 unpacks a zip archive from <i>s</i>'s stream
1269 <property name="ibex.stream.uncab(s)">
1270 unpacks a cab archive from <i>s</i>'s stream
1273 <property name="ibex.stream.cache(s,k)">
1274 valign=top>wraps a disk-backed read cache keyed on <i>k</i>
1275 around <i>s</i>'s stream
1278 <property name="ibex.stream.watch(s,f)">
1279 returns an object whose stream is drawn from <i>s</i>'s
1280 stream, but invokes <i>f(n,d)</i> as it is read from.
1283 <property name="ibex.stream.parse.xml(s, h)">
1284 Use SAX to parse the XML document on stream <i>s</i> with
1288 <property name="ibex.stream.parse.html(s, h)">
1289 Same as <tt>parse.xml()</tt>, but tries to fix broken HTML.
1292 <property name="ibex.stream.parse.utf8(s)">
1294 treat <i>s</i>'s stream as a string encoded as a UTF-8 byte stream and return the string</tr>
1296 <property name="ibex.stream.homedir">
1297 <tt>ibex.stream.tempdir</tt>
1302 <section title="Cryptography">
1304 <property name="ibex.crypto.rsa(k,s)">
1305 <i><font color=red>not implemented yet:</font></i> return a
1306 stream which rsa-decrypts stream <i>s</i> with key <i>k</i>
1309 <property name="ibex.crypto.rc4(k,s)">
1310 <i><font color=red>not implemented yet:</font></i> return a
1311 stream which rc4-decrypts stream <i>s</i> with key <i>k</i>
1314 <property name="ibex.crypto.md5(s)">
1315 <i><font color=red>not implemented yet:</font></i> immediately
1316 MD5-hash stream <i>s</i>
1319 <property name="ibex.crypto.sha1(s)">
1320 <i><font color=red>not implemented yet:</font></i> immediately
1321 SHA1-hash stream <i>s</i>
1327 <!-- ----------------------------------------------------------------------- -->
1328 <section title="Traps">
1330 <section title="Simple Traps">
1332 You can add a trap to a property by applying the <tt>++=</tt> operator
1333 to a function with one argument. The trap will be invoked whenever
1334 that property is written to.
1338 foo ++= function(z) {
1339 ibex.log.info("foo is " + z);
1344 If another script were to set the property <tt>"foo"</tt>
1345 on the box above to the value <tt>5</tt>, the function above would be
1346 invoked with the argument <tt>5</tt>. The function would then log
1347 the string <tt>"foo is 5"</tt>.
1349 Within a trap, the expression <tt>trapee</tt> can be used to
1350 get a reference to the box on which the trap was placed.
1352 The expression <tt>trapname</tt> returns the name of the
1353 trap executing the current function. This is useful when a function
1354 is applied to multiple traps. For example:
1358 func ++= function(z) {
1359 ibex.log.info("called trap " + trapname);
1368 <section title="Removing Traps">
1370 You can remove a trap by using the <tt>--=</tt> operator with the same
1371 function you added as a trap:
1375 var myfunc = function(z) { /* ... */ }
1386 <section title="Multiple Traps on the Same Property">
1388 When the property is <i>written</i> to, each of the trap functions placed
1389 on it will be invoked in the opposite order that they were placed on
1390 the box -- the most recently placed trap will execute first. This
1391 last-to-first execution of traps is called <i>cascading</i>. After the
1392 last trap is invoked, the value is stored on the box (remember, boxes
1393 are objects, so they can hold properties just like all other
1394 ECMAscript objects).
1398 <section title="Manual Cascades">
1400 There are two additional tricks you can use when placing traps. The
1401 first is a <i>manual cascade</i>. If you want to cascade to lower
1402 traps in the middle of a function, or you want to cascade with a
1403 different value than the value passed to you (in effect "lying" to
1404 lower traps), you can use <tt>cascade</tt>. For example:
1408 color ++= function(c) {
1409 ibex.log.info("refusing to change colors!");
1415 This effectively creates a box whose color cannot be changed, and
1416 which complains loudly if you try to do so.
1418 Do <i>not</i> try to do something like this:
1422 color ++= function(z) {
1423 color = "black"; // INFINITE LOOP! BAD!!!
1427 To prevent automatic cascading, return <tt>true</tt> from your function:
1431 color ++= function(z) {
1432 return true; // the box's color will not change
1439 <section title="Read Traps">
1441 The other trick is a <i>read-trap</i>. Read traps are just like normal
1442 traps, except that you use a function that takes zero arguments instead of one. Read traps
1443 also do not automatically cascade.
1447 doublewidth <tt>++=</tt> function() { return 2 * width; }
1451 If another script attempts to read from the <tt>doublewidth</tt>
1452 property on this box, the value it gets will be twice the actual width
1453 of the box. Note that
1454 the actual <tt>doublewidth</tt> property on the box never gets written
1455 to, since the trap does not cascade.
1457 You can manually cascade on read traps as well:
1461 text <tt>++=</tt> function() { return "my text is " + cascade; }
1465 Read traps are only rarely needed -- most of the time a write trap
1470 <section title="Prohibited Traps">
1472 To prevent confusing and hard-to-debug behaviors, scripts may not
1473 place traps on any of the properties described in the sections
1474 <link section="Box Layout Properties"/>, <link
1475 section="Child-Control Properties"/>, or <link section="Other Box
1476 Properties"/> except for <tt>childadded</tt>,
1477 <tt>childremoved</tt> and <tt>surface</tt>. <font
1478 color=red>FIXME: remove?</font>
1482 <section title="Exceptions and Traps ">
1484 If an uncaught exception is thrown from a trap, Ibex will log the
1485 exception, but will <i>not</i> propagate it to the code which
1486 triggered the trap. If the trap was a read trap, the value
1487 <tt>null</tt> will be returned.
1488 <font color=red>FIXME: is this right?</font>
1492 <section title="Architectural Significance of Traps">
1494 Traps are the backbone of Ibex. Since almost all UI programming is
1495 event/demand driven, traps eliminate the need for separate
1496 member/getter/setter declarations, often cutting the amount of typing
1497 you have to do to a third of what it would normally be.
1501 <section title="Cloning">
1503 <I>Cloning</i> is a companion technique for traps; together they can
1504 be used to simulate any sort of environment you might need. When you
1505 call <tt>ibex.clone(o)</tt>, Ibex returns a new object (called the
1506 <i>clone</i>) which compares with equality (<tt>==</tt>) to the
1507 original object. Furthermore, both objects are "equal" as keys in
1512 var theclone = ibex.clone(o);
1514 ibex.log.info(hash[theclone]); // prints "5"
1517 Any writes to properties on the clone will actually write to
1518 properties on the original object, and reads from properties on the
1519 clone will read properties on the original object. In fact, the only
1520 thing that can be used to distinguish the original from the clone is
1521 traps -- a trap placed on the clone is <i>not</i> placed on the
1522 original object as well.
1526 <section title="Ibex self-emulation">
1528 When the core first starts up, it clones the <tt>ibex</tt> object,
1529 creates a stream for the initial .ibex, and then places a trap on the
1530 cloned <tt>ibex</tt> object so that its empty-string property returns
1531 the .ibex stream. The cloned Ibex object is then passed as the third
1532 (optional) argument to <tt>ibex.apply()</tt>, making it the default
1533 <tt>ibex</tt> object for the scripts that are executed as part of the
1534 template instantiation.
1537 var new_ibex = ibex.clone(ibex);
1538 var stream = ibex.bless(ibex.stream.url("http://..."));
1539 new_ibex[""] ++= function() { return stream; }
1540 ibex.apply(ibex.box, new_ibex..main, new_ibex);
1543 Note that we called <tt>ibex.bless()</tt> on the stream before tacking
1544 it on to the new Ibex object. The bless function returns a clone of
1545 the object passed to it, with a few traps which are explained below.
1546 Additionally, any sub-streams retrieved by accessing properties of the
1547 blessed stream will also automatically be blessed (blessed streams are
1550 Blessing a stream serves three purposes:
1552 <list type="unordered">
1554 Blessed clones always return the appropriate static block when
1555 their empty property is accessed; this ensures that references
1556 to the static blocks of other templates work properly.
1558 Blessed substreams can return their parent stream by accessing
1559 a hidden property which is reserved for internal use by Ibex.
1560 This ensures that Ibex can automatically add filename
1561 extensions where needed, according to the following rules:
1563 If the stream is a template to be applied, the string
1564 <tt>".ibex"</tt> is appended.
1566 If the stream is an image, the string <tt>".png"</tt> is
1567 appended. If no stream is found, <tt>".jpeg"</tt> and
1568 <tt>".gif"</tt> are tried, in that order.
1570 If the stream is an font, the string <tt>".ttf"</tt> is
1573 Every call to <tt>ibex.bless()</tt> returns a different object
1574 (which happens to be a clone of the object passed to it) with
1575 a completely separate set of static blocks.
1579 Ibex can self-emulate by using <tt>ibex.clone()</tt> on the Ibex object;
1580 this technique is very similar to the use of ClassLoaders in
1581 Java. This is useful for a number of applications, including
1582 debuggers, IDEs, sandboxing untrusted code, remote-control, and
1583 others. For example:
1586 var newLoadFunction = function(url) { /* ... */ };
1587 var new_ibex = ibex.clone(ibex);
1588 new_ibex.load ++= function() { return newLoadFunction; }
1589 ibex.apply(ibex.box, .main, new_ibex);
1595 <!-- ----------------------------------------------------------------------- -->
1596 <section title="Contexts and Threading">
1598 <section title="Contexts">
1600 From the perspective of an application writer, Ibex is strictly
1601 single-threaded. Ibex is always in exactly one of the following three
1604 <list type="unordered">
1606 <b>Rendering Context</b> (redrawing the screen)
1608 <b>Event Context</b> (executing javascript traps triggered by an event)
1610 <b>Thread Context</b> (executing a background thread spawned with <tt>ibex.thread</tt>)
1614 There are two important restrictions on what can be done in particular contexts:
1616 <list type="unordered">
1618 The <tt>box.mouse</tt> property and its subproperties
1619 (<tt>x</tt>, <tt>y</tt>, and <tt>inside</tt>) can only be read
1620 from within the Event Context, or in a thread context
1621 <i>after</i> a the <tt>box.mouse</tt> property on this box or
1622 an ancestor box has been written to.
1624 Blocking operations (anything that accesses the network or
1625 disk) can only be performed in the Thread Context.
1631 <section title="Background Threads">
1633 Ibex offers easy access to threads. Spawning a background thread is as
1634 simple as writing a function to the <tt>ibex.thread</tt> property:
1637 ibex.thread = function() {
1638 ibex.log.info("this is happening in a background thread!");
1642 The argument set passed to the function is currently undefined and is
1643 reserved for use in future versions of Ibex. Scripts should not
1644 depend on the number or content of these arguments.
1646 Ibex is <i>cooperatively multitasked</i>, so threads must not process
1647 for too long. This was a deliberate choice; cooperatively
1648 multitasked environments do not require complex locking primitives
1649 like mutexes and semaphores which are difficult for novices to
1650 understand. The disadvantage of cooperative multitasking is that one
1651 thread can hog the CPU. This is unlikely to happen in Ibex for two reasons:
1652 first, all blocking I/O operations <i>automatically</i> yield the CPU,
1653 so the overall user interface never becomes unresponsive because it is
1654 waiting for a disk or network transfer. Second, since Ibex is strictly
1655 a user interface platform, Ibex scripts are unlikely to perform highly
1656 compute-intensive operations that keep the CPU busy for more than a
1661 <section title="Events">
1663 Every execution of the Event Context begins with an event, which
1664 consists of a key/value pair, and a mouse position, which consists of
1665 an x and y coordinate. The possible keys are <tt>_Press[1-3]</tt>,
1666 <tt>_Release[1-3]</tt>, <tt>_Click[1-3]</tt>, <tt>_DoubleClick[1-3]</tt>,
1667 <tt>_Move</tt>, <tt>_KeyPressed</tt>, and <tt>_KeyReleased</tt>.
1669 Here are two example events:
1671 An event is triggered by writing the key to the value on a box. This
1672 triggers any trap handlers which may be present. Once these handlers
1673 have executed, Ibex figures out which child of the current box contains
1674 the mouse (taking into account that some boxes may cover up others)
1675 and writes the key and value to that box. If none of the box's
1676 children contain the mouse position, Ibex removes the leading
1677 underscore from the key name and writes the value to
1678 <i>that</i> property. Once all the traps on that property have
1679 executed, the value is written to the box's parent.
1681 Intuitively, Ibex delivers the underscored event to every box from the
1682 root to the target, and then delivers the non-underscored event to
1683 that same set of boxes in reverse order. So the event travels down
1684 the tree to the target, and then back up to the root. The following
1685 example prints out "first second third fourth" in that order.
1689 _Press1 ++= function(b) { ibex.log.info("first"); }
1690 Press1 ++= function(b) { ibex.log.info("fourth"); }
1692 _Press1 ++= function(b) { ibex.log.info("second"); }
1693 Press1 ++= function(b) { ibex.log.info("third"); }
1698 In general, you should use the <i>non-underscore</i> names to respond
1699 to user input and use the underscored names when you want to override
1700 child boxes' behavior or route events to particular boxes (for
1701 example, when implementing a focus protocol). This is why the
1702 underscored elements are delivered to parents before children (so
1703 parents can override their childrens' behavior), but non-underscored
1704 events are delivered to children before parents (since, visually, a
1705 mouse click is usually "intended" for the leaf box underneath the
1710 <section title="Stopping the Process">
1712 At any point in this sequence, a trap handler can choose not to
1713 cascade (by returning <tt>true</tt> from the trap handler function).
1714 This will immediately cease the propagation of the event. This is how
1715 you would indicate that an event has been "handled".
1719 <section title="Re-routing events">
1721 At any point in the Event Context, you can write to the <tt>mouse</tt>
1722 property on any box. The value written should be an object with two
1723 properties, <tt>x</tt> and <tt>y</tt>. For example:
1726 _Press1 ++= function(p) {
1727 mouse = { x: 32, y: 77 };
1731 The coordinates specified are relative to the box whose <tt>mouse</tt>
1732 property is being written to. There is no need to supply the
1733 <tt>inside</tt> property; it is computed automatically. Writing to
1734 the <tt>mouse</tt> property causes Ibex to recompute the eventual
1735 target box, and also alter the values returned by <tt>mouse.x</tt>,
1736 <tt>mouse.y</tt>, and <tt>mouse.inside</tt> for any <i>descendants</i>
1737 of the current box. Writing to the <tt>mouse</tt> property also
1738 automatically prevents the event from returning to the box's parents
1739 -- it is equivalent to not cascading on the non-underscored event.
1740 This ensures that child boxes cannot trick their parent boxes into
1741 thinking that the mouse has moved.
1743 If you want the event to "skip over" the boxes between the trapee
1744 and the target, or if you want to re-route an event to a box which
1745 is not a descendant of the current box, simply write the value to
1746 the proper key on the target box.
1750 _KeyPressed = function(k) { ibex.log.info("first"); }
1751 KeyPressed = function(k) { ibex.log.info("sixth"); }
1752 $recipient.target = $target;
1753 <box id="recipient">
1754 _KeyPressed = function(k) {
1755 ibex.log.info("second");
1756 thisbox.target.KeyPressed = k;
1757 // inhibit cascade to keep the event from going to $excluded
1760 KeyPressed = function(k) { ibex.log.info("fifth"); }
1762 _KeyPressed = function(k) { ibex.log.info("this never happens"); }
1766 _KeyPressed = function(k) { ibex.log.info("third"); }
1767 KeyPressed = function(k) { ibex.log.info("fourth"); }
1774 <section title="Synthesizing Your Own Events">
1776 You can create "fake events" by simply writing to the <tt>mouse</tt>
1777 property and then writing a value to one of the underscored properties
1778 on a box. This will have exactly the same effect as if the use had
1779 actually pressed a key, clicked a button, or moved the mouse -- they
1780 are indistinguishable.
1784 <section title="Enter and Leave">
1786 Ibex will trigger the <tt>Enter</tt> and <tt>Leave</tt> properties as
1787 it walks down the tree, based on the position of the mouse (or the
1788 faked position if the <tt>mouse</tt> property has been written to).
1789 However, <tt>Enter</tt> and <tt>Leave</tt> are not events since they
1790 do not implicitly cascade up or down the tree.
1794 <section title="Detailed Description of Events">
1796 <property name="Press1 / Press2 / Press3">
1797 Indicates that the use has pressed a mouse button. On
1798 platforms with three mouse buttons, the <i>middle</i> button
1799 is button 3 -- this ensures that applications written to only
1800 use two buttons (1 and 2) will work intuitively on three button
1804 <property name="Release1 / Release2 / Release3">
1805 Indicates that the use has released a mouse button.
1808 <property name="Click1 / Click2 / Click3">
1809 Indicates that the user has pressed and released the
1810 mouse button without moving the mouse much (exactly how
1811 much is platform-dependent).
1814 <property name="DoubleClick1 / DoubleClick2 / DoubleClick3">
1815 Indicates that the user has clicked the
1816 mouse button twice within a short period of time (exactly how long is platform-dependent).
1819 <property name="Move">
1820 Indicates that the mouse has moved while within this box, or that
1821 the mouse while outside this box <i>if a button was pressed while within this box and has not yet been released</i>
1824 <property name="KeyPressed KeyReleased">
1825 A string is written to this property when a key is pressed or
1826 released If the key was any other key, a multi-character
1827 string describing the key will be put. For simplicity, we use
1828 the VK_ constants in the <link
1829 url="http://java.sun.com/products/jdk/1.1/docs/api/java.awt.event.KeyEvent.html#VK_0"
1830 text=" Java 1.1 API java.awt.event.KeyEvent class"/>. When a
1831 key is pressed or released, the string put will be the portion
1832 of its VK_ constant after the underscore, all in lower case.
1833 If the shift key was depressed immediately before the event
1834 took place, then the string will be capitalized. Special
1835 keynames are also capitalized; shift+home is reported as
1836 "<tt>HOME</tt>". Symbols are capitalized as they appear on the
1837 keyboard; for example, on an American QWERTY keyboard, shift+2
1838 is reported as "<tt>@</tt>". If the alt, meta, or command key
1839 was depressed immediately before this key was pressed, then
1840 the string will be prefixed with the string "<tt>A-</tt>". If
1841 the control key was depressed while this key was pressed, then
1842 the string will be prefixed with the string "<tt>C-</tt>". If
1843 both alt and control are depressed, the string is prefixed
1844 with "<tt>C-A-</tt>". Ibex does not distinguish between a key
1845 press resulting from the user physically pushing down a key,
1846 and a 'key press' resulting from the keyboard's typematic
1847 repeat. In the rare case that an application needs to
1848 distinguish between these two events, it should watch for
1849 KeyReleased messages and maintain an internal key-state
1856 <!-- ----------------------------------------------------------------------- -->
1857 <section title="Networking">
1859 <section title="XML-RPC">
1861 XML-RPC objects can be created by calling <tt>ibex.net.rpc.xml(<<i>XML-RPC
1862 URL</i>>)</tt>, and then invoking methods on that object. For example,
1865 Press1 += function(v) {
1866 ibex.thread = function() {
1867 color = ibex.net.rpc.xml("http://xmlrpc.ibex.org/RPC2/").color.getTodaysColor("Friday");
1872 When the user clicks the first mouse button on this box, it will
1873 contact the server <tt>xmlrpc.ibex.org</tt>, route to the
1874 <tt>/RPC2/</tt> handler and invoke the <tt>getTodaysColor()</tt>
1875 method on the <tt>color</tt> object with a single string argument
1876 <tt>"Friday"</tt>. The return value will be used to change the color
1877 of the box the user clicked on.
1879 Note that in this example we spawned a background thread to handle the
1880 request -- the <tt>Press1</tt> event is delivered in the foreground
1881 thread, and XML-RPC methods may only be invoked in background
1882 threads. This is to prevent the UI from "locking up" if the server
1883 takes a long time to reply.
1885 If the XML-RPC method faults, an object will be thrown with two
1886 properties: <tt>faultCode</tt> and <tt>faultString</tt>, as defined in
1887 the <link url="http://www.xmlrpc.org/spec" text="XML-RPC specification"/>. If
1888 Ibex encounters a network, transport, or session-layer error, it will
1889 throw a <tt>String</tt> object describing the error in a
1890 human-readable format. Scripts should not rely on the contents of
1891 this string having any special structure or significance.
1893 If an object with an associated non-empty stream is passed as an
1894 argument to an XML-RPC method, it will be sent as a <base64>
1895 element. If a <base64> element is found in the XML-RPC reply, it
1896 will be returned as an object with a stream drawn from that byte sequence.
1898 Each object returned by <tt>ibex.net.rpc.xml()</tt> represents a
1899 single HTTP connection. The connection will be held open until
1900 the object is garbage collected or the server closes the
1901 connection. If a second call is issued on the object before the
1902 first one returns (usually from a seperate thread), the two calls
1904 url="http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.1.2.2"
1905 text="pipelined"/>. This can dramatically improve performance.
1907 Ibex supports HTTP Basic and Digest authentication. To use
1908 authentication, pass <tt>ibex.net.rpc.xml()</tt> a URL in the form
1909 <tt>http[s]://user:password@hostname/</tt>. Ibex will use Digest
1910 authentication if the server supports it; otherwise it will use
1911 Basic authentication. Please be aware that many XML-RPC server
1912 implementations contain a <link
1913 url="http://www.ibex.org/faq.html#auth" text="broken implementation
1914 of Basic authentication"/>.
1918 <section title="SOAP">
1920 SOAP methods are invoked the same way as XML-RPC methods, but with three differences:
1922 <list type="ordered">
1924 <tt>ibex.net.rpc.soap()</tt> is used instead of
1925 <tt>ibex.net.rpc.xml()</tt>
1927 Instead of specifying just the URL of the service itself, you
1928 must specify the URL, the SOAPAction argument, and the
1931 The actual method invocation takes only one argument, which
1932 must be an object. This is necessary since SOAP arguments are
1933 specified by name, rather than ordering.
1937 SOAP faults are handled the same way as XML-RPC faults except that the
1938 capitalization of the <tt>faultstring</tt> and <tt>faultcode</tt>
1939 members is all lower-case, to match the SOAP spec. Here is a
1943 Press1 ++= function(v) {
1944 ibex.thread = function() {
1945 color = ibex.net.rpc.soap("http://soap.ibex.org/SOAP", // endpoint
1946 "GETTODAYSCOLOR", // SOAPAction header
1947 "http://ibex.org/namespace" // namespace for SOAP-ENV
1948 ).color.getTodaysColor( {
1955 As you can see, SOAP is much more verbose, yet does not offer
1956 substantially improved functionality. We recommend that XML-RPC be
1957 used whenever possible, and that SOAP be reserved for legacy
1960 The current Ibex SOAP stack does not support 'document style' or
1961 multi-ref (<tt>href</tt>) data structures.
1965 <section title="Security">
1967 Applications downloaded from the network (as opposed to those loaded
1968 from the filesystem) may only make certain kinds of connections to
1969 certain hosts. See Appendix A for a detailed description of the
1975 <!-- ----------------------------------------------------------------------- -->
1976 <section title="Error Handling">
1978 If the Ibex Core encounters an error while servicing a function call
1979 originating in JavaScript, the core will throw a string consisting of
1980 an error code followed by a colon, a space, and a descriptive message.
1984 "ibex.net.dns.unknownhostexception: unable to resolve host foo.com"
1987 The code should be used to determine how the program should respond to
1988 an error. The codes are organized in a hierarchy, so the
1989 string.startsWith() method can be used to determine if an error lies
1990 within a particular subhierarchy. The descriptive message portion of
1991 the string may be shown to the user.
1993 <property name="ibex.assertion.failed">
1996 <property name="ibex.io">
1997 General I/O exceptions
1999 <property name="ibex.io.encoding">
2000 Error translating between character encodings.
2002 <property name="ibex.io.zip">
2003 Attempted to access a corrupt zip archive.
2005 <property name="ibex.io.eof">
2006 End of file encountered unexpectedly
2008 <property name="ibex.net.security.prohibitedHost">
2009 A piece of untrusted Ibex code attempted to contact a
2010 restricted host. See Appendix A for details.
2012 <property name="ibex.net.dns.temporaryFailure">
2013 An attempt to resolve a hostname failed but it is not known
2014 for certain that the hostname is invalid.
2016 <property name="ibex.net.dns.unknownHost">
2017 An attempt to resolve a hostname failed because the hostname
2020 <property name="ibex.net.socket.closed">
2021 A socket was closed unexpectedly.
2023 <property name="ibex.net.socket.connectionFailed">
2024 A connection could not be made to the remote host.
2026 <property name="ibex.net.url.malformed">
2027 Tried to parse a malformed URL.
2029 <property name="ibex.net.ssl">
2030 General SSL protocol errors.
2032 <property name="ibex.net.ssl.untrustedCertificate">
2033 The server's certificate was not signed by a CA trusted by Ibex.
2035 <property name="ibex.net.http.">
2036 Thrown when an HTTP error code is returned during an
2037 operation. The three characters <tt><i>xyz</i></tt> will be
2038 the three-digit HTTP status code.
2040 <property name="ibex.net.xmlrpc.null">
2041 The caller attempted to transmit the <tt>null</tt> value via XML-RPC.
2043 <property name="ibex.net.xmlrpc.circular">
2044 The caller attempted to transmit a circular data structure via XML-RPC.
2046 <property name="ibex.net.xmlrpc.specialObject">
2047 The caller attempted to transmit a "special" object via
2048 XML-RPC (for example, a Box or the Ibex object).
2050 <property name="ibex.null.put">
2051 A JavaScript attempted to put to a property on the <tt>null</tt> value
2053 <property name="ibex.null.get">
2054 A JavaScript attempted to get from a property on the <tt>null</tt> value
2056 <property name="ibex.null.call">
2057 A JavaScript attempted to call the <tt>null</tt> value
2061 If an exception is thrown inside a trap, the exception will propagate
2062 to the script that triggered the trap.
2064 If an uncaught exception is thrown while applying a template, or the
2065 requested template could not be found, an error will be logged and the
2066 box to which the template was being applied will be made invisible
2067 (<tt>visible = false</tt>). This ensures that half-applied widgets are
2068 never shown to the user.
2072 <!-- ----------------------------------------------------------------------- -->
2073 <section title="A: Security Architecture and Considerations">
2075 Due to the expense and hassle imposed by the commercial PKI code
2076 signing architecture, and the fact that it <link
2077 url="http://www.counterpane.com/pki-risks-ft.txt" text="doesn't
2078 really provide any security anyways"/>, Ibex user interfaces are
2079 distributed as unsigned, untrusted code. As such, they are handled
2080 very carefully by the Ibex Core, and assumed to be potentially
2083 Ibex's security architecture is divided into defenses against four
2084 major classes of attacks:
2086 <section title="Malicious UI attempts to acquire or alter data on the client">
2088 Ibex user interfaces are run in an extremely restrictive sandbox. The
2089 environment does not provide primitives for accessing any data outside
2090 the Ibex core except via XML-RPC and SOAP calls. There are no
2091 facilities to allow Ibex user interfaces to access the client's
2092 operating system or to interact with other applications on the same
2093 host (unless they provide a public XML-RPC or SOAP interface).
2094 An Ibex script may only access a file on the user's hard disk if the
2095 user explicitly chooses that file from an "open file" or "save file"
2096 dialog. There is one exception to this rule: if all templates
2097 currently loaded in the Ibex core originated from the local
2098 filesystem, those templates can load additional .ibexs from the local
2101 The Ibex Core is written in Java, so it is not possible for
2102 scripts to perform buffer overflow attacks against the core
2105 Ibex applications may only read from the clipboard when the user
2106 middle-clicks (X11 paste), presses control-V (Windows paste), or
2107 presses alt-V (Macintosh paste; the command key is mapped to Ibex
2108 "alt"). This ensures that Ibex applications are only granted access to
2109 data that other applications have placed on the clipboard when the user
2110 specifically indicates that that information should be made available
2111 to the Ibex application.
2115 <section title="Malicious UI attempts to use client to circumvent firewalls">
2117 Ibex user interfaces may only make XML-RPC or SOAP calls and load .ibex
2118 archives via HTTP; they cannot execute arbitrary HTTP GET's or open
2119 regular TCP sockets.
2121 Ibex will not allow a script to connect to a non-public IP address
2122 (10.0.0.0/8, 172.16.0.0/12, or 192.168.0.0/16, as specified in <link
2123 url="http://www.cis.ohio-state.edu/cgi-bin/rfc/rfc1918.html" text="RFC
2124 1918"/>). There is one exception -- if all templates currently loaded
2125 in the core originated from the same IP address, those scripts may
2126 make calls to that IP address regardless of whether or not it is
2127 firewalled. If Ibex does not have access to a DNS resolver (because it
2128 is using a proxy which performs DNS lookups), Ibex will provide the
2129 proxy with the appropriate <link
2130 url="http://www.ibex.org/x-requestorigin.html"
2131 text=""/>X-RequestOrigin</tt></a> header that the proxy needs in order
2132 to maintain security.
2134 The only remaining possible attack is against a XML-RPC or SOAP
2135 service running on a firewalled host with a public address. Assigning
2136 such machines public IP addresses is a poor network security policy,
2137 and doing so squanders scarce public IPv4 addresses. As such, the onus
2138 is on the administrators of such machines to explicitly block access
2139 to clients reporting a <tt>User-Agent:</tt> header beginning with the
2140 three characters "<tt>Ibex</tt>".
2144 <section title="Malicious UI attempts to trick user into divulging secret information">
2146 All top-level windows created by Ibex are <i>scarred</i> -- a stripe
2147 and a lock is drawn across the corner of the window. There is no way
2148 for a user interface to remove this scar. Ibex user interfaces may not
2149 create windows smaller than the size of the scar.
2153 <section title="Malicious network attempts to snoop or man-in-the-middle transactions">
2155 Ibex user interfaces may transmit network data using HTTPS (SSL 3.0)
2156 for encryption. Ibex will attempt 128-bit encryption, but will
2157 negotiate down to 40-bit if the server does not support strong
2158 crypto. Ibex's SSL implementation is currently provided by <link
2159 url="http://www.ibex.org/tinyssl" text="TinySSL"/> and <link
2160 url="http://www.bouncycastle.org" text="The Legion of the Bouncy
2163 All HTTPS connections must be authenticated by the server using a
2164 certificate whose name matches the domain name of the HTTPS URL. The
2165 certificate must be signed by a trusted root CA. Ibex trusts the same
2166 93 root CAs whose certificates are included as "trusted" in Microsoft
2167 Internet Explorer 5.5 SP2. This provides a minimal level of protection
2168 against man-in-the-middle attacks; you should not trust this
2169 connection with any data you would not normally trust an SSL-enabled
2176 <!-- ----------------------------------------------------------------------- -->
2177 <section title="B: ECMAscript compliance">
2179 Ibex's scripts are written in a modified subset of ECMA-262, revision 3
2180 (aka JavaScript 1.5). The interpreter strays from the spec in a few
2183 <section title="Omissions">
2185 The following ECMA features are not supported:
2187 <list type="unordered">
2189 The <tt>undefined</tt> value, <tt>===</tt>, and <tt>!==</tt>
2191 The <tt>new</tt> keyword (and ECMAScript object inheritance)
2194 <tt>getter</tt> and <tt>setter</tt>
2196 The ECMA <tt>this</tt> keyword.
2198 The <tt>String</tt>, <tt>Number</tt>, and <tt>Boolean</tt>
2199 classes. Note that <tt>string</tt>, <tt>number</tt>, and
2200 <tt>boolean</tt> values are supported, however.
2202 You may not <tt>throw</tt> the <tt>null</tt> value.
2206 Additionally, you must declare all root-scope variables (with
2207 <tt>var</tt>) before using them; failure to do so will result in an
2208 exception. Box properties are pre-defined in the scope that scripts
2213 <section title="Extensions">
2215 <list type="unordered">
2217 The token <tt>..</tt> is equivalent to <tt>[""]</tt>.
2223 Extended <tt>catch</tt> syntax. The following code:
2225 } catch(e propname "foo.bar.baz") {
2232 if (e.propname != null && e.propname >= "foo.bar.baz" && e.propname < "foo.bar.baz/") {
2237 Multiple extended-catch blocks can appear at the end of a single try
2238 block. However, at most one non-extended catch block may appear, and
2239 if it does appear, it must be the last one.
2241 Since Ibex ECMAscripts are wrapped in XML, the lexical token
2242 "<tt>lt</tt>" is be interpreted as <tt><</tt>, the lexical
2243 token "<tt>gt</tt>" is be interpreted as <tt>></tt>, and the
2244 token "<tt>and</tt>" is interpreted as <tt>&&</tt>.
2245 Thus these tokens cannot be used as variable names.
2247 The identifier <tt>static</tt> is a reserved word in
2248 ECMAScript, but not in Ibex.
2250 Ibex defines an additional reserved word, "<tt>assert</tt>",
2251 which will evaluate the expression which follows it, throwing
2252 a <tt>ibex.assertion.failed</tt> exception if the expression
2253 evaluates to <tt>false</tt>.
2255 To ensure that Ibex files appear the same in all text editors, tab
2256 characters are not allowed in Ibex files.
2260 Some useful tutorials include:
2262 <list type="unordered">
2265 url="http://developer.netscape.com/docs/manuals/communicator/jsref/index.htm"
2266 text=" JavaScript 1.2 Reference"/>. Although this document is
2267 out of date, it is arguably the best guide available for free
2268 on the Internet. The changes from JavaScript 1.2 (aka ECMA-262
2269 r1) to 1.5 were minimal, and many of them were <link
2270 url="ecmascriptcompliance" text="omitted"/> from Ibex.
2273 url="http://search.barnesandnoble.com/booksearch/isbnInquiry.asp?isbn=0596000480"
2274 text=" JavaScript: The Definitive Guide"/>, by David Flanagan
2275 and Paula Ferguson. The latest edition of this book covers
2276 JavaScript 1.5 (ECMA-262 r3).
2279 url="http://www.ecma.ch/ecma1/STAND/ECMA-262.HTM"
2280 text="ECMA-262"/> specification. This is an extremely
2289 <!-- ----------------------------------------------------------------------- -->
2290 <section title="C: Logging and Command Line Invocation">
2292 Very early in the loading process, Ibex begins logging messages about
2293 what it is doing. Where this output is logged to differs by platform;
2294 currently it goes to standard output when running inside a JVM, and to
2295 <tt>$TMPDIR\ibex-log.txt</tt> on Win32 (where <tt>$TMPDIR</tt> is the
2296 value returned by <tt>GetTempPath()</tt>). The logs contain a lot of
2297 valuable debugging information and performance hints; if you are
2298 having trouble developing an Ibex application, be sure to check the
2301 If Ibex encounters a serious problem before it starts logging
2302 information, or if it is unable to open the log file, it will abort
2303 immediately with a critical abort, which will be displayed on the
2304 console for POSIX-native cores and in a dialog box for JVM-based and
2307 You can invoke Ibex directly from the command line during
2308 development. When using a JVM, the invocation format is:
2311 java -jar <i>path-to-ibex-jar</i> [-sv] <i>source-location</i> [<i>initial-template</i>]
2314 Where <tt><i>path-to-ibex-jar</i></tt> is the path to <tt>ibex.jar</tt>,
2315 which can be downloaded <link url="http://www.ibex.org/dist/ibex.jar" text="here"/>.
2317 On Win32, the invocation format is:
2320 ibex.exe [-v] <i>source-location</i> [<i>initial-template</i>]
2323 The file <tt>ibex.exe</tt> is placed in Windows' ActiveX cache
2324 directory the first time Ibex is used on the machine. The ActiveX
2325 cache location depends on what version of Windows you are using;
2326 on newer versions of Windows it is <tt>C:\WINDOWS\DOWNLOADED
2327 PROGRAM FILES\</tt>. You can also extract <tt>ibex.exe</tt> from
2328 <tt>ibex.cab</tt>, which is available <link
2329 url="http://www.ibex.org/dist/ibex.cab" text="here"/>.
2331 The <tt><i>source-location</i></tt> parameter can be either the path
2332 to an .ibex archive, the http url of an .ibex archive, or the path to a
2333 directory comprising an unpacked .ibex archive.
2335 The <tt><i>initial-template</i></tt> parameter is the stream name of
2336 a template to be used as the initial template. If ommitted, it
2337 defaults to <tt>main</tt>.
2339 The <tt>-v</tt> option causes Ibex to enable verbose logging; this will
2340 cause it to log <i>lots</i> of information to the log file. This
2341 option will also substantially decrease Ibex's performance.
2345 <!-- ----------------------------------------------------------------------- -->
2347 <section title="E: Grammars">
2349 <font color=red><i>Grammar support is experimental in this release
2350 and may not work properly. It may change in incompatible ways or
2351 disappear completely from future releases</i></font>
2353 Grammars are defined with a statement in the following form:
2358 A grammar is really just another function; once defined you can't tell
2359 it apart from an ordinary function. A grammar takes one argument,
2360 which can be a string or stream. The argument is parsed and the
2361 result of executing the code block 'c' is returned.
2363 The property 'a' is read; if the value is a grammar, a new production
2364 rule (ie a new alternative, as with '<tt>|</tt>') is added to that grammar
2365 (this is a destructive update). This allows you to add productions to
2366 pre-existing grammars (for example, adding a new type of expression to
2367 a programming language by extending the 'expr' grammar). If the old
2368 value is not a grammar, the value is discarded and a new grammar
2371 The value 'b' is a pattern, which may consist of seven simple
2374 <list type="unordered">
2377 grouping parens <tt>()</tt>
2379 combinators: <tt> | + * ?</tt>
2381 references to other grammars
2384 The value 'c' and the braces surrounding it are an *optional* code
2385 block, in which the following identifiers are bound:
2387 <list type="unordered">
2389 The identifier 'whole' is bound to the string matched by the
2390 entire expression. If the code block is omitted it behaves
2391 as if it were <tt>"{ return whole; }"</tt>.
2393 For every reference to another grammar which was matched in the
2394 pattern, the *name used to reference that other grammar* will
2395 be bound to the value returned by its code block. Here's an
2396 example of this important distinction:
2399 var foo ::= 'a' | 'b';
2401 var baz ::= 'c' | bar { /* foo is not defined here, but bar is */ };
2404 On the last line, the identifier 'bar' serves two purposes: it
2405 pulls in the definition of the pattern *and* acts as a binder
2406 within the scope of the braces.
2408 If a reference is matched multiple times (either because it
2409 appears multiple times in the pattern or because the * or +
2410 operator was applied to it) then its name will be bound to an
2411 array containing the matches.
2415 Here is the metacircular definition of the grammar facility:
2418 grammar ::= identifier '::=' pattern (';' | '{' code '}' ';'?)
2419 identifier ::= ('a'..'z' | 'A'..'Z' | '_' | '$') (identifier | '0'..'9')*
2420 char ::= '\0x0000'..'\0xffff'
2421 literal ::= '\'' char+ '\''
2422 | '\'' char '\'' '..' '\'' char '\''
2423 pattern ::= identifier
2430 | pattern '|' pattern
2435 Copyright (C) 2004 Adam Megacz, verbatim redistribution permitted.
2436 Ibex is a trademark of Adam Megacz