Tutorial: creating editable web pages with AXEL

By S. Sire, Oppidoc, (Last edited 2013-08-21)

This document describes the new API (since AXEL 1.3.2) to generate document editors inside web application pages and to interact with the editors to load and save XML data. This API is based on a $axel object, it supersedes the legacy API based on the xtiger.util.form object.

The $axel object is a wrapper function that takes a node set specification and returns a wrapped set object supporting several functions that act on the first element (or on all elements) of the node set. This tutorial presents the transform, load and save functions that act on the first element of the wrapped set to respectively generate an editor, load XML data into it, and serialize XML data from it.

It is very convenient to use the $axel object together with the jQuery library since you can then directly pass a node set specification as a jQuery selector string or as a jQuery wrapped set. You can still use the $axel object without jQuery if you pass it directly DOM node(s) to interact with. For latest information about the $axel object and for a description of other wrapped set functionalities you may consult its wiki page.

Step 1 : write an XTiger XML template

Follow the XTiger XML specification. You can use the Template.xhtml provided with the distribution as a skeleton (show source). For a quick introduction to XTiger XML you may also have a look at this executive summary.

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
  "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

  <html xmlns="http://www.w3.org/1999/xhtml"
        xmlns:xt="http://ns.inria.org/xtiger">
  <head>
    <!-- Use UTF-8 and omit xml protocol at the top for IE -->
    <meta http-equiv="content-type" content="text/html; charset=UTF-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge" />

    <title>XTiger XML with AXEL tutorial</title>

    <xt:head version="1.1" templateVersion="1.0" label="greetings">
      <xt:component name="personList">
        <ul>
          <xt:repeat minOccurs="0" maxOccurs="*" label="persons">
            <li>
              <xt:use types="text" param="shape=parent-75px;type=textarea"
                 label="name">name</xt:use><xt:menu-marker/>
            </li>
          </xt:repeat>
        </ul>
      </xt:component>
    </xt:head>

    <!-- See Step 2 -->

  </head>
  <body>
    <div id="document">
        <p class="template">Template directly embedded within this page</p>
        <p>List of persons to great:</p>

        <xt:use types="personList"/>
    </div>
  </body>
  </html>

show explanation

The best compromise to be able to open your Web page in standard compliant browsers AND in Internet Explorer is to save the file as UTF-8 and to omit the xml protocol declaration (i.e. <?xml version="1.0" encoding="UTF-8"?>). So the file should start directly with an XHTML DOCTYPE declaration. It is recommended to read the HTML Compatibility Guidelines from the XHTML 1.0 Recommendation before writing template files. You may also use the XHTML syntax of HTML5.

It is wised to specify the content-type with a meta element, this improves MIME-Type sniffing when opening the file directly from a local file system on Internet Explorer. If you access the file from a Web server, you should serve it with a MIME TYPE set to application/xhtml+xml, except for Internet Explorer that only supports text/html when the template is also the Web page (variant a in Step 3). Eventually you can specify Microsoft X-UA-Compatible property to tell Internet Explorer to open the page in a specific mode, currently AXEL works with IE starting from 7, and on all other major browsers (at least Firefox, Safari, Chrome, Opera).

Step 2 : include AXEL library inside your web application page

You need to include both the axel.js file containing the library and the corresponding axel.css file. In addition the bundles path of the AXEL distribution must be avalaible on your server (show source)

<script type="text/javascript" src="{PATH-TO}/axel/axel.js"></script>
<link rel="stylesheet" href="{PATH-TO}/axel/axel.css" type="text/css"></link>
  

show explanation

The src attribute of the script element must point to the location where you have copied the AXEL library file axel.js which is distributed inside the axel/ folder.

You must include the global AXEL CSS file axel.css which is distributed under the same axel/ folder (excepted if you are applying variant C of step 3).

Finally you also must make the axel/bundles/ folder of the AXEL distribution available and provide a bundlesPath parameter to the $axel.setup function with a string path (relative to your web application page) leading to the bundles folder of the AXEL distribution.

You can generate a new AXEL library file with your own selection of plugins by editing the scripts/build.xml file and with a build.lib target with ant (cd scripts; ant build.lib). This supposes you have installed the Yahoo UI compressor and set its path into the javascript.compressor variable in the file scripts/ant.properties. Otherwise you may generate an uncompressed version of the library with the ant build.debug target.

Step 3 : write the template transformation code inside your web application page

Variant a : your web page is also the XTiger XML template page

The div below contains some XTiger XML declarations which have been transformed immediately after page loading through a registered load event handler (show source). Consequently you can edit a list of persons :

Template self-contained into this page

List of persons to great:

To generate the editor defined in the <div id="embedded"> element in a web application page that is also an XTiger XML template, you can write :

    <script type="text/javascript">
      function init() {
        var n = document.getElementById('embedded');
        $axel.setup({ bundlesPath : '{PATH-TO}/axel/bundles', enableTabGroupNavigation: true });
        $axel(n).transform();
      }
      xtdom.addEventListener(window, 'load', init, false);
    </script>

Alternatively if you have included jQuery inside your web page, you can directly pass a jQuery selector string to the $axel object :

    <script type="text/javascript">
      function initApp() {
        $axel.setup({ bundlesPath : '{PATH-TO}/axel/bundles', enableTabGroupNavigation: true });
        $axel('#embedded').transform();
      }
      jQuery(function() { initApp(); });
    </script>

Note that if you want to treat the whole page as a single editor, you can directly pass the document object to the $axel object such as :

$axel(document).transform()

You can also directly pass the AXEL setup as an option hash to the transform method :

$axel('#embedded').transform({ bundlesPath : '{PATH-TO}/axel/bundles', enableTabGroupNavigation: true })

show explanation

You can call the $axel.setup function in a page load event handler or right before generating an editor. Note that you can also initialize some other globals by the same occasion, such as enableTabGroupNavigation to enable tab navigation between editor's fields, however this functionality is not yet fully functional on all browsers. The settings are memorized so that you just need to set them once even if you use the $axel object multiple times.

Note that the xtdom.addEventListener function is an AXEL function to register event handlers, you may of course use any other function, especially since that function may be deprecated in the future.

Variant b : your web page contains a div that you fill with an external XTiger XML template

Click to load and transform the external Hello-world.xhtml XTiger XML template into the div below (show source) :

Template dynamically loaded with Ajax

To generate the editor defined by the "Hello-world.xhtml" template inside the <div id="placeholder"> element of a web application page, you can write :

$axel('#placeholder').transform('Hello-world.xhtml')

Once again you can also directly pass the AXEL setup as an auxiliary option hash to the transform method :

$axel('#placeholder').transform('Hello-world.xhtml', { bundlesPath : '{PATH-TO}/axel/bundles', 
      enableTabGroupNavigation: true })

show explanation

By passing a string to the transform function you instruct the $axel object to first retrieve an XTiger XML document at the URL/path specified by the string, and then to transform it and to copy the result of the transformation inside the first element of the wrapped set passed to the $axel object.

The URL/path string is passed to an internal xtiger.cross.loadDocument function to retrieve the XTiger XML document. It uses an XHR object in synchronous mode. Alternatively you can use your own function to first load the XTiger XML document. In that case you just need to pass the resulting XML Document object (typically your own xhr.responseXML if you are using XHR) to the transform function instead of a URL/path string.

Variant c : your web page contains an iframe that contains an external XTiger XML template

Click to transform the XTiger XML template inside the iframe below into an editor (show source) :

Template inside an iframe