1 <ibex-doc title="The Ibex Reference" subtitle="Nitrogen Release" author="Adam Megacz" email="adam@ibex.org">
3 <!-- ----------------------------------------------------------------------- -->
4 <section title="Introduction">
7 If you are reading the html version of this document and are
8 thinking of printing it out, you might be interested in the nicely
9 typeset <link url="reference.pdf" text="pdf version"/> produced
13 This document is a __reference__. It is not a
14 __specification__ or a
17 This document does not guide the user gently through examples (as a
18 tutorial would), and it doesn't provide enough detail and formality
19 for a third party to construct a compatible re-implementation of the
20 Ibex Core (as a specification would).
22 Rather, the goal of this document is to completely describe every
23 aspect of the environment that the Ibex Core provides to client
24 applications, from the bottom up. If you want to be an Ibex expert,
25 this is the right document to read. It is assumed that you are already
26 familiar with XML and with either JavaScript or ECMAscript.
28 If you need to use or rely on some behavior you notice in the Ibex
29 Core, but which is not clearly defined here, please post to <link
30 url="http://lists.ibex.org/listinfo/users" text="the users mailing list"/>.
32 <section title="Key Concepts">
34 <definition term="The Core">
35 Ibex itself; the native code (or Java bytecode) that runs on
36 the client. This term does not include the **Wildebeest**
37 or the **UI**</definition>
39 <definition term="The UI / The Application">
40 A set of files (mostly XML, JavaScript, and PNG images)
41 bundled up in a zip archive, ending with the "[[.ibex]]"
42 extension. Together, these files specify the appearance and
43 behavior of the application's user interface.
46 <definition term="The Server">
47 We will use the term "the server" to refer to any other
48 computer which the client makes XML-RPC or SOAP calls
49 to. Note that it is possible for the client and server to be
50 the same machine.</definition>
52 <definition term="Wildebeest">
53 This is a very small piece of code that is downloaded the
54 first time a client uses Ibex. It downloads the Ibex core,
55 verifies its signature, and launches it with the appropriate
56 parameters indicating where to find the initial UI.
57 Wildebeest works differently on every platform, and is outside
58 the scope of this document.</definition>
60 <definition term="put/write">
61 In ECMAscript, when you change the value of a property on an
62 object, you are **putting** to that property, or
63 **writing** to it. For example, the ECMAscript expression
64 "[[foo.bar = 5]]" **puts** the value 5 to the bar
65 property on object foo.</definition>
67 <definition term="get/read">
68 In ECMAscript, when you access the value of a property on an
69 object, you are **getting** that property, or
70 **reading** from it. For example, the ECMAscript
71 expression "[[return (3 + foo.bar)]]" **gets** the
72 value of bar property on object foo and then adds 3 to it
73 before returning the result.</definition>
75 <definition term="JavaScript">
76 We will use the terms JavaScript and ECMAScript
77 interchangeably in this document. The Ibex interpreter is not
78 completely ECMA-compliant, however (see <link
79 appendix="ECMAscript compliance"/> for details).
84 <section title="Life Cycle of an Ibex Application">
86 <image url="lifecycle.pdf" caption="The Lifecycle of an Ibex Application"/>
88 A user typically begins an Ibex session by clicking on a link to
89 an Ibex application. This link serves the {\tt launch.html} file
90 to the user's browser, which in turn downloads the appropriate
91 {\it Wildebeest} -- currently either an ActiveX Control
92 (Win32/MSIE), XPInstaller (Mozilla), or Signed Applet (all
95 The Wildebeest downloads the appropriate core for the user's
96 machine and verifies its digital signature. It then launches the
97 core, which downloads the UI (an [[.ibex]] archive), loads it,
98 applies the [[main.t]] template (found in the archive), and
99 renders it onto the screen, running any associated JavaScript
102 The user interacts with the application by clicking and moving the
103 mouse, and by pressing keys on the keyboard. These actions trigger
104 fragments of JavaScript code which are designated to handle events.
105 This JavaScript code can then relay important information back to the
106 server using XML-RPC or SOAP, or it can modify the structure and
107 properties of the user interface to change its appearance, thereby
108 giving feedback to the user.
110 The Ibex core quits when the last remaining surface has been destroyed.
115 <section title="Surfaces">
117 <image url="offscreen.pdf" width="2in"
118 caption="An Ibex surface positioned at (83,0)"/>
119 Each top-level window in an Ibex UI is called a
120 **surface**. There are two kinds of surfaces: **frames**,
121 which usually have a platform-specific titlebar and border, and
122 **windows**, which never have any additional platform-specific
125 Whenever we refer to the size or position
126 of a surface, we are referring to the size or position of the
127 UI-accessible portion of the surface; this does not include any
128 platform-specific decorations. This means that if you set the
129 position of a frame to (0,0), the platform-specific titlebar will
130 actually be off the screen on most platforms (it will be above and
131 to the left of the top-left corner of the screen).
133 Surfaces are not actual JavaScript objects; you cannot obtain a
134 reference to a surface. However, each surface is uniquely identified
135 by its **root box**, described in the next section.
139 <section title="Boxes">
141 A **box** is the fundamental unit from which all Ibex user
142 interfaces are built. Boxes can contain other boxes (referred to as
143 its **children**). Each surface has a single box associated with
144 it called the **root box**; the root box and its children (and
145 its children's children, and so on) form the surface's **box
148 There are three ways to think of a box:
151 As a rendered visualization on the screen (the "**Visual Representation**")
153 As a JavaScript object (the "**Object Representation**")
155 As as an XML tag (the "XML Template Representation").
159 <image url="threeviews.pdf" caption="The three representations of an Ibex box"/>
161 All three representations are equally valid, and being able to
162 figure out what an action in one representation would mean in terms
163 of the other two representations is crucial to a solid understanding
169 <section title="The XML Template Representation">
171 A template (discussed in the next section) is an XML file which acts
172 as a blueprint for constructing a tree of boxes. We call this
173 construction process **applying**, since unlike
174 **instantiation** in object-oriented programming systems, you
175 always apply a template to a pre-existing box, and you can apply
176 multiple templates to the same box.
178 Each XML tag corresponds to a single box, or to another template
179 which will be applied to that box. For example, a [[scrollbar]]
180 template, when applied, will construct a tree of boxes which has the
181 visual appearance and behavior of a scrollbar.
183 Although it is useful to think of the XML tags as being boxes, keep
184 in mind that the XML representation is only a blueprint for
185 constructing a tree of JavaScript objects. Once the template has
186 been instantiated, the XML is effectively "thrown away", and
187 JavaScript code is free to alter the boxes. Once the process of
188 applying a template is complete, Ibex completely forgets the fact
189 that it has applied a particular template to a particular box. One
190 consequence of this approach is that if you think of templates as
191 classes, then Ibex has no equivalent for Java's [[instanceof]]
194 Each template is an XML document whose root element is
195 [[<ibex>]]. Here is a sample template file:
198 <ibex xmlns:lib="ibex.lib">
201 This is a cool widget.
204 // this code is executed only once
205 static = { instances : [] };
207 // this element applies the ibex.lib.focusable template
211 static.instances.push(thisbox);
212 <ui:box id="container"/>
221 The following two namespaces are predefined and need not be declared
224 <definition term="meta">
225 [[http://xmlns.ibex.org/meta]]
227 This will be referred to as the "[[meta]] namespace" in the
228 remainder of this document.
231 <definition term="ui">
232 [[http://xmlns.ibex.org/ui]]
234 This will be referred to as the "[[ui]] namespace" in the
235 remainder of this document.
238 Additionally, the default namespace for the document will be set to
239 the template's package FIXME.
241 <section title="Static Code">
243 If the root [[<ibex>]] element contains any non-whitespace
244 text content, this text is interpreted as JavaScript code and is
245 executed the first time the template is referenced. This code is
246 executed in a fresh scope containing two predefined properties:
248 <definition term="ibex">
249 The Ibex Object (described in <ref section="The Ibex Object"/>)
252 <definition term="static">
253 A reference to this template's **static object**, which is
254 initially [[null]]. The static object can be accessed (read
255 and written) from both static scripts as well as instance
256 scripts in a particular template. FIXME
260 <section title="Metadata">
262 Any immediate children of the root element which are in the
263 [[meta]] namespace are treated as metadata and are exempted from
264 the rest of the template application process. Currently only one
265 type of metadata element is defined:
268 [[<meta:doc>]]: structured documentation for the
274 <section title="Other Elements">
276 All remaining children of the root element are treated as elements
277 to be **applied** to the box, in the order in which they appear
278 in the file using the following procedure.
280 <remark text="While this process outlined below sounds very
281 complex, it actually works pretty intuitively. The
282 description below is given in great detail since
283 most applications will wind up being unintentionally
284 dependent on subtle features of this process.
285 However, most of the time you can just pretend that
286 the XML tags and the boxes are the same thing."/>
288 <heading title="Intuitive Description"/>
292 During a box initialization, script-private references to a
293 box's descendants with [[id]] attributes are placed on the
294 box. These references allow scripts on that box to easily refer
295 to descendant nodes created by the template in which the script
296 appears. For example, these two blocks of code have exactly the
301 <ui:box id="foo"/> <ui:box/>
302 $foo.color = "red"; var $foo = this[0];
307 <heading title="Precise Description"/>
309 To apply an XML tag [[__x__]] to a box [[__b__]], perform the following
310 operations, in this order:
312 <list type="ordered">
314 Allocate a fresh scope [[__s__]] whose parent scope is
317 Process each child element or text segment of [[__x__]]
318 in the order they appear in the document:
322 Treat each text segment [[__t__]] as JavaScript code
323 and execute it with [[__s__]] as the root scope.
325 For each child element [[__x'__]] of [[__x__]]:
328 Create a new box [[__b'__]].
330 If the name of tag [[__x'__]] is not
331 "[[box]]" in the [[ui]] namespace, prepend the
332 tag's namespace identifier uri (if any) to the name of
333 the tag, and use the result as a key to retrieve a
334 property from the root stream (defined later).
335 Interpret the resulting stream as a template and apply
336 that template to [[__b'__]].
338 (recursively) apply [[__x'__]] to [[__b'__]].
340 If [[__x'__]] has an [[id]] attribute, declare a variable
341 in [[__s__]] whose name is the value of the [[id]]
342 attribute, prefixed with the [[$]] character, and whose
345 Copy any [[$]]-variables created during the application
346 of [[__x'__]] into scope [[__s__]].
348 Append [[__b'__]] as the last child of [[__b__]].
352 Apply any attributes on [[__x__]] to [[__b__]], except for
353 [[id]]. Since XML specifies that the order of attributes
354 cannot be significant, Ibex processes attributes in
355 alphabetical order by attribute name. For example, if
356 [[__x__]] has the attribute [[foo="bar"]], then the
357 equivalent of the statement [[B.foo="bar";]] will be
358 performed, with the following exceptions:
361 If the value portion of the attribute is the string
362 "[[true]]", put the boolean [[true]]. If the
363 value is "[[false]]", put the boolean [[false]].
365 If the value is a valid ECMAscript number, put it as a
366 number (instead of a string).
368 If the value begins with a dollar sign ([[$]]),
369 retrieve the value of the corresponding variable in
370 [[__s__]] and use that value instead.
372 If the value begins with a dot ([[.]]), prepend the
373 attributes' namespace identifier uri (if any) and
374 interpret the remainder as a property to be retrieved from
375 the root stream (defined later).
379 <heading title="Initialization Invariants"/>
381 The last two steps are referred to as the **initialization** of the
382 node. There are two important aspects of this ordering to be aware of:
384 <list type="unordered">
386 A given box will be fully initialized before its parent is
387 given a reference to that box. This way, parents can be
388 certain that they will never wind up accessing a box when it
389 is in a partially-initialized state.
391 Attributes are applied **after** scripts are run so that
392 the attributes will trigger any **traps** (defined later)
393 placed by the script.
401 <!-- ----------------------------------------------------------------------- -->
402 <section title="Layout and Rendering">
404 Each box occupies a rectangular region on the surface. The visual
405 appearance of a surface is created by rendering each box in its tree.
406 Unless the [[clip]] attribute is [[false]], each box will
407 clip its childrens' visual representations to its own, so that the
408 children appear "confined to" the parent. Children are rendered after
409 their parents so they appear "on top of" their parents.
411 Each box has two major visual components, each with subcomponents:
415 <definition term="path">
417 A box's [[path]] consists of zero or more lines and curves.
418 The path may be filled with a color, gradient, or texture, and
419 may be stroked with a line of a given thickness and color. If
420 the path is not specified, it defaults to the perimiter of the
421 box. [**Note: Vector Graphics support (including the ability
422 to set the [[path]] property to anything other than the
423 default) is currently not implemented**].
428 an associated [[strokecolor]], which is a color
430 an associated [[strokewidth]], which is a number
431 specifying the width of the stroke. [**Note: Vector
432 Graphics support (including the [[strokewidth]]
433 property) is currently not implemented**]
435 a [[fill]], which is either a color, gradient, or
440 <definition term="text">
442 Each box also has a single line of [[text]], whose
443 appearance is determined by its:
446 associated [[font]], which can be any font supported by
447 the <link url="http://www.freetype.org" text="FreeType2"/>
450 an associated [[fontsize]] in **pixels**
452 an associated [[textcolor]]
456 These eight components plus the size of a box fully specify its
457 appearance. Every single box you see in Ibex is drawn only on the
458 basis of these components and its size.
460 The size and position of every box is determined by its
461 properties, its childrens' sizes, and its parent's size and
462 position. Box layout and rendering happens in four phases:
463 **packing**, **constraining**, **placing**, and
464 **rendering**. The Core is careful to only perform a phase on
465 a box if the box has changed in a way that invalidates the work
466 done the last time that phase was performed. The packing and
467 constraining phases are performed in a single traversal of the
468 tree (packing is preorder, constraining is postorder), and the
469 placing and rendering phases are performed in a second traversal
470 of the tree (first placing, then rendering, both preorder).
472 For brevity, the rest of this chapter deals only with width and
473 columns. Height and rows is treated identically and independently.
474 Also, it is important to note that the term **minimum width** is
475 not the same thing as the property [[minwidth]], although they
478 <heading title="The Size of the Root Box"/>
480 When the user resizes a window, Ibex changes the root box's
481 [[maxwidth]] and [[maxheight]] to match the size chosen by
482 the user and then determines the root box's size using the same sizing
483 rules it uses for other boxes.
485 Ibex will always attempt to prevent the
486 user from making the surface smaller than the root box's
487 [[minwidth]] and [[minheight]]. If the [[hshrink]] or
488 [[vshrink]] flag is set, Ibex will try to prevent the user from
489 resizing the surface at all. However, not all platforms give Ibex
490 enough control to do this.
492 <heading title="The alignment point"/>
494 When talking about positioning, we will often refer to the
497 If the [[align]] property is "[[center]]", then the
498 alignment point is the center of the box.
500 If the [[align]] property is "[[topleft]]",
501 "[[bottomleft]]", "[[topright]]", or
502 "[[bottomright]]", then the alignment point is
503 corresponding corner of the box.
505 If the [[align]] property is "[[top]]",
506 "[[bottom]]", "[[right]]", or "[[left]]", then
507 the alignment point is middle of the corresponding edge of the
510 <section title="Packing">
512 A grid of **cells** is created within the parent. If the
513 parent's [[cols]] property is set to 0, the cell grid has an
514 infinite number of columns. Either [[cols]] or [[rows]]
515 must be zero, but not both.
517 If a child's [[visible]] property is [[false]], it does
518 not occupy any cells (and is not rendered). Otherwise, each child
519 occupies a rectangular set of cells [[child.colspan]] cells
520 wide and [[child.rowspan]] cells high.
522 The Core iterates over the cells in the grid in the following
523 order: if [[rows]] is 0, the Core iterates across each column
524 before proceeding to the next row; otherwise rows come before
525 columns. At each cell, the Core attempts to place the **first
526 remaining unplaced child's** top-left corner in that cell
527 (with the child occupying some set of cells extending down and
528 to the right of that cell). If the parent has a fixed number of
529 columns and the child's [[colspan]] exceeds that limit, the
530 child is placed in column zero regardless, but only occupies the
531 available set of cells (it does not "hang off the end" of the
532 box). <image url="layout.pdf" width="1in"/>
537 <ui:box id="2" rowspan="2" />
538 <ui:box id="3" colspan="2" />
540 <ui:box id="5" colspan="2" />
546 <section title="Constraining">
548 Each box's minimum width is computed recursively as the
554 The width of the box's [[text]] (after applying the
555 box's [[transform]]) [**Note: Vector Graphics support
556 (including the [[transform]] property) is currently not
559 The width of the box's path (after applying the box's
560 [[transform]]) **if the box is [[packed]]**.
562 The minimum width of the children in each row.
565 If a box's [[hshrink]] property is set to
566 [[true]], the box's maximum width is the same as its
567 minimum width; otherwise it is the box's
572 <section title="Placing">
574 <heading title="Non-Packed Boxes"/>
576 Each non-packed box is transformed according to the parent's
577 [[transform]] property and then positioned so that its alignment
578 point is [[(child.x, child.y)]] pixels from the corresponding
579 edge/corner/center of its parent.
581 <heading title="Packed Boxes"/>
583 Ibex formulates a set of constraints for placing a box's
584 **packed** children as follows:
587 - A box's width can be no greater than the sum of the
589 - The sum of a set of colums cannot be smaller than the
590 minimum width of a box that spans them.
591 - The sum of the widths of the parents' columns will be at
592 least as large as the parent's width is (but possibly
596 Subject to these two unbreakable constraints, Ibex searches for
597 a solution which will optimize the following three goals,
598 prioritized from most important to least important:
601 - (__Most Important__) The sum of all columns will be a close
602 to the parent's with as possible (ie as small as possible)
603 - Ibex will attempt to make a set of columns no wider than
604 the [[maxwidth]] of a box spanning them.
605 - (__Least Important__) Ibex will attempt to make all
606 columns the same width.
609 Each packed box is then placed within the set of cells that it
610 spans. Usually the box will exactly fill this rectangle; if it
611 does not (due to [[maxwidth]] or minimum width constraints), the
612 box's will be placed so that its alignment point coincides with
613 the alignment point of that rectangle of cells.
617 <section title="Rendering">
619 Boxes are rendered in a depth-first, pre-order traversal. Note that
620 this may cause a non-packed box to overlap its siblings.
622 <list type="ordered">
624 If the box's [[transform]] property is non-null, the
625 coordinate space is transformed accordingly for the rest of
626 this phase and for the rendering of all children. [**Note:
627 Vector Graphics support (including the [[transform]]
628 property) is currently not implemented**].
630 If the box is packed and has a non-[[null]] path, the
631 path is translated such that the alignment point of the path's
632 bounding box coincides with the box's alignment point (both
633 alignment points are determined by the box's [[align]]
636 If a box has a path, that path is filled with the color,
637 gradient, or image specified by the [[fill]] property and
638 stroked with the color and width specified by the
639 [[strokecolor]] and [[strokewidth]] properties.
641 If the box has a non-null [[text]] attribute,
642 the text is rendered in [[font]] with size
643 [[fontsize]] and color [[textcolor]]. The text is
644 then translated such that the alignment point of the text's
645 bounding box coincides with the box's alignment point (both
646 alignment points are determined by the box's [[align]]
649 The box's children are rendered (pre-order traversal).
656 <!-- ----------------------------------------------------------------------- -->
657 <section title="Box Properties">
659 Each box is a full-fledged ECMAscript object, and can store
660 key-value pairs as properties. Some of these keys have special
661 meaning, which will be explained later. Each box's numeric
662 properties hold its **child boxes**.
664 <section title="Rendering Properties">
666 Every box has several special properties which control how it is
667 drawn. In general, if you put an
668 invalid value to a special property, no action will be taken -- the
671 <property name="strokecolor" type="string" default="clear">
673 If the value is a 5-character hex string ([[#RGB]]),
674 7-character hex string ([[#RRGGBB]]), 9-character hex
675 string ([[#AARRGGBB]]), the box's stroke color will be set
678 If the value is one of the <link
679 url="http://www.color.org/ICC-1A_1999-04.PDF"
680 text="ICC"/> colors (the same set of color names
681 supported by SVG), the stroke color be set to that color.
683 If the value is [[null]], the stroke color will be set
684 to clear ([[#00000000]]).
687 <property name="strokewidth" type="int" default="1">
688 The width (in pixels) to stroke the path with.
691 <property name="fill">
692 This property can be set to any of the values specified for
694 Alternatively, if the value written is an object, its stream
695 will be read and interpreted as a PNG, GIF, or JPEG image,
696 which will become the texture for this box, and the box's
697 [[minwidth]] and [[minheight]] properties will be
698 automatically set to the dimensions of the image.
701 <property name="path" type="string" default='""'>
702 The box's path. The grammar and feature set supported are
703 identical to that specified in <link
704 url="http://www.w3.org/TR/SVG11/paths.html" text="SVG 1.1,
708 <property name="text" type="string" default='""'>
709 The box's text; writing [[null]] to this property sets it
713 <property name="textcolor" type="number" default="black">
714 The color in which to render the font; accepts the same values as [[strokecolor]].
717 <property name="font" type="stream" default=".ibex.ui.font.sansserif">
718 When an object is written to this property, its stream is read
719 using the <link url="http://www.freetype.org" text="FreeType 2 library"/>,
720 and the resulting font is used to render the
724 <property name="fontsize" type="number" default="10">
725 The size (in points) to render the text.
730 <section title="Layout Properties">
732 <property name="shrink" type="boolean" default="false">
733 If set to [[true]], this box will shrink
734 (horizontally/vertically/both) to the smallest size allowed by
735 its children and the bounding box of its path.
738 <property name="x y" type="integer" default="varies">
739 If the box is a root box, this is the (x/y)-coordinate of the
740 surface; otherwise it is the distance between the parent's
741 alignment point and the corresponding corner/edge/center of
745 <property name="minwidth minheight" type="integer" default="0">
746 The desired minimum width and height.
749 <property name="maxwidth maxheight" type="integer" default="ibex.ui.maxdim">
750 The desired maximum width and height.
753 <property name="width height" type="integer">
754 When read, this is the current (width/height) of this box.
755 Writing to this property is equivalent to writing to
756 **both** the minimum and maximum (width/height).
759 <property name="cols rows" type="integer" default="0">
760 The number of (columns/rows) in which to lay out the children of this
761 box. If set to zero, the number of (columns/rows) is unconstrained.
762 Either [[rows]] or [[cols]] must be zero. If
763 [[0]] is written to [[cols]] when [[rows]] is
764 [[0]], the write is ignored. If a nonzero value is
765 written to [[cols]] when [[rows]] is nonzero,
766 [[rows]] is set to [[0]], and vice versa.
769 <property name="colspan rowspan" type="integer" default="1">
770 The number of (columns/rows) that this box spans within its parent.
773 <property name="align" type="string" default="center">
774 Determines the box's alignment point for positioning its text,
775 texture, path, and children.
778 <property name="visible" type="boolean" default="true">
779 If set to [[false]], this box will be rendered as if its
780 width and height were zero. If this is a root box, the
781 associated surface will be hidden.
783 When reading from this property, the value [[false]] will
784 be returned if this box **or any of its ancestors** is not
785 visible. Thus it is possible to write [[true]] to a box's
786 [[visible]] property and then read back [[false]].
789 <property name="packed" type="boolean" default="true">
790 The layout strategy for this box. If set to [[true]], the
791 box occupies no cells and is laid out independently of its
797 <section title="Child Control Properties">
799 <property name="redirect" type="box" default="thisbox">
800 Writing to this property sets the box's redirect target. This
801 property cannot be read from, and can only be written to if
802 the value being written is a **descendant** of the current
805 If a box has a non-null redirect target, reads and writes to
806 any of the other properties in this section will be forwarded
807 to the redirect target.
809 The [[redirect]] attribute is very useful for hiding the
810 internal structure of a widget, and for allowing widgets to act as
811 "smart" containers for other widgets. For example, a menu widget might
812 have an invisible child as its redirect target; this way, when boxes
813 representing items on the menu are added as children of the menu
814 widget, they do not appear until the menu is pulled down.
817 <property name="numeric properties" type="int" default="">
818 The **n**th child of box [[b]] can be accessed by reading from
819 [[b[n]]]. The **n**th child can be removed by writing
820 [[null]] to [[b[n]]] (the child will become parentless). A
821 new child can be inserted **before** the **n**th child by
822 writing it to [[b[n]]]; if the value written is already a child of
823 [[b]], it will be removed from [[b]] first. It is important
824 to note that this behavior is different from ECMAscript arrays --
825 writing a non-[[null]] value to [[b[n]]] does not eliminate
826 the **n**th child; it merely shifts it over one position.
827 __Note:__ Unlike most JavaScript objects, enumerating a Box's
828 properties with the JavaScript [[for..in]] construct will
829 enumerate **only** the box's children and not any other properties.
832 <property name="clip" type="boolean" default="true">
833 If [[true]], the visual representation of this box's
834 children will be clipped to the boundaries of this box.
835 __Note:__ setting this property to [[false]] imposes a
836 substantial performance penalty.
839 <property name="numchildren" type="integer" default="0">
840 The number of children this box has.
844 <property name="surface" type="" default="null">
846 If this box has a parent, this property returns
847 [[**parent**.surface]]; otherwise it returns null.
848 This property is a simple building block that the widget
849 library uses to implement more complex functionality such as
850 focus control and popups.
855 <section title="Other Box Properties">
857 <property name="cursor" type="string" default="null">
858 The shape that the cursor should take when inside this
859 box. Valid values are: "[[default]]" , "[[wait]]",
860 "[[crosshair]]", "[[text]]", "[[hand]]", and
861 "[[move]]", as well as resizing cursors"[[east]]",
862 "[[west]]", "[[north]]", "[[south]]",
863 "[[northwest]]", "[[northeast]]",
864 "[[southwest]]", and "[[southeast]]". Note that on
865 some platforms, resize cursors for opposite directions (such
866 as [[northwest]] and [[southeast]] are the
868 If a box's cursor is [[null]], its parent's cursor will
869 be used. If the root box's cursor is null, the
870 "[[default]]" cursor will be used.
873 <property name="static" type="object" default="N/A">
874 Reading from this property will return the parent scope used
875 to execute the [[<static/>]] block of the template
876 in which the currently-executing code resides.
879 <property name="thisbox" type="box" default=" ">
880 Returns a reference to the box itself.
881 If [[null]] is written to this property, and this box is
882 the root box of a surface, the box will be detached and the
883 surface destroyed. If this box has a parent, it will be
884 detached from its parent.
887 <property name="indexof()" type="function" default=" ">
888 This property is actually a function; invoking
889 [[parent.indexof(child)]] will return the numerical index
890 of [[child]] in [[parent]] if [[child]] is a
891 child of [[parent]] (or [[parent]]'s redirect
892 target), and [[-1]] otherwise. Writing to this property
896 <property name="distanceto()" type="function" default=" ">
897 This property is actually a function; invoking
898 [[box.distanceto(otherbox)]] will return an object with two
899 properties, [[x]] and [[y]], containing the horizontal
900 and vertical distance between the two boxes (negative if
901 [[otherbox]] is to the left of / above [[box]]). This
902 can be used to determine the relative placement of two boxes
903 on different branches of the box tree.
908 <section title="Root Box Properties">
910 The following special properties are only meaningful on the root box
913 <property name="Focused">
914 The value [[true]] is put to this property on the root box
915 when the surface gains the input focus, and [[false]] when
916 the surface loses the input focus. Reading from this value will
917 return [[true]] if the surface is focused and [[false]]
918 if it is not. Putting [[true]] to this property will
919 **not** cause the surface to "steal" the input focus from other
923 <property name="Maximized">
924 The value [[true]] is put to this property on the root box
925 when the surface is maximized, and [[false]] when the surface
926 is un-maximized. Reading from this value will return [[true]]
927 if the surface is maximized and [[false]] if it is
928 not. Putting [[true]] to this property will maximize the
929 window, and putting [[false]] to this property will
930 unmaximize the window.
931 Note that not all platforms support maximization.
934 <property name="Minimized">
935 The value [[true]] is put to this property on the root box
936 when the surface is minimized, and [[false]] when the surface
937 is unminimized. Reading from this value will return [[true]]
938 if the surface is minimized and [[false]] if it is
939 not. Putting [[true]] to this property will minimize the
940 window, and putting [[false]] will unminimize it.
943 <property name="Close">
944 When the user attempts to close a surface, the value
945 [[true]] will be put to this property. Scripts may trap
946 this property to prevent the window from closing. Putting the
948 [[true]] to this property on a root box has the same
949 effect as putting [[null]] to the [[thisbox]]
953 <property name="icon">
954 The surface's icon. This is usually displayed on the titlebar of a
955 window. The value should be an object whose stream is a PNG image. Note
956 that not all platforms support this property.
959 <property name="titlebar">
960 The surface's titlebar text. Note that not all platforms support
961 this property. Only ASCII characters 0x20-0x7F are permitted.
968 <!-- ----------------------------------------------------------------------- -->
969 <section title="Streams">
971 <heading title="Every object has a stream..."/>
973 Every object has a **stream** associated with it. A stream is a
974 sequence of bytes that can be read or written to.
976 By default an object has an empty stream (zero bytes). However, some objects
977 (returned from special methods on the [[ibex]] object) have
978 streams yielding data read from an url, file, or a component of a zip
979 archive. In a future release, the stream associated with a box will
980 be an .ibex template which, when applied, will fully reconstitute the
983 <heading title="...but streams are not objects"/>
985 Despite the ubiquity of streams, you cannot actually reference a
986 stream, since it is not an object. Instead, you simply reference the
987 object it belongs to. If you are familiar with Java, this is similar
988 to how every Java object has a monitor associated with it, but you
989 cannot directly manipulate the monitor (you can't pass around a
990 reference to just the monitor).
992 In the rest of the section we will sometimes refer to "getting
993 properties from a stream" or "passing a stream to a function"; this is
994 just shorthand for saying to perform those actions on the object the
997 <section title="Creating Streams from URLs">
999 You can create a stream from a URL by calling
1002 var r = ibex.stream.url("http://...");
1005 This will return an object whose stream draws data from the specified
1006 URL. Streams are loaded lazily whenever possible.
1010 <section title="Getting Substreams">
1012 Most stream objects let you access
1013 substreams using the usual JavaScript operators [[[]]] and
1014 [[.]], as well as the [[for..in]] syntax.
1017 // r1 and r2 are equivalent but not equal (!=)
1018 var r1 = ibex.stream.url("http://www.ibex.org/foo/bar.html");
1019 var r2 = ibex.stream.url("http://www.ibex.org/foo")["bar.html"];
1024 <section title="The Root Stream">
1026 The empty-string property on the [[ibex]] object is called the
1027 **root stream**. You can access this object as [[ibex..]] or
1028 [[ibex[""]]]. Additionally, any expression which starts with a
1029 dot is treated as property to be retrieved from the root stream. The
1030 following three expressions are equivalent:
1040 <section title="Static Blocks">
1044 You can access variables within the static block of a template by
1045 appending a double period ([[..]]) and the variable name to the
1046 stream used to load that template:
1049 <!-- org/ibex/themes/linux/scrollbar.ibex -->
1053 ibex.log.print(org.ibex.themes.linux.scrollbar..foo); // prints "12"
1058 <section title="Formatting Streams">
1060 If you attempt to send a stream as part of an XML-RPC call, the
1061 stream will be read in its entirity, Base64-encoded, and transmitted
1062 as a [[<base64/>]] element.
1064 Ibex supports two special URL protocols. The first is [[data:]],
1065 which inteprets the rest of the URL as a Base64 encoded sequence of
1066 bytes to use as a source. The other is [[utf8:]] which
1067 interpretets the rest of the string as a Unicode character sequence to
1068 be UTF-8 encoded as a string of bytes to use as a source.
1071 var r5 = ibex.stream.url("data:WFWE876WEh99sd76f");
1072 var r6 = ibex.stream.url("utf8:this is a test");
1075 You can read a UTF-8 encoded string from a stream like this:
1078 var myString = ibex.stream.fromUTF(ibex.stream.url("utf8:testing..."));
1080 You can also parse XML from a stream using SAX like this:
1083 ibex.stream.xml.sax(
1084 ibex.stream.url("http://foo.com/foo.xml"),
1085 { beginElement : function(tagname, attributeKeyValuePairs) { ... },
1086 endElement : function(tagname) { ... },
1087 content : function(contentString) { ... }
1088 whitespace : function(whitespaceString) { ... }
1096 <!-- ----------------------------------------------------------------------- -->
1097 <section title="The Ibex object">
1099 The [[ibex]] object is present in the top-level scope of every
1100 script. It has the following properties:
1102 <heading title="General"/>
1104 <property name="ibex.box">
1105 reading from this property returns a new box
1107 <property name="ibex.clone(o)">
1108 creates a clone of object
1110 <property name="ibex.bless(s)">
1111 returns a blessed clone of stream
1114 <heading title="ECMA Library Objects"/>
1116 <property name="ibex.date">
1117 reading from this property returns a new date
1119 <property name="ibex.math">
1120 this object contains the ECMA math functions
1122 <property name="ibex.regexp(s)">
1123 return a regexp object corresponding to string **s**
1125 <property name="ibex.string">
1126 this object contains the ECMA string manipulation functions
1129 <heading title="Logging"/>
1131 <property name="ibex.log.debug(m1, ... mn)">
1132 log the debug messages **m1** through **mn**.
1136 <property name="ibex.log.info(m1, ... mn)">
1137 log the info messages **m1** through **mn**.
1140 <property name="ibex.log.warn(m1, ... mn)">
1141 log the warning messages **m1** through **mn**.
1144 <property name="ibex.log.error(m1, ... mn)">
1145 log the error messages **m1** through **mn**.
1148 <heading title="User Interface"/>
1150 <property name="ibex.ui.browser(u)">
1151 opens a new browser window with URL **u**
1154 <property name="ibex.ui.key.control">
1155 true if the control key is depressed
1158 <property name="ibex.ui.key.shift">
1159 true if the shift key is depressed
1162 <property name="ibex.ui.key.alt">
1163 true if the alt key is depressed
1166 <property name="ibex.ui.key.name.alt">
1167 the name of the "alt" key (usually either "alt", "meta", or
1171 <property name="ibex.ui.clipboard">
1172 the contents of the clipboard; can be read and written to
1175 <property name="ibex.ui.maxdim">
1176 the maximum dimension of any UI element; usually
1177 2<sup>31</sup>, but may be smaller
1180 <property name="ibex.ui.screen.width">
1181 the width of the screen, in pixels
1184 <property name="ibex.ui.screen.height">
1185 the height of the screen, in pixels
1188 <property name="ibex.ui.mouse.button">
1189 either 0, 1, 2, or 3, indicating the mouse button currently
1193 <property name="ibex.ui.frame">
1194 when a box is written to this property, it becomes the root
1198 <property name="ibex.ui.window">
1199 when a box is written to this property, it becomes the root
1203 <property name="ibex.ui.font.serif">
1204 an object whose stream is a a builtin serif font
1207 <property name="ibex.ui.font.sansserif">
1208 an object whose stream is a builtin sans-serif font
1211 <property name="ibex.ui.font.monospace">
1212 an object whose stream is a a builtin fixed-width font
1215 <heading title="Networking"/>
1217 <property name="ibex.net.rpc.xml(u)">
1218 return an XML-RPC call object with endpoint URL **u**
1221 <property name="ibex.net.rpc.soap(u,">
1222 return a SOAP call object with endpoint URL **u**,
1223 SoapAction **a**, and XML Namespace **n**
1226 <heading title="Threads"/>
1228 <property name="ibex.thread">
1229 when a function is written to this property, a new thread is
1233 <property name="ibex.thread.yield()">
1234 yield the current thread
1237 <property name="ibex.thread.sleep(n)">
1238 sleep for **n** milliseconds
1241 <heading title="Streams"/>
1243 <property name="ibex.stream.url(u)">
1244 returns a new object whose stream is drawn from URL **u**
1247 <property name="ibex.stream.unzip(s)">
1248 unpacks a zip archive from **s**'s stream
1251 <property name="ibex.stream.uncab(s)">
1252 unpacks a cab archive from **s**'s stream
1255 <property name="ibex.stream.cache(s,k)">
1256 valign=top>wraps a disk-backed read cache keyed on **k**
1257 around **s**'s stream
1260 <property name="ibex.stream.watch(s,f)">
1261 returns an object whose stream is drawn from **s**'s
1262 stream, but invokes **f(n,d)** as it is read from.
1265 <property name="ibex.stream.parse.xml(s, h)">
1266 Use SAX to parse the XML document on stream **s** with
1270 <property name="ibex.stream.parse.html(s, h)">
1271 Same as [[parse.xml()]], but tries to fix broken HTML.
1274 <property name="ibex.stream.parse.utf8(s)">
1275 treat **s**'s stream as a string encoded as a UTF-8 byte stream and return the string
1278 <property name="ibex.stream.homedir">
1279 [[ibex.stream.tempdir]]
1282 <heading title="Cryptography"/>
1284 <property name="ibex.crypto.rsa(k,s)">
1285 **not implemented yet:** return a
1286 stream which rsa-decrypts stream **s** with key **k**
1289 <property name="ibex.crypto.rc4(k,s)">
1290 **not implemented yet:** return a
1291 stream which rc4-decrypts stream **s** with key **k**
1294 <property name="ibex.crypto.md5(s)">
1295 **not implemented yet:** immediately
1296 MD5-hash stream **s**
1299 <property name="ibex.crypto.sha1(s)">
1300 **not implemented yet:** immediately
1301 SHA1-hash stream **s**
1305 <!-- ----------------------------------------------------------------------- -->
1306 <section title="Traps">
1308 You can add a trap to a property by applying the [[++=]] operator
1309 to a function with one argument. The trap will be invoked whenever
1310 that property is written to.
1314 foo ++= function(z) {
1315 ibex.log.info("foo is " + z);
1320 If another script were to set the property "[[foo]]"
1321 on the box above to the value [[5]], the function above would be
1322 invoked with the argument [[5]]. The function would then log
1323 the string "[[foo is 5]]".
1325 Within a trap, the expression [[trapee]] can be used to
1326 get a reference to the box on which the trap was placed.
1328 The expression [[trapname]] returns the name of the
1329 trap executing the current function. This is useful when a function
1330 is applied to multiple traps. For example:
1334 func ++= function(z) {
1335 ibex.log.info("called trap " + trapname);
1342 <section title="Removing Traps">
1344 You can remove a trap by using the [[--=]] operator with the same
1345 function you added as a trap:
1349 var myfunc = function(z) { /* ... */ }
1360 <heading title="Multiple Traps on the Same Property"/>
1362 When the trapped property is **written** to, each of the trap
1363 functions placed on it will be invoked in the opposite order that
1364 they were placed on the box -- the most recently placed trap will
1365 execute first. This last-to-first execution of traps is called
1366 **cascading**. After the last trap is invoked, the value is
1367 stored on the box (remember, boxes are objects, so they can hold
1368 properties just like all other ECMAscript objects).
1370 <section title="Manual Cascades">
1372 There are two additional tricks you can use when placing traps. The
1373 first is a **manual cascade**. If you want to cascade to lower
1374 traps in the middle of a function, or you want to cascade with a
1375 different value than the value passed to you (in effect "lying" to
1376 lower traps), you can use [[cascade]]. For example:
1379 <ui:box color="black">
1380 color ++= function(c) {
1381 ibex.log.info("refusing to change colors!");
1387 This effectively creates a box whose color cannot be changed, and
1388 which complains loudly if you try to do so.
1390 Do **not** try to do something like this:
1393 <ui:box color="black">
1394 color ++= function(z) {
1395 color = "black"; // INFINITE LOOP! BAD!!!
1399 To prevent automatic cascading, return [[true]] from your function:
1402 <ui:box color="black">
1403 color ++= function(z) {
1404 return true; // the box's color will not change
1411 <section title="Read Traps">
1413 The other trick is a **read-trap**. Read traps are just like normal
1414 traps, except that you use a function that takes zero arguments instead of one. Read traps
1415 also do not automatically cascade.
1419 doublewidth [[++=]] function() { return 2 * width; }
1423 If another script attempts to read from the [[doublewidth]]
1424 property on this box, the value it gets will be twice the actual width
1425 of the box. Note that
1426 the actual [[doublewidth]] property on the box never gets written
1427 to, since the trap does not cascade.
1429 You can manually cascade on read traps as well:
1433 text [[++=]] function() { return "my text is " + cascade; }
1437 Read traps are only rarely needed -- most of the time a write trap
1442 <heading title="Prohibited Traps"/>
1444 To prevent confusing and hard-to-debug behaviors, scripts may not
1445 place traps on any of the properties described in the sections
1446 <link text="Box Layout Properties" section="Layout Properties"/>, <link
1447 section="Child-Control Properties"/>, or <link section="Other Box
1448 Properties"/> except for [[childadded]],
1449 [[childremoved]] and [[surface]]. FIXME: remove?
1451 <heading title="Exceptions and Traps"/>
1453 If an uncaught exception is thrown from a trap, Ibex will log the
1454 exception, but will **not** propagate it to the code which
1455 triggered the trap. If the trap was a read trap, the value
1456 [[null]] will be returned.
1457 FIXME: is this right?
1459 <heading title="Architectural Significance of Traps"/>
1461 Traps are the backbone of Ibex. Since almost all UI programming is
1462 event/demand driven, traps eliminate the need for separate
1463 member/getter/setter declarations, often cutting the amount of typing
1464 you have to do to a third of what it would normally be.
1466 <section title="Cloning">
1468 **Cloning** is a companion technique for traps; together they can
1469 be used to simulate any sort of environment you might need. When you
1470 call [[ibex.clone(o)]], Ibex returns a new object (called the
1471 **clone**) which compares with equality ([[==]]) to the
1472 original object. Furthermore, both objects are "equal" as keys in
1477 var theclone = ibex.clone(o);
1479 ibex.log.info(hash[theclone]); // prints "5"
1482 Any writes to properties on the clone will actually write to
1483 properties on the original object, and reads from properties on the
1484 clone will read properties on the original object. In fact, the only
1485 thing that can be used to distinguish the original from the clone is
1486 traps -- a trap placed on the clone is **not** placed on the
1487 original object as well.
1492 <!-- ----------------------------------------------------------------------- -->
1493 <section title="Threads">
1495 <section title="Contexts">
1497 From the perspective of an application writer, Ibex is strictly
1498 single-threaded. Ibex is always in exactly one of the following three
1501 <list type="unordered">
1503 __Rendering Context__ -- (redrawing the screen)
1505 __Event Context__ (executing javascript traps triggered by an event)
1507 __Thread Context__ (executing a background thread spawned with [[ibex.thread]])
1511 There are two important restrictions on what can be done in particular contexts:
1513 <list type="unordered">
1515 The [[box.mouse]] property and its subproperties
1516 ([[x]], [[y]], and [[inside]]) can only be read
1517 from within the Event Context, or in a thread context
1518 **after** a the [[box.mouse]] property on this box or
1519 an ancestor box has been written to.
1521 Blocking operations (anything that accesses the network or
1522 disk) can only be performed in the Thread Context.
1528 <section title="Background Threads">
1530 Ibex offers easy access to threads. Spawning a background thread is as
1531 simple as writing a function to the [[ibex.thread]] property:
1534 ibex.thread = function() {
1535 ibex.log.info("this is happening in a background thread!");
1539 The argument set passed to the function is currently undefined and is
1540 reserved for use in future versions of Ibex. Scripts should not
1541 depend on the number or content of these arguments.
1543 Ibex is **cooperatively multitasked**, so threads must not process
1544 for too long. This was a deliberate choice; cooperatively
1545 multitasked environments do not require complex locking primitives
1546 like mutexes and semaphores which are difficult for novices to
1547 understand. The disadvantage of cooperative multitasking is that one
1548 thread can hog the CPU. This is unlikely to happen in Ibex for two reasons:
1549 first, all blocking I/O operations **automatically** yield the CPU,
1550 so the overall user interface never becomes unresponsive because it is
1551 waiting for a disk or network transfer. Second, since Ibex is strictly
1552 a user interface platform, Ibex scripts are unlikely to perform highly
1553 compute-intensive operations that keep the CPU busy for more than a
1559 <section title="Events">
1561 Every execution of the Event Context begins with an event, which
1562 consists of a key/value pair, and a mouse position, which consists of
1563 an x and y coordinate. The possible keys are [[_Press[1-3]]],
1564 [[_Release[1-3]]], [[_Click[1-3]]], [[_DoubleClick[1-3]]],
1565 [[_Move]], [[_KeyPressed]], and [[_KeyReleased]].
1567 Here are two example events:
1569 An event is triggered by writing the key to the value on a box. This
1570 triggers any trap handlers which may be present. Once these handlers
1571 have executed, Ibex figures out which child of the current box contains
1572 the mouse (taking into account that some boxes may cover up others)
1573 and writes the key and value to that box. If none of the box's
1574 children contain the mouse position, Ibex removes the leading
1575 underscore from the key name and writes the value to
1576 **that** property. Once all the traps on that property have
1577 executed, the value is written to the box's parent.
1579 Intuitively, Ibex delivers the underscored event to every box from the
1580 root to the target, and then delivers the non-underscored event to
1581 that same set of boxes in reverse order. So the event travels down
1582 the tree to the target, and then back up to the root. The following
1583 example prints out "first second third fourth" in that order.
1587 _Press1 ++= function(b) { ibex.log.info("first"); }
1588 Press1 ++= function(b) { ibex.log.info("fourth"); }
1590 _Press1 ++= function(b) { ibex.log.info("second"); }
1591 Press1 ++= function(b) { ibex.log.info("third"); }
1596 In general, you should use the **non-underscore** names to respond
1597 to user input and use the underscored names when you want to override
1598 child boxes' behavior or route events to particular boxes (for
1599 example, when implementing a focus protocol). This is why the
1600 underscored elements are delivered to parents before children (so
1601 parents can override their childrens' behavior), but non-underscored
1602 events are delivered to children before parents (since, visually, a
1603 mouse click is usually "intended" for the leaf box underneath the
1608 <heading title="Stopping the Process"/>
1610 At any point in this sequence, a trap handler can choose not to
1611 cascade (by returning [[true]] from the trap handler function).
1612 This will immediately cease the propagation of the event. This is how
1613 you would indicate that an event has been "handled".
1615 <heading title="Non-Propagating Events"/>
1617 Ibex uses the following events to notify a box about changes that
1618 only matter to that particular box. These events do not propagate
1619 either up or down the tree.
1621 <property name="Enter Leave">
1622 The value [[true]] is written to this property when the mouse (enters/leaves) the box.
1625 <property name="SizeChange">
1626 The value [[true]] is put to this property after the size
1627 of this box changes.
1630 <property name="ChildChange">
1631 When a child is added or removed, that child is written to
1632 this property. The write is always performed **after** the
1633 addition or removal, so these two cases can be distinguished
1634 by checking [[indexof(child)]].
1636 Note that if the parent's redirect target is set to another
1637 box, this trap will only be invoked when children are
1638 manipulated by reading and writing to the parent. Reads and
1639 writes directly to the redirect target will **not** trigger
1642 Note also that this traps is still triggered if a box's
1643 [[redirect]] target is **null**. This is useful for
1644 boxes that need to accept children and then relocate them
1648 <section title="Listing of Events">
1650 <property name="Press1 Press2 Press3">
1651 Indicates that the use has pressed a mouse button. On
1652 platforms with three mouse buttons, the **middle** button
1653 is button 3 -- this ensures that applications written to only
1654 use two buttons (1 and 2) will work intuitively on three button
1658 <property name="Release1 Release2 Release3">
1659 Indicates that the use has released a mouse button.
1662 <property name="Click1 Click2 Click3">
1663 Indicates that the user has pressed and released the
1664 mouse button without moving the mouse much (exactly how
1665 much is platform-dependent).
1668 <property name="DoubleClick1 DoubleClick2 DoubleClick3">
1669 Indicates that the user has clicked the
1670 mouse button twice within a short period of time (exactly how long is platform-dependent).
1673 <property name="Move">
1674 Indicates that the mouse has moved while within this box, or that
1675 the mouse while outside this box **if a button was pressed while within this box and has not yet been released**
1678 <property name="KeyPressed KeyReleased">
1680 A string is written to this property when a key is pressed or
1681 released If the key was any other key, a multi-character
1682 string describing the key will be put. For simplicity, we use
1683 the VK_ constants in the <link
1684 url="http://java.sun.com/products/jdk/1.1/docs/api/java.awt.event.KeyEvent.html#VK_0"
1685 text=" Java 1.1 API java.awt.event.KeyEvent class"/>. When a
1686 key is pressed or released, the string put will be the portion
1687 of its VK_ constant after the underscore, all in lower case.
1690 If the shift key was depressed immediately before the
1691 event took place, then the string will be capitalized. Special
1692 keynames are also capitalized; shift+home is reported as
1693 "[[HOME]]". Symbols are capitalized as they appear on the
1694 keyboard; for example, on an American QWERTY keyboard, shift+2
1695 is reported as "[[@]]".
1697 If the alt, meta, or command key was depressed immediately
1698 before this key was pressed, then the string will be prefixed
1699 with the string "[[A-]]". If the control key was depressed
1700 while this key was pressed, then the string will be prefixed
1701 with the string "[[C-]]". If both alt and control are
1702 depressed, the string is prefixed with "[[C-A-]]".
1704 Ibex does not distinguish between a key press resulting from
1705 the user physically pushing down a key, and a 'key press'
1706 resulting from the keyboard's typematic repeat. In the rare
1707 case that an application needs to distinguish between these
1708 two events, it should watch for KeyReleased messages and
1709 maintain an internal key-state vector.
1717 <!-- ----------------------------------------------------------------------- -->
1718 <section title="Networking">
1720 <section title="XML-RPC">
1722 XML-RPC objects can be created by calling [[ibex.net.rpc.xml(**XML-RPC
1723 URL**)]], and then invoking methods on that object. For example,
1726 Press1 += function(v) {
1727 ibex.thread = function() {
1728 color = ibex.net.rpc.xml("http://xmlrpc.ibex.org/RPC2/").
1729 color.getTodaysColor("Friday");
1734 When the user clicks the first mouse button on this box, it will
1735 contact the server [[xmlrpc.ibex.org]], route to the
1736 [[/RPC2/]] handler and invoke the [[getTodaysColor()]]
1737 method on the [[color]] object with a single string argument
1738 "[[Friday]]". The return value will be used to change the color
1739 of the box the user clicked on.
1741 Note that in this example we spawned a background thread to handle the
1742 request -- the [[Press1]] event is delivered in the foreground
1743 thread, and XML-RPC methods may only be invoked in background
1744 threads. This is to prevent the UI from "locking up" if the server
1745 takes a long time to reply.
1747 If the XML-RPC method faults, an object will be thrown with two
1748 properties: [[faultCode]] and [[faultString]], as defined in
1749 the <link url="http://www.xmlrpc.org/spec" text="XML-RPC specification"/>. If
1750 Ibex encounters a network, transport, or session-layer error, it will
1751 throw a [[String]] object describing the error in a
1752 human-readable format. Scripts should not rely on the contents of
1753 this string having any special structure or significance.
1755 If an object with an associated non-empty stream is passed as an
1756 argument to an XML-RPC method, it will be sent as a <base64/>
1757 element. If a <base64/> element is found in the XML-RPC reply, it
1758 will be returned as an object with a stream drawn from that byte sequence.
1760 Each object returned by [[ibex.net.rpc.xml()]] represents a
1761 single HTTP connection. The connection will be held open until
1762 the object is garbage collected or the server closes the
1763 connection. If a second call is issued on the object before the
1764 first one returns (usually from a seperate thread), the two calls
1766 url="http://www.w3.org/Protocols/rfc2616/rfc2616-sec8.html#sec8.1.2.2"
1767 text="pipelined"/>. This can dramatically improve performance.
1769 Ibex supports HTTP Basic and Digest authentication. To use
1770 authentication, pass [[ibex.net.rpc.xml()]] a URL in the form
1773 http[s]://user:password@hostname/
1776 Ibex will use Digest authentication if the server supports it;
1777 otherwise it will use Basic authentication. Please be aware that
1778 many XML-RPC server implementations contain a <link
1779 url="http://www.ibex.org/faq.html#auth" text="broken
1780 implementation of Basic authentication"/>.
1784 <section title="SOAP">
1786 SOAP methods are invoked the same way as XML-RPC methods, but with three differences:
1788 <list type="ordered">
1790 [[ibex.net.rpc.soap()]] is used instead of
1791 [[ibex.net.rpc.xml()]]
1793 Instead of specifying just the URL of the service itself, you
1794 must specify the URL, the SOAPAction argument, and the
1797 The actual method invocation takes only one argument, which
1798 must be an object. This is necessary since SOAP arguments are
1799 specified by name, rather than ordering.
1803 SOAP faults are handled the same way as XML-RPC faults except that the
1804 capitalization of the [[faultstring]] and [[faultcode]]
1805 members is all lower-case, to match the SOAP spec. Here is a
1809 Press1 ++= function(v) {
1810 ibex.thread = function() {
1811 color = ibex.net.rpc.soap("http://soap.ibex.org/SOAP",
1813 "http://ibex.org/namespace"
1814 ).color.getTodaysColor( {
1821 As you can see, SOAP is much more verbose, yet does not offer
1822 substantially improved functionality. We recommend that XML-RPC be
1823 used whenever possible, and that SOAP be reserved for legacy
1826 The current Ibex SOAP stack does not support 'document style' or
1827 multi-ref ([[href]]) data structures.
1831 <section title="Security">
1833 Applications downloaded from the network (as opposed to those loaded
1834 from the filesystem) may only make certain kinds of connections to
1835 certain hosts. See Appendix A for a detailed description of the
1841 <!-- ----------------------------------------------------------------------- -->
1842 <section title="Error Handling">
1844 If the Ibex Core encounters an error while servicing a function call
1845 originating in JavaScript, the core will throw a string consisting of
1846 an error code followed by a colon, a space, and a descriptive message.
1850 "ibex.net.dns.unknownhostexception: unable to resolve host foo.com"
1853 The code should be used to determine how the program should respond to
1854 an error. The codes are organized in a hierarchy, so the
1855 string.startsWith() method can be used to determine if an error lies
1856 within a particular subhierarchy. The descriptive message portion of
1857 the string may be shown to the user.
1859 <property name="ibex.assertion.failed">
1862 <property name="ibex.io">
1863 General I/O exceptions
1865 <property name="ibex.io.encoding">
1866 Error translating between character encodings.
1868 <property name="ibex.io.zip">
1869 Attempted to access a corrupt zip archive.
1871 <property name="ibex.io.eof">
1872 End of file encountered unexpectedly
1874 <property name="ibex.net.security.prohibitedHost">
1875 A piece of untrusted Ibex code attempted to contact a
1876 restricted host. See <link appendix="Security Architecture and Considerations"/> for details.
1878 <property name="ibex.net.dns.temporaryFailure">
1879 An attempt to resolve a hostname failed but it is not known
1880 for certain that the hostname is invalid.
1882 <property name="ibex.net.dns.unknownHost">
1883 An attempt to resolve a hostname failed because the hostname
1886 <property name="ibex.net.socket.closed">
1887 A socket was closed unexpectedly.
1889 <property name="ibex.net.socket.connectionFailed">
1890 A connection could not be made to the remote host.
1892 <property name="ibex.net.url.malformed">
1893 Tried to parse a malformed URL.
1895 <property name="ibex.net.ssl">
1896 General SSL protocol errors.
1898 <property name="ibex.net.ssl.untrustedCertificate">
1899 The server's certificate was not signed by a CA trusted by Ibex.
1901 <property name="ibex.net.http.">
1902 Thrown when an HTTP error code is returned during an
1903 operation. The three characters [[**xyz**]] will be
1904 the three-digit HTTP status code.
1906 <property name="ibex.net.xmlrpc.null">
1907 The caller attempted to transmit the [[null]] value via XML-RPC.
1909 <property name="ibex.net.xmlrpc.circular">
1910 The caller attempted to transmit a circular data structure via XML-RPC.
1912 <property name="ibex.net.xmlrpc.specialObject">
1913 The caller attempted to transmit a "special" object via
1914 XML-RPC (for example, a Box or the Ibex object).
1916 <property name="ibex.null.put">
1917 A JavaScript attempted to put to a property on the [[null]] value
1919 <property name="ibex.null.get">
1920 A JavaScript attempted to get from a property on the [[null]] value
1922 <property name="ibex.null.call">
1923 A JavaScript attempted to call the [[null]] value
1926 If an exception is thrown inside a trap, the exception will propagate
1927 to the script that triggered the trap.
1929 If an uncaught exception is thrown while applying a template, or the
1930 requested template could not be found, an error will be logged and the
1931 box to which the template was being applied will be made invisible
1932 ([[visible = false]]). This ensures that half-applied widgets are
1933 never shown to the user.
1937 <!-- ----------------------------------------------------------------------- -->
1938 <section title="Advanced Topics">
1940 <section title="Re-routing events">
1942 At any point in the Event Context, you can write to the [[mouse]]
1943 property on any box. The value written should be an object with two
1944 properties, [[x]] and [[y]]. For example:
1947 _Press1 ++= function(p) {
1948 mouse = { x: 32, y: 77 };
1952 The coordinates specified are relative to the box whose [[mouse]]
1953 property is being written to. There is no need to supply the
1954 [[inside]] property; it is computed automatically. Writing to
1955 the [[mouse]] property causes Ibex to recompute the eventual
1956 target box, and also alter the values returned by [[mouse.x]],
1957 [[mouse.y]], and [[mouse.inside]] for any **descendants**
1958 of the current box. Writing to the [[mouse]] property also
1959 automatically prevents the event from returning to the box's parents
1960 -- it is equivalent to not cascading on the non-underscored event.
1961 This ensures that child boxes cannot trick their parent boxes into
1962 thinking that the mouse has moved.
1964 If you want the event to "skip over" the boxes between the trapee
1965 and the target, or if you want to re-route an event to a box which
1966 is not a descendant of the current box, simply write the value to
1967 the proper key on the target box.
1971 _KeyPressed = function(k) { ibex.log.info("first"); }
1972 KeyPressed = function(k) { ibex.log.info("sixth"); }
1973 $recipient.target = $target;
1974 <ui:box id="recipient">
1975 _KeyPressed = function(k) {
1976 ibex.log.info("second");
1977 thisbox.target.KeyPressed = k;
1978 // inhibit cascade; keep event from going to $excluded
1981 KeyPressed = function(k) { ibex.log.info("fifth"); }
1982 <ui:box id="excluded">
1983 _KeyPressed = function(k) {
1984 ibex.log.info("this never happens");
1988 <ui:box id="target">
1989 _KeyPressed = function(k) { ibex.log.info("third"); }
1990 KeyPressed = function(k) { ibex.log.info("fourth"); }
1997 <section title="Synthesizing Your Own Events">
1999 You can create "fake events" by simply writing to the [[mouse]]
2000 property and then writing a value to one of the underscored properties
2001 on a box. This will have exactly the same effect as if the use had
2002 actually pressed a key, clicked a button, or moved the mouse -- they
2003 are indistinguishable.
2007 <section title="Ibex self-emulation">
2009 When the core first starts up, it clones the [[ibex]] object,
2010 creates a stream for the initial .ibex, and then places a trap on the
2011 cloned [[ibex]] object so that its empty-string property returns
2012 the .ibex stream. The cloned Ibex object is then passed as the third
2013 (optional) argument to [[ibex.apply()]], making it the default
2014 [[ibex]] object for the scripts that are executed as part of the
2015 template instantiation.
2018 var new_ibex = ibex.clone(ibex);
2019 var stream = ibex.bless(ibex.stream.url("http://..."));
2020 new_ibex[""] ++= function() { return stream; }
2021 ibex.apply(ibex.box, new_ibex..main, new_ibex);
2024 Note that we called [[ibex.bless()]] on the stream before tacking
2025 it on to the new Ibex object. The bless function returns a clone of
2026 the object passed to it, with a few traps which are explained below.
2027 Additionally, any sub-streams retrieved by accessing properties of the
2028 blessed stream will also automatically be blessed (blessed streams are
2031 Blessing a stream serves three purposes:
2033 <list type="unordered">
2035 Blessed clones always return the appropriate static block when
2036 their empty property is accessed; this ensures that references
2037 to the static blocks of other templates work properly.
2039 Blessed substreams can return their parent stream by accessing
2040 a hidden property which is reserved for internal use by Ibex.
2041 This ensures that Ibex can automatically add filename
2042 extensions where needed, according to the following rules:
2045 If the stream is a template to be applied, the string
2046 "[[.ibex]]" is appended.
2048 If the stream is an image, the string "[[.png]]" is
2049 appended. If no stream is found, "[[.jpeg]]" and
2050 "[[.gif]]" are tried, in that order.
2052 If the stream is an font, the string "[[.ttf]]" is
2056 Every call to [[ibex.bless()]] returns a different object
2057 (which happens to be a clone of the object passed to it) with
2058 a completely separate set of static blocks.
2062 Ibex can self-emulate by using [[ibex.clone()]] on the Ibex object;
2063 this technique is very similar to the use of ClassLoaders in
2064 Java. This is useful for a number of applications, including
2065 debuggers, IDEs, sandboxing untrusted code, remote-control, and
2066 others. For example:
2069 var newLoadFunction = function(url) { /* ... */ };
2070 var new_ibex = ibex.clone(ibex);
2071 new_ibex.load ++= function() { return newLoadFunction; }
2072 ibex.apply(ibex.box, .main, new_ibex);
2077 <!-- ----------------------------------------------------------------------- -->
2078 <appendix title="Security Architecture and Considerations">
2080 Due to the expense and hassle imposed by the commercial PKI code
2081 signing architecture, and the fact that it <link
2082 url="http://www.counterpane.com/pki-risks-ft.txt" text="doesn't
2083 really provide any security anyways"/>, Ibex user interfaces are
2084 distributed as unsigned, untrusted code. As such, they are handled
2085 very carefully by the Ibex Core, and assumed to be potentially
2088 Ibex's security architecture is divided into defenses against four
2089 major classes of attacks:
2091 <heading title="Malicious UI attempts to acquire or alter data on the client"/>
2093 Ibex user interfaces are run in an extremely restrictive sandbox. The
2094 environment does not provide primitives for accessing any data outside
2095 the Ibex core except via XML-RPC and SOAP calls. There are no
2096 facilities to allow Ibex user interfaces to access the client's
2097 operating system or to interact with other applications on the same
2098 host (unless they provide a public XML-RPC or SOAP interface).
2099 An Ibex script may only access a file on the user's hard disk if the
2100 user explicitly chooses that file from an "open file" or "save file"
2101 dialog. There is one exception to this rule: if all templates
2102 currently loaded in the Ibex core originated from the local
2103 filesystem, those templates can load additional .ibexs from the local
2106 The Ibex Core is written in Java, so it is not possible for
2107 scripts to perform buffer overflow attacks against the core
2110 Ibex applications may only read from the clipboard when the user
2111 middle-clicks (X11 paste), presses control-V (Windows paste), or
2112 presses alt-V (Macintosh paste; the command key is mapped to Ibex
2113 "alt"). This ensures that Ibex applications are only granted access to
2114 data that other applications have placed on the clipboard when the user
2115 specifically indicates that that information should be made available
2116 to the Ibex application.
2118 <heading title="Malicious UI attempts to use client to circumvent firewalls"/>
2120 Ibex user interfaces may only make XML-RPC or SOAP calls and load .ibex
2121 archives via HTTP; they cannot execute arbitrary HTTP GET's or open
2122 regular TCP sockets.
2124 Ibex will not allow a script to connect to a non-public IP address
2125 (10.0.0.0/8, 172.16.0.0/12, or 192.168.0.0/16, as specified in <link
2126 url="http://www.cis.ohio-state.edu/cgi-bin/rfc/rfc1918.html" text="RFC
2127 1918"/>). There is one exception -- if all templates currently loaded
2128 in the core originated from the same IP address, those scripts may
2129 make calls to that IP address regardless of whether or not it is
2130 firewalled. If Ibex does not have access to a DNS resolver (because it
2131 is using a proxy which performs DNS lookups), Ibex will provide the
2132 proxy with the appropriate <link
2133 url="http://www.ibex.org/x-requestorigin.html"
2134 text="X-RequestOrigin"/> header that the proxy needs in order
2135 to maintain security.
2137 The only remaining possible attack is against a XML-RPC or SOAP
2138 service running on a firewalled host with a public address. Assigning
2139 such machines public IP addresses is a poor network security policy,
2140 and doing so squanders scarce public IPv4 addresses. As such, the onus
2141 is on the administrators of such machines to explicitly block access
2142 to clients reporting a [[User-Agent:]] header beginning with the
2143 four characters "[[IBEX]]".
2145 <heading title="Malicious UI attempts to trick user into divulging secret information"/>
2147 All top-level windows created by Ibex are **scarred** -- a stripe
2148 and a lock is drawn across the corner of the window. There is no way
2149 for a user interface to remove this scar. Ibex user interfaces may not
2150 create windows smaller than the size of the scar.
2152 <heading title="Malicious network attempts to snoop or man-in-the-middle transactions"/>
2154 Ibex user interfaces may transmit network data using HTTPS (SSL 3.0)
2155 for encryption. Ibex will attempt 128-bit encryption, but will
2156 negotiate down to 40-bit if the server does not support strong
2157 crypto. Ibex's SSL implementation is currently provided by <link
2158 url="http://www.ibex.org/tinyssl" text="TinySSL"/> and <link
2159 url="http://www.bouncycastle.org" text="The Legion of the Bouncy
2162 All HTTPS connections must be authenticated by the server using a
2163 certificate whose name matches the domain name of the HTTPS URL. The
2164 certificate must be signed by a trusted root CA. Ibex trusts the same
2165 93 root CAs whose certificates are included as "trusted" in Microsoft
2166 Internet Explorer 5.5 SP2. This provides a minimal level of protection
2167 against man-in-the-middle attacks; you should not trust this
2168 connection with any data you would not normally trust an SSL-enabled
2173 <!-- ----------------------------------------------------------------------- -->
2174 <appendix title="ECMAscript compliance">
2176 Ibex's scripts are written in a modified subset of ECMA-262, revision 3
2177 (aka JavaScript 1.5). The interpreter strays from the spec in a few
2180 <section title="Omissions">
2182 The following ECMA features are not supported:
2184 <list type="unordered">
2186 The [[undefined]] value, [[===]], and [[!==]]
2188 The [[new]] keyword (and ECMAScript object inheritance)
2191 [[getter]] and [[setter]]
2193 The ECMA [[this]] keyword.
2195 The [[String]], [[Number]], and [[Boolean]]
2196 classes. Note that [[string]], [[number]], and
2197 [[boolean]] values are supported, however.
2199 You may not [[throw]] the [[null]] value.
2203 Additionally, you must declare all root-scope variables (with
2204 [[var]]) before using them; failure to do so will result in an
2205 exception. Box properties are pre-defined in the scope that scripts
2210 <section title="Extensions">
2212 <list type="unordered">
2214 The token [[..]] is equivalent to [[[""]]].
2220 Extended [[catch]] syntax. The following code:
2222 } catch(e propname "foo.bar.baz") {
2229 if (e.propname != null and e.propname >= "foo.bar.baz" and
2230 "foo.bar.baz/" > e.propname) {
2235 Multiple extended-catch blocks can appear at the end of a single try
2236 block. However, at most one non-extended catch block may appear, and
2237 if it does appear, it must be the last one.
2239 Since Ibex ECMAscripts are wrapped in XML, the lexical token
2240 "[[lt]]" is be interpreted as [[<]], the lexical
2241 token "[[gt]]" is be interpreted as [[>]], and the
2242 token "[[and]]" is interpreted as [[&&]].
2243 Thus these tokens cannot be used as variable names.
2245 The identifier [[static]] is a reserved word in
2246 ECMAScript, but not in Ibex.
2248 Ibex defines an additional reserved word, "[[assert]]",
2249 which will evaluate the expression which follows it, throwing
2250 a [[ibex.assertion.failed]] exception if the expression
2251 evaluates to [[false]].
2253 To ensure that Ibex files appear the same in all text editors, tab
2254 characters are not allowed in Ibex files.
2258 Some useful tutorials include:
2260 <list type="unordered">
2263 url="http://developer.netscape.com/docs/manuals/communicator/jsref/index.htm"
2264 text=" JavaScript 1.2 Reference"/>. Although this document is
2265 out of date, it is arguably the best guide available for free
2266 on the Internet. The changes from JavaScript 1.2 (aka ECMA-262
2267 r1) to 1.5 were minimal, and many of them were <link
2268 url="ecmascriptcompliance" text="omitted"/> from Ibex.
2271 url="http://search.barnesandnoble.com/booksearch/isbnInquiry.asp?isbn=0596000480"
2272 text=" JavaScript: The Definitive Guide"/>, by David Flanagan
2273 and Paula Ferguson. The latest edition of this book covers
2274 JavaScript 1.5 (ECMA-262 r3).
2277 url="http://www.ecma.ch/ecma1/STAND/ECMA-262.HTM"
2278 text="ECMA-262"/> specification. This is an extremely
2285 <!-- ----------------------------------------------------------------------- -->
2286 <appendix title="Logging and Command Line Invocation">
2289 Usage: ibex [-lawp] [ url | file | directory ]
2290 -l [level] set logging level to { debug, info (default), warn, error, silent }
2291 -l rpc log all XML-RPC and SOAP conversations
2292 -l user@host email log to user@host
2293 -l host:port emit log to TCP socket
2294 -l [file] write log to a file on disk
2296 -w [window-id] reserved for libibex
2297 -p dump profiling information [not yet supported]
2300 If Ibex encounters a serious problem before it starts logging
2301 information, or if it is unable to open the log file, it will abort
2302 immediately with a critical abort, which will be displayed on the
2303 console for POSIX-native cores and in a dialog box for JVM-based and
2306 Note that Microsoft Windows does not provide any mechanism for
2307 redirecting standard input/output of an application which is not
2308 compiled as a "console application". Therefore, Ibex is compiled
2309 as a "console application", and will open a console window when
2310 invoked. To inhibit this console window, provide a logging
2311 destination (file, port, etc).
2313 The [[**source-location**]] parameter can be either the path
2314 to an [[.ibex]] archive, the http url of an [[.ibex]]
2315 archive, or the path to a directory comprising an unpacked
2318 The [[**initial-template**]] parameter is the stream name of
2319 a template to be used as the initial template. If ommitted, it
2320 defaults to [[main]].
2322 The [[-v]] option causes Ibex to enable verbose logging; this will
2323 cause it to log **lots** of information to the log file. This
2324 option will also substantially decrease Ibex's performance.
2328 <!-- ----------------------------------------------------------------------- -->
2330 <appendix title="Grammars">
2332 **Grammar support is experimental in this release
2333 and may not work properly. It may change in incompatible ways or
2334 disappear completely from future releases**
2336 Grammars are defined with a statement in the following form:
2341 A grammar is really just another function; once defined you can't tell
2342 it apart from an ordinary function. A grammar takes one argument,
2343 which can be a string or stream. The argument is parsed and the
2344 result of executing the code block 'c' is returned.
2346 The property 'a' is read; if the value is a grammar, a new production
2347 rule (ie a new alternative, as with '[[|]]') is added to that grammar
2348 (this is a destructive update). This allows you to add productions to
2349 pre-existing grammars (for example, adding a new type of expression to
2350 a programming language by extending the 'expr' grammar). If the old
2351 value is not a grammar, the value is discarded and a new grammar
2354 The value 'b' is a pattern, which may consist of seven simple
2357 <list type="unordered">
2360 grouping parens [[()]]
2362 combinators: [[ | + * ?]]
2364 references to other grammars
2367 The value 'c' and the braces surrounding it are an *optional* code
2368 block, in which the following identifiers are bound:
2370 <list type="unordered">
2372 The identifier 'whole' is bound to the string matched by the
2373 entire expression. If the code block is omitted it behaves
2374 as if it were "[[{ return whole; }]]".
2376 For every reference to another grammar which was matched in the
2377 pattern, the *name used to reference that other grammar* will
2378 be bound to the value returned by its code block. Here's an
2379 example of this important distinction:
2382 var foo ::= 'a' | 'b';
2384 var baz ::= 'c' | bar { /* foo is not defined here, but bar is */ };
2387 On the last line, the identifier 'bar' serves two purposes: it
2388 pulls in the definition of the pattern *and* acts as a binder
2389 within the scope of the braces.
2391 If a reference is matched multiple times (either because it
2392 appears multiple times in the pattern or because the * or +
2393 operator was applied to it) then its name will be bound to an
2394 array containing the matches.
2398 Here is the metacircular definition of the grammar facility:
2401 grammar ::= identifier '::=' pattern (';' | '{' code '}' ';'?)
2402 identifier ::= ('a'..'z' | 'A'..'Z' | '_' | '$') (identifier | '0'..'9')*
2403 char ::= '\0x0000'..'\0xffff'
2404 literal ::= '\'' char+ '\''
2405 | '\'' char '\'' '..' '\'' char '\''
2406 pattern ::= identifier
2413 | pattern '|' pattern
2418 Copyright (C) 2004 Adam Megacz, verbatim redistribution permitted.
2419 Ibex is a trademark of Adam Megacz