JIX
 
  Why not try to keep it simple ?
 
     (C) Henri Lesourd 2018, 2019
 
1. Rationale
JIX (aka. Javascript, Interactive, and eXtensible) is a Javascript toolkit meant to enable the development of simple and evolveable software. It is made of a set of combinable mini-languages that enable setting up and developing simple apps mostly without programming, and of a set of orthogonal libraries that enable extending these simple apps by means of Javascript code to develop more sophisticated designs. This provides an excellent basis to develop modern, leightweight webapps in an incremental fashion.

JIX is free software. It is released under the LGPLv3.


2. A tour of JIX
In this document, we describe the functionalities available in JIX by means of showing how to develop the most salient parts of a webapp that enables browsing a little music database:

  
    Figure 1: a simple webapp to browse a music database


In Section 3 below, we explain how data can be represented in JIX by means of objects. In Section 4, we show how to use an extension of HTML called JXML to develop user interfaces, while the development of JIX applications directly by means of the Javascript programming language is discussed in Section 5. In Section 6, we talk about how to build, package, install & run these applications by means of JIX. Finally, in Appendix A and Appendix B, we give a summary of the APIs and of the events system.


3. Data description language
Objects in JIX are represented as attribute-value lists, (mostly) like any other Javascript objects. For example, the song "Imagine", by John Lennon, could be represented (using JSON notation) as the following object:
The simplest way available in JIX to store such objects is inside CSV files, with the first line describing the objects' attributes, and with one object per line. For example:
CSV files can be edited with any spreadsheet software like Excel or Open Office, which makes the creation and manipulation of data files very convenient in JIX.

On the first line of such a CSV data file, a given column's description contains its name, plus a number of optional informations, related to the type of its values, separated from the name by a colon (":"). For example, in the CSV snippet shown above, the column Year has values that are of type int, while the column Authors has values that are of type "list of strings" (written as "*str").

The data types currently available in JIX are:
int Integers (positive or negative).
num Numbers (floating point).
str Strings (the default type).
obj Object references. The object references are written using the character "#" as the prefix of an object's id. For example given an object having the following shape:

#obj1 is then a reference to this object.
* Lists (used as a prefix, e.g. "*str"): the cell contains multiple elements.
*! Sets (used as a prefix, e.g. "*!str"): the cell contains multiple elements that are all unique, i.e., no element appears more than one time in the list.

To make all this more concrete, we will now develop our previous example a little bit more, and on the one hand, show how to create data files containing objects of several classes (i.e., songs, as above, but also authors), and on the other hand, show how precisely these data files can be laid out in the filesystem, along with the way to query and modify the objects that they contain.

Let's now turn our little media database to something a bit more elaborate. In the CSV file shown above, the information related to the authors of a song is stored as a list of strings, using only the name and the first name of each author to indentify him/her. Let's now create another CSV file (named "Persons.csv") to store the description of our authors, now using first-class objects to this purpose (rather than only strings):
In the CSV file above, the authors' descriptions have an id that can be used to refer to them, plus well-defined attributes to store their names and first names. Also, we use a list of int (type written as "*int") as the type of the objects' Years attribute, to store the birth and death years of our authors. To use this newly minted way of representing our authors' information in the CSV file (named "Songs.csv") that contains the songs' descriptions, we will modify it in the following way:
Observe how we changed the type of the column Authors, turning it to a set of objects' references (written as "*!obj"), and how we replaced the content of the related cells by lists of references pointing to the objects stored in "Persons.csv" that describe the relevant authors.

Finally, we will now show how to query and modify the data which is stored in our little database. Let's suppose we have a folder (named "mwiki") for our project, located in "/home/henri" in the filesystem. Under the UNIX shell, we have:
To query our database, we will use the jix command. To list all the songs stored in the CSV files located in the directory /home/henri/mwiki having a Genre equal to "Rock", we can do:
To list all the songs from John Lennon stored in the database (when the name of the folder containing the CSV files is omitted, the jix command looks for the data files in the shell's current working directory), we can do:

And to add another author in the database, we do:

Now to to set the first name of the author we just added in the database, we can proceed as such, first fetching the corresponding object by means of its id attribute, then modifying it:


4. User interfaces
User interfaces in JIX can be implemented (mainly) in two ways : either by means of an HTML page containing Javascript code that creates widgets by means of the JIX APIs, and then attaches the obtained widget tree to the browser's DOM to activate it, or either by means of an extension of HTML called JXML, enabling the designer to develop the user interface directly by means of markup.


4.1. Core HTML+CSS
As we just noted, JXML is an extension of HTML, which means that all the HTML tags are available in JXML, along with all the CSS styling functionalities that come with them (since for each JXML tag there is one corresponding HTML tag once the JXML has been expanded to HTML, the whole set of available CSS styling functionalities also applies to JXML tags, by means of the class and style attributes, as usual).

In the current Section 4.1, as a remainder, we describe some of the core functionalities of HTML+CSS, as they are often used directly in the development of JIX/JXML user interfaces.

4.1.1. Text attributes

Basic HTML tags:
Text in italics.
Underlined text.
Bold text.
<font face=FONT
      size=SIZE
      color=COLOR> 
...
</font>
Specifying attributes for the text (especially, the font face, the size and the text's color).

Basic CSS properties:
Sets the font face (e.g. "Arial", "Times New Roman", "Helvetica", "Courier", etc.).
Sets the font size (e.g. in %, rem, px, pt).
Sets the font style (e.g. normal, oblique, italic).
Sets the font weight (e.g. normal, bold, lighter).
Sets the text decoration (e.g. none, line-through, underline).
Sets the text's color (e.g. red, blue, #80ab80).
Sets the text's background color.


4.1.2. Characters

Line break.
Horizontal rule.
Nonbreaking space.
Ampersand ("&").
Less than ("<").
Greater than (">").
Uppercase "A" with grave accent ("À").
Uppercase "A" with acute accent ("Á").
Uppercase "A" with circumflex ("Â").
Uppercase "A" with umlaut ("Ä").
Lowercase "a" with grave accent ("à").
Lowercase "e" with acute accent ("é").
Lowercase "c" with cedilla ("ç").
Greek small letter alpha ("α").
Greek small letter beta ("β").
Greek small letter gamma ("γ").
Greek small letter delta ("δ").
Greek small letter epsilon ("ε").


4.1.3. Composite markup

Grouping elements:
Inline composite element.
Block composite element.

Alignment, size & borders (CSS):
Text horizontal alignment (e.g. center, justify, left, right).
Text vertical alignment (e.g. top, bottom, middle, baseline).
Element's width (e.g. in %, rem, px, pt).
Element's height (e.g. in %, rem, px, pt).
Element's border width (e.g. in %, rem, px, pt).
Element's border style (e.g. dotted, dashed, solid).
Element's border color (e.g. red, blue, #80ab80).


4.1.4. Other common HTML tags

HTML link.
Target location within a page.
Image.
Video element.
Audio element.
<input type="text"
       name=NAME
       value=VALUE> 
Text input field, having its initial content set to VALUE.
<input type="button" 
       value=VALUE> 
Button, having its label set to VALUE.


4.2. Layout (JXML)

<lines>
Item1 <> Item2 <> ... 
</lines>
List of items, laid out as a list of lines.
<columns>
Item1 <> Item2 <> ... 
</columns>
List of items, laid out in columns.
<superpose current=POS> 
Item1 <> Item2 <> ...
</superpose>
Set of several items, with only the one at position POS displayed at a given time.


4.3. Displaying objects
JXML markup elements can have a content which is given as markup, but they can also display data (i.e. Javascript objects).

This is done by means of setting the value of the value attribute of an element, which can be given as a string containing a JSON expression (the <lines> and <columns> tags are the only JXML elements which work this way at the moment). For example, the following markup:
<lines border="1" value='["Item1","Item2","Item3"]'/>

is displayed as:
Item1 
Item2
Item3

More complex Javascript objects can also be displayed, for example the following <lines> element:
<lines border="1" value='[{ "":"person", Name:"Lennon", FName:"John" },{ "":"song", Title:"Imagine", Genre:"Rock", Year:1971 }]'/>

is displayed as:
{ "":"person", Name:"Lennon", FName:"John" }
{ "":"song", Title:"Imagine", Genre:"Rock", Year:1971 } 

Arrived here, we would like to be able to not only display our Javascript elements as JSON values, but also to have a way to customize the display of these Javascript elements. This is the purpose of the skins that exist in JXML, and can be attached to the kind of data-displaying JXML tags that we are currently describing.

Such skins enable to, given a set of Javascript classes, for each one of these classes, define a shape, which contains informations that are used to redefine various aspects of the behaviour of the elements of this class (especially, how the elements of a given Javascript class should be displayed). For example, the following skin:
defines a way of displaying the Javascript objects of the classes "person" and "song". Let's now extend the markup given in our previous example, by means of adding a skin attribute that refers to the skin above:
<lines border="1" skin="skin1" value='[{ "":"person", Name:"Lennon", FName:John },{ "":"song", Title:"Imagine", Genre:"Rock", Year:1971 }]'/>

Our modified <lines> element is now displayed as:
John Lennon
Rock
Imagine (1971) 


4.4. Queries
In Section 3 above, we saw how to query a small database made of a set of CSV files by means of a local jix command (which, used in this way, is in fact directly accessing the files, just like, for example the UNIX grep does).

But to be able to access the data in a remote way, we need to do something else, namely to start a server that enables people to access the data from outside. The JIX system includes a little web/data server that provides a simple way to do this. For example, if the machine where the data files are located has the domain name jix-software.com, and if our data files are located in /home/henri/mwiki in the local filesystem:
then we can start jix as a server on the port 8081 by means of the following command:
From there, it is now possible to query the database thru the internet from another machine by means of a jix db command, as we did before. For example:
Once our data are exported by a server in this way, it is possible to access them from inside a JXML page in the browser. To do this, we must first connect to the server, by means of declaring a JXML variable that refers to it. For example:
Overall, in this case we use this variable to refer to the location where the data are stored, i.e. we use it as something that acts as a container for these data. With such a container, we can perform queries that fetch data from this container, in a way that is in essence the same as what we did with the command jix db fetch in the example above.

Performing queries inside JXML is done by means of setting the src attribute of one of the data-displaying JXML tags described in Section 4.3 above to the name of the container we want to query, and of setting its value attribute with a string that contains the query. For example:

is displayed as:
{ "":"song", id:0, Title:"Yesterday", Genre:"Rock", ... } 
{ "":"song", id:1, Title:"Imagine", Genre:"Rock", ... }
...

Let's add a skin to the <lines> element above:
We now obtain:
Yesterday (1965) 
Imagine (1971)
...


4.5. Events
In JXML, markup elements can be made sensitive to events, and turn these events to messages that are finally sent to other elements that act as targets of these messages. Events and messages propagate into the markup in a process called bubbling, namely they propagate from the inner elements to the outer elements, until an element able to process them is found.

This mechanism proceeds in two steps: first, when an event occurs, a markup element that is sensitive to this event must be found. The event is then turned to a message. This relationship is specified by means of setting the events attribute of the appropriate markup elements. The syntax of an events' specification, as given in the events attribute of a JXML element is as follows (in BNF-like notation):

Next, once a given event-sensitive markup element turned an event to a message, this message is emitted at the point in the markup where the initial event appeared. From there, the second step of the bubbling mechanism proceeds, and the emitted message propagates upwards until a markup element which "knows" how to choose the target of the message can be found. The information that is needed to choose the target of the bubbling messages of a certain kind is given by means of setting the targets attribute of the appropriate markup elements. The syntax of a targets' specification, as given in the targets attribute of a JXML element is:

The parameters (denoted by the PARM non-terminal symbols in the first BNF above) that appear in a parameters list can be atomic JIX objects (i.e. of the type int, num or str). Such parameters, along with the targets (denoted by the TARGET non-terminal symbol in the second BNF above) that appear in a target expression can also be JIX objects' references. Additionaly, there are a number of predefined symbols which refer to some of the most salient elements which take part in an event's bubbling process:
"This": the current markup element.
The value of This.
The initial target of an event (i.e., the markup element in the DOM which initially received the event, e.g. the button that initiated the bubbling process when the user clicked on it).
The value of an event's initial target.

To make all this more concrete, we now show how to build a simple form, which sends a query to a <lines> element (which will then be loaded with the query's result), by means of a load message (for a complete list of JXML messages, see Appendix B below).

Here is the <lines> element which will be the target of this load message:

The <lines> element above is initially displayed as:

And here is our form, implemented by means of another <lines> element, with its events and targets attributes defined in an appropriate way:

This form, made of two text input fields and of an "OK" button, is initially displayed as:

When, for example, the user edits the input field corresponding to the songs' release year to select all the songs of the year 75 (i.e.: "*75"), and then clicks on the "OK" button to submit:

this button emits a click event, which bubbles until it reaches the containing <lines> element. Since this <lines> element's events attribute says that click events should be turned to load messages having the value of the current markup element (which is the very <lines> element we are talking about) as a parameter, the following load message:

is then emitted, at the level of the button which received the initial click event. The second step of the bubbling process takes place, and this message bubbles until it reaches the containing <lines> element, which has a targets attribute that defines the target of load events (i.e.: we have targets="load:#view1"). The chosen target in this case is the markup element having "view1" as its id, which is the target <lines> element that has been shown in the beginning of the current example. The message is then sent to this target, which becomes:
<lines id="view1" border="1" src="db1"
       value='{ "":"song", Title:"*", Year:"*75" }'> 
...
</lines>

Finally, its value attribute having been redefined, our target <lines> element is redisplayed as:
Wish You Were Here (1975) 
Born to Run (1975)
...


5. Javascript programming
The JIX system is made of a set of orthogonal Javascript libraries which provide an excellent basis to develop modern webapps, especially:
  • A core library to create and manipulate objects ;
  • A widget toolkit which enables doing everything that JXML provides by means of Javascript code, and more ;
  • A persistent layer to store, fetch and synchronize objects by means of containers ;
  • A server library to implement communications between the different parts of a distributed application ;
In the current Section 5, we present the development of JIX applications in Javascript. In Section 5.1 below, we introduce the JIX object system. We then give a tour of the main JIX classes: first, we describe the widgets (Section 5.2), then the containers (Section 5.3), and finally the servers (Section 5.4).


5.1. Objects
The JIX object system enables the programmer to manipulate Javascript objects, which can either be instances of a Javascript primitive datatype, or instances of a JIX datatype. In Section 5.1.1 below, we discuss how the JIX object system deals with objects that are instances of Javascript primitive datatypes, while in Section 5.1.2, we discuss the creation and manipulation of JIX objects.

5.1.1. Primitive datatypes
The primitive datatypes known to JIX are the datatypes bool (booleans), num (numbers), str (strings), array (arrays), obj (objects: the root datatype from which all JIX datatypes inherit), func (functions), and type (type descriptors). The bool, num, str, array, obj and func datatypes are equivalent to the corresponding primitive Javascript datatypes, i.e. Boolean, Number, String, Array, Object and Function, while the type datatype is the datatype of all the JIX type descriptors.

The basic functions available in JIX to manipulate objects are the functions typeOf(), that returns the type descriptor of an object, the functions parse() and serialize(), which convert JSON strings to Javascript objects (and vice-versa), and the setMethod() method, that enables attaching a new method to a given datatype (this method also works on primitive datatypes).

Example 1:
 ⟹ 

Example 2:
 ⟹ 

Example 3:
 ⟹ 

Finally, the JIX type descriptors (i.e. objects of the type type, like num, str, etc.) are also factory functions, namely they can be directly used as constructors (without needing to use the Javascript operator new), for example:
 ⟹ 


5.1.2. JIX objects
The JIX object system also enables the programmer to create new datatypes, by means of the type() datatype constructor, which has the following prototype:
Creates a new datatype that inherits from TYPE, having the name NAME, the description of the additional attributes of this new datatype being given in ATTRS.

The two methods name() and parent() respectively return the name of a datatype, and its first parent in the inheritance relation.

Thus we can create a new type person (which corresponds to the person datatype we used in the examples given in Section 3 and below), and then display its name and the name of its parent datatype:
 ⟹ 

Once created, such a datatype can be used to create new instances of itself. When calling the constructor type() to create a datatype τ, the JIX object system automatically creates a polymorphic constructor τ() for this newly created datatype which has the following prototype:
Creates a new instance of τ having the attributes given in the object OBJ. When the type τ inherits from a Javascript atomic datatype, a value VAL of this type must be given to initialize the newly created object.

For example, to create a new objet of the type person we can do:
Here is a more complex example, which illustrates how to create composite objects made of objects that belong to different datatypes (i.e. an object of the type song corresponding to the song datatype we used in the examples given in Section 3 and below, which contains objects of the class person in its Authors attribute), along with some of the options of the serialize() method to handle these kinds of objects:
 ⟹ 

Finally, composite objects can be parsed by means of the function parse() ; the example below also illustrates how to fetch objects from memory by means of their id using the method getById():
 ⟹ 


5.2. Widgets
The JIX system provides widgets, that all inherit from the datatype widget. Such widgets can be attached to any browser's DOM element by means of the method attach() of the dom datatype, which is the JIX datatype that enables manipulating DOM elements.

Moreover, to make constructing composite XML-like objects more convenient, the type() datatype constructor also supports datatype descriptions having an optional array-like part (created by means of defining the "$" attribute) ; in that case, the constructor τ() of such a given JIX datatype τ has the following prototype:
Creates a new instance of τ having the attributes given in the object OBJ, and optionally, having its array-like part containing the objects given in the array of objects LOBJ.

For example, to represent HTML <div> tags, a (rather incomplete) JIX widget datatype could be defined as follows:

Then, to create an HTML <div> tag having its name attribute equal to "div1", containing the three text elements "a", "b" and "c", we could do:

And to fetch the page's <body> tag, and to attach the DIV1 widget to it, we can do:

Here is a more complex code snippet, that shows how to implement a simplified version of the last example given in section Section 4.3 directly in Javascript:

Finally, to enable representing markup as a pure Javascript datastructure, rather than as a Javascript expression containing constructor calls, the markup() function enables turning a Javascript array representing a chunk of markup to the corresponding JIX widget. Such a Javascript array representing a chunk of markup should have the following syntax:

Above, the TAG parameter should be a JIX datatype (i.e., an instance of the type datatype), the ATTRS and ELTS parameters are both optional, ATTRS should be a composite object (i.e. a pure attribute-value list), while ELTS should be an array containing elements having the datatype widget or str.

The previous example can then be rewritten as follows by means of two single calls to the markup() function:

The instances of datatypes that inherit from the widget datatype have attributes that directly map to those of the corresponding HTML/JXML tags, and thus, have the same names. A subset of the HTML tags' attributes is available (e.g. id, name, class, style, etc.), plus the additional attributes that JXML provides (especially events, targets and value, and a bunch of others, like title or current, for example).

The following example shows how to implement a <superpose> JXML tag containing three <div>s and a button that triggers a focus event inside it:

Just after the call to attach() above, our markup is initially displayed as:
Item3 


When the "OK" button is clicked, it becomes:
Item1 



5.3. Containers
The JIX containers are the abstraction by means of which groups of data can be manipulated, loaded from disk and saved to disk. These containers can be queried, and the objects that they contain can be directly modified, copied, moved or deleted.

Here is a simple code snippet, which illustrates how to implement the first example given in Section 3 directly in Javascript. We first open the database by means of the container() constructor, we perform the query by means of the query() method of the container datatype, and then we display the objects that have been fetched by the query:

We obtain:

In the following example, we open the container and first create an object, then we fetch this object by means of its id from the container, and finally display it:

We obtain:

To create the very same object inside the container without performing a query, we could have used the constructor of the type person directly, with an extra parameter to specify the target container:

Or either, we could have used the parse() function, which also can take such an extra parameter that specifies the target container:

To delete objects that belong to a container, we simply use the method delete() that is available for all objects that are instances of a datatype inheriting from obj. In the example below, we delete all the songs having a genre equal to "Rock":

Now, to copy objects, we use the method copy() (without specifying a target container, which means that the copy will be created in memory(), which is the container representing the Javascript memory). The method containerOf() is used below to test to which container the source and target objects respectively belong:

We obtain:

The two objects representing, respectively the author of the first song and the author of its copy, are in fact the same object, i.e., if we do:

We obtain:

In the example above, the copy() method performs only a flat copy, thus the instance of the person datatype representing the author of the song is not copied. It is possible to obtain a full recursive copy by means of specifying a traversal mode when calling copy() (see Appendix A.1 for the definition of the available traversal modes). In the example below, we create a new author and a new song, we perform a full recursive copy of this song, and then we display a number of things to show the difference:

We can now see that the copy() method duplicated the object representing the song, but also the object representing the author:

To move objects, we use the method move(). The move() operation is roughly equivalent to a copy() followed by a delete(). When the method delete() is called on an object, this object does not immediately disappears, it is only scheduled for deletion (so the object remains, but its behaviour changes, for example, such objects can still be read, but can not be fetched by queries) ; the method isDeleted() may be used to know if an object is scheduled for deletion. The example below performs a copy of an object, then it moves this object, and it performs a number of outputs to show what happens:

We obtain:

Finally, to save the modifications to disk, we use the method sync():


5.4. Servers
The JIX system provides a server datatype to implement servers (and the corresponding clients) that can handle the communications between the different parts of an application across a network. These servers enable implementing remote procedure calls on the one hand, and access to remote data on the other hand. In this section, we cover these two topics in turn.

5.4.1. Remote procedure calls
A JIX server is able to receive messages on a given port, and these messages are remote procedure calls. In most of the cases, JIX servers are able to deal automatically with the process of serialization/deserialization of the data they exchange with the caller.

Here is a simple example of a server and of its corresponding client. The server (implemented by means of a Javascript file named "srv1.js") is as follows:

And here is the client (implemented by means of a Javascript file named "cli1.js"):

Let's try, now. First we start the server:

And now we run the client:

The terminal from which we started the server becomes:


5.4.2. Containers & access to remote data
The JIX containers are the abstraction by means of which groups of data can be mapped from one memory area to another. To this end, containers can be derived from one another, including across a network. On the one hand, a derived container behaves as a cache with respect to the container it is derived from, and on the other hand, when the data located in a derived container have been modified, the modifications can be propagated to the containers it is derived from by means of the sync() method.

Here is a simple example, which illustrates how to create two containers, the second one being derived from the first one, how to query the second container and modify the data that has been fetched from the first container, and finally how to synchronize the two containers:

We obtain:

We now show a more elaborated example featuring a simple server that enables the little database we used in Section 3 above to be accessed in a remote manner, and a web page containing Javascript code that creates a <lines> JXML tag that performs a query to this database and displays the data by means of the appropriate skin. The code of the server is given below:

The code of the corresponding web page is:


6. Applications
In this section, we describe the command-line tools provided by the JIX system to manage a project on the one hand, and the installation procedure of the JIX system itself on the other hand. We will now cover these two topics in turn.

6.1. Command-line tools
The JIX command line tools provide means to run applications in a test environment, to compile them, to package tarballs, and to install applications.

The basic directory layout of a JIX application is as follows:
bin/ Binaries. This folder contains the binaries that can exist in a given project, either those that are called by the Javascript, or tools that are necessary to administer the application.
build/ Built project. This folder contains the files the working project is made of, especially the HTML files, the images, the CSS files, and the minified .js files.
src/ Sources. This folder contains the source code of the project (JXML and HTML files, Javascript and JIX files, especially).
data/ Data. This folder contains the persistent data that come together with the application (various kinds of files that can be accessed by the Javascript, or database files).
LICENSE License. This file contains the license under which the project is released.
README Readme. This file is the traditional README file that may come together with a project.

The JIX command line tools are all available via the jix command. The table below describes its most common options:
The db option enables querying a JIX local or remote container. With fetch, one can perform reads, while with update, one can perform writes.
The server option enables starting a server on the port PORT, which provides access to the JIX container located in the DIR directory of the local filesystem.
The build option enables compiling a given JIX project, located in the DIR directory. When the src/ directory exists, the compilation starts from there, otherwise it proceeds directly from the directory DIR. The JXML and JIX files are respectively compiled to HTML and Javascript, and all the compiled files are copied to build/.
The clean option deletes all compiled files, and empties the build/ directory if it exists.
The run option enables to either start the application, or to run a given Javascript file.
The release option creates a source tarball of the application, or creates a copy of the application with all its source code (i.e., the source code as such, but also files like LICENSE, README, etc.).
The install option installs the application in the directory DIR, i.e. it copies the content of the build/ folder to a place where it can be made active (e.g., somewhere in one of the folders containing files that are served by a webserver like Apache).


6.2. Installation
The installation procedure is minimally simple:
  • Linux: you should be logged in as root or either use sudo, and launch install.sh. Then, the jix command will be copied in /usr/bin, and the jix folder containing the JIX distribution will be created in /share ;
  • Windows: you should be logged in as Administrator or under an account having the appropriate rights, and launch install.bat. Then, the jix folder containing the JIX distribution will be created in C:\Program Files, and "C:\Program Files\jix" will be added to the PATH environment variable ;
The JIX distribution has the following structure:
bin/ Binaries. The binaries that come with the JIX system (especially, those that constitute the command-line tools, e.g. the jix command).
src/ Sources. The source code of all the JIX packages, especially objects, containers, servers and widgets.
doc/ Documentation. The JIX documentation, including for example the current manual.
LICENSE License. The JIX license.
README The JIX Readme. A short and easy to read text file that summarizes the content and purpose of the current JIX distribution.
install.sh Linux installer. The Linux JIX installer.
install.bat Windows installer. The Windows JIX installer.


7. Conclusion
With JIX, we have a toolkit which is first of all based on a set of well-established, mature standards (HTML5, CSS and Javascript), and next, which provides a set of combinable components to build applications. This makes lightweight, modular software easier to develop, and enables an incremental style of development in which design and implementation can be meshed. Thus, ideally, at any time in the development process, the developers should remain able to continue refining the design, rather than being forced to freeze it early due to rigidities stemming from implementation concerns.

As far as we know, such problematic implementation concerns are primarily of two kinds: (1) an excessive complexity of the underlying software and tooling ; (2) a lack of elegance in the overall software's architecture. There is of course no magic receipt that would enable developers to address these issues without investing the appropriate amount of creative effort: that's why they are all the more important and indeed, are relatively well-known. Especially:
  • Simplicity is in fact a very important feature of a given software's implementation: « Reducing complexity and size must be the goal in every step – in system specification, design, and in detailed programming. » (Niklaus Wirth, "A Plea for Lean Software", 1995).
        Conversely, the loss of overall understanding that arises when overall software's complexity becomes excessive is a well-known factor in the failure of software projects: « Interestingly, prior studies have recognized, but not emphasized, the central role of implementation and software testing in causing software project failures. [...] The [problematic] products were complex and required extensive technical knowledge. [...] In three cases, the participants noticed that the existing product was so complex that it was likely that nobody knew the system fully. » (Lehtinen et al., "Perceived causes of software project failures – An analysis of their relationships", 2014) ;
  • Elegance is not an option, but a key property of software implementations: « How do we convince people that in programming simplicity and clarity – in short: what mathematicians call "elegance" – are not a dispensable luxury, but a crucial matter that decides between success and failure? » (Edsger W. Dijkstra – "Why is software so expensive?", 1982) ;
  • There's no magic receipt, because programming remains an art: « we have actually succeeded in making our discipline a science, and in a remarkably simple way: merely by deciding to call it "computer science." [...] if we don't fully understand something, it is an art to deal with it. [...] The mysterious insights that people have when [...] they are programming, are still beyond the reach of science; nearly everything we do is still an art. » (Donald Knuth – "Computer Programming as an Art", 1974 ACM Turing Award Lecture) ;
We believe that the overall philosophy of JIX, along with its design, provide a genuine (although unavoidably imperfect) answer to alleviate these problems, that is, JIX is a tool from which on the one hand, as much complexity as possible has been banned, while nevertheless (thanks to the maturity of the current standards) remaining complete enough to enable the development of interesting applications, and which, on the other hand, is well-architected enough to be easy to extend in case the needed functionalities are not natively provided.

Happy hacking !


Appendix A. The JIX APIs

A.1. Objects

Types (class type):
Constructor. Creates a new type, having name NAME, inheriting from the type TYPE, the instances of this type having the attributes ATTRS.
Function. Tests if the object O is of the type type.
Class method. Returns the type having the name NAME.
Method. Returns the name attribute of the type T.
Method. Returns the parent type of the type T.
Method. Tests if the type T inherits TYPE.
Method. Returns the list of attribute descriptors of the type T.
Method. Returns the attribute descriptor of the type T having the name NAME.
Method. Sets the attribute descriptor of the type T having the name NAME to the attribute descriptor ATTR
Method. Returns the method of the type T having the name NAME.
Method. Sets the method of the type T having the name NAME to the method FUNC.

Objects (class obj):
Constructor. Creates an object of the type TYPE, having the attributes NAME(i), with values VAL(i), and having its array-like part containing the elements of the array LOBJ.
Constructor. Creates an object of the type TYPE, having the attributes given in the object ATTRS, and optionally, having its array-like part containing the objects given in the list of objects OBJ(i).
Method. Returns the type of the object O.
Class method. Returns the object having the id ID.
Method. Creates a copy of the object O in the container CONT (if CONT is omitted, the default value is the Javascript memory). The traversal mode MODE is used (the possible values are "flat" and "full").
Method. Moves the object O in the container CONT (if CONT is omitted, the default value is the Javascript memory). The traversal mode MODE is used (the possible values are "flat" and "full").
Method. Parses the string S. The result is created in the container CONT.
Method. Serializes the object O. The traversal mode MODE is used (the possible values are "flat", "flat*", and "full").
Method. Returns the container of the object O.
Destructor. Deletes the object O. The object O does not immediately disappears, it is only scheduled for deletion.

Objects (wrapper functions that can be called with the main parameter being an unboxed javascript value):
Constructor. create() <=> obj().
Function. Creates a boxed value of the object O. There are boxed values for objects of the types nil, bool, num or str, otherwise the boxed value of a given object O is equal to O. Due to the limitations of the Javascript object system, the boxed values of Nil and Undefined are not equivalent to Nil and Undefined.
Function. Returns the type of the object O.
Function. Tests if the type of the object O inherits from the datatype TYPE.
Function. Creates a copy of the object O in the container CONT (if CONT is omitted, the default value is the Javascript memory). The traversal mode MODE is used (the possible values are "flat" and "full").
Function. Moves the object O in the container CONT (if CONT is omitted, the default value is the Javascript memory). The traversal mode MODE is used (the possible values are "flat" and "full").
Function. Parses the string S. The result is created in the container CONT.
Function. Serializes the object O. The traversal mode MODE is used (the possible values are "flat", "flat*", and "full").
Destructor. Deletes the object O. The object O does not immediately disappears, it is only scheduled for deletion.

Predefined constants:
Type. This datatype has only two instances, which are Nil and Undefined.
Constant. Undefined = undefined
Function. isDefined(O) <=> O!==Undefined.
Function. isUndefined(O) <=> O===Undefined.
Constant. Nil = null
Function. Tests if the object O is of the type nil.
Constant. True = true
Constant. False = false
Function. Tests if the object O is of the type bool.

Objects (miscellaneous):
Function. Tests if the object O has been scheduled for deletion.
Function. Tests if the object O is an atom (i.e., if O is of the type nil, bool, num or str).
Function. Tests if the object O is a boxed object.
Function. isObject(O) <=> isBoxed(O)
Function. Tests if the object O is of the type func.
Function. Tests if the object O is a Javascript method. All methods are functions, but not all functions are methods.

Numbers (class num):
Constructor. When O is a string, num(O) <=> parse(O) ; when O is a number, num(O) <=> copy(O).
Function. Tests if the object O is of the type num.

Arrays & strings:
Function. Tests if O is empty (i.e. its length equals zero).
Function. Returns the length of the object O.
Function. Tests if the object O contains the part PART.
Function. Returns the first element of O.
Function. Returns the last element of O.

Strings (class str):
Constructor. When O is a string, str(O) <=> copy(O) ; otherwise, str(O) <=> serialize(O).
Function. Tests if the object O is of the type str.
Method. Tests if PREF is a prefix of the string S.
Method. Tests if SUFF is a suffix of the string S.
Method. Tests if the string S matches the pattern PATTERN.
Method. Returns the substring of S located between the indexs I and J (not including the character located at position J).
Method. Returns the trimmed version of the string S, eliminating all the characters contained in CHARS. When LEFT, the string is left-trimmed, and when RIGHT, the string is right-trimmed. The default value of LEFT and RIGHT is True.
Method. Returns the lowercase version of the string S.
Method. Returns the uppercase version of the string S.
Method. Returns a version of the string S where the first occurence of the substring S1 has been replaced by the string S2.
Method. Returns a version of the string S where all occurences of the substring S1 have been replaced by the string S2.
Method. Splits the string S using SEP as the separator.

Arrays (class array):
Constructor. Creates a new array of N elements, each equal to VAL.
Function. Tests if the object O is of the type array.
Method. Adds the object OBJ at the end of the array A.
Method. Removes the last element of the array A, and returns it.
Method. Removes the first element of the array A, and returns it.
Method. Adds the object OBJ at the beginning of the array A.
Method. Inserts the elements contained in the list of elements [OBJ] into the array A at the position I, after having deleted NDEL elements at this position.

JIX:
Object. The object representing the JIX module in Javascript. This object is always available by means of a global variable having the name jix.
Function. The JIX module's initialization function.


A.2. Servers

Servers: (class server)
Constructor. Creates a server listening to the port PORT, serving the API API. The server is not started.
Constructor. Connects to a remote server located at url URL.
Function. Tests if the object O is of the type server.
Method. Tests if the object O is a connection to a remote server.
Method. Tests if the object O is a local server.
Method. Performs a procedure call to the remote server SRV, calling the function having the name NAME, with the list of parameters PARMS.
Method. Starts the local server SRV.
Method. Stops the local server SRV.

APIs (class api):
Constructor. Creates an API made of the functions FUNC(i), available under the names NAME(i).
Function. Tests if the object O is of the type api.


A.3. Containers

Containers: (class container)
Constructor. Creates a container having the name NAME, optionally attached to the server SRV.
Constructor. Creates a container backed by the data located at the position FNAME on the disk, having the category CATEG, which is optionally attached to the server SRV. The name of the created container is the name of the file or directory located at the position FNAME.
Constructor. Creates a derived container of the container CONT, optionally attached to the server SRV.
Function. Tests if the object O is of the type container.
Method. Returns the parent container of the container CONT (i.e., the container it is derived from, if any).
Method. Queries the container CONT using the query created by means of applying its parameters to the constructor of the datatype query.
Method. Creates a copy of the object O in the container CONT. The traversal mode MODE is used (the possible values are "flat" and "full").
Method. Moves the object O in the container CONT. The traversal mode MODE is used (the possible values are "flat" and "full").
Method. Propagates the changes that have been performed on the objects which belong to the container CONT to the containers it is derived from, and in the same time, fetches all the changes that have been performed on the objects which belong to the containers it is derived from.

Queries (class query):
Constructor. Creates a query, the list of its result variables being provided in VARS, the code of the query itself being represented by the object OBJ.
Function. Tests if the object O is of the type query.

Servers: (container-related methods)
Method. Returns the list of the containers that are attached to the server SRV.
Method. Returns the attached container having the name NAME in the server SRV.


A.4. Widgets, wobjets and skins

Widgets (class widget):
Constructor. Creates a widget of the type TYPE (which must inherit from the datatype widget), having the attributes given in the object ATTRS, and optionally, having its array-like part containing the objects given in the list of objects OBJ(i).
Function. Tests if the object O is of the type widget.
Method. Returns the DOM-translated part of the widget W.
Method. Returns the width of the widget W.
Method. Sets the width of the widget W to the value W2.
Method. Returns the height of the widget W.
Method. Sets the height of the widget W to the value H.
Method. Returns the parent of the widget W.
Method. Returns the list of the children of the widget W.
Method. Returns the widget that comes before the widget W in the list of the children of the parent of the widget W.
Method. Returns the widget that comes after the widget W in the list of the children of the parent of the widget W.
Method. Sends a focus message to the widget W.
Method. Returns the skin of the widget W (if any).
Method. Sets the skin of the widget W to the value SK.
Method. Returns the value of the mode attribute of the widget W.
Method. Sets the mode attribute of the widget W to the value MODE.
Method. Returns the source container of the widget W.
Method. Sets the source container of the widget W to CONT, which must be a container.
Method. Sends a load message to the widget W. The value attribute of the widget W is set to the value VALUE, which must either be a Javascript object or an instance of the query datatype.
Method. Sends a save message to the widget W. The current editing changes are collected and applied to the data located inside W, and the source container of W (if any) is then synchronized.

DOM elements (class dom):
Class method. Returns the DOM element having its id attribute equal to ID.
Class method. Returns the DOM elements having their tag name equal to NAME.
Function. Tests if the object O is of the type dom.
Method. Returns the browser's DOM element corresponding to the DOM element DOM.
Method. Attaches the widget W to the DOM element DOM.

Widgets (constructors):
Constructor. markup() <=> widget().
Constructors. Constructors for HTML markup elements.
Function. Tests if the object O is an HTML element.
Constructor. Creates a <lines> JXML element.
Constructor. Creates a <columns> JXML element.
Constructor. Creates a <superpose> JXML element.
Function. Tests if the object O is a JXML element.
Constructor. Creates a <skin> JXML element.
Function. Tests if the object O is of the type skin.


Appendix B. JXML Events and messages

Events:
Left click.
Right click.
(Left) double click.
Mouse over.
Left arrow key.
Right arrow key.
Down arrow key.
Up arrow key.
Carriage return.
Keyboard event emitted when the key having the character CHAR is pressed.

Messages:
The element becomes focussed, i.e., it goes on top, and it becomes the element of the page having the cursor.
The mode attribute of a skin-enabled data-displaying element is set to MODE. The element is redisplayed.
The value attribute of a data-displaying element is set to a Javascript data, or either to a Javascript object representing a query. The element's content is reloaded, and redisplayed.
The element's content is saved.



About JIX
Services
Download
Manual
Contact