Chapter 55. The Backwards Transformation: From Reference Page to Source

Table of Contents

1. Page Header
2. A Live Example
2.1. Element H: The embedded OpenLaszlo application
2.2. Element I: The program listing
2.3. Element J: The edit button
3. The Attributes Table
4. Method Details

In this chapter, we will show where several elements on the end product reference page can be traced back to their origins in the sources.

[Note] Note

At this point we strongly, strongly encourage the reader to undergo an investigation of XPath 1.0 and to find an XML editor which is capable of doing live XPath queries. (Oxygen XML Editor works.) Then, actually run some queries on a js2doc dataset. Without this exercise, the remainder of this chapter will be utter gobbledygook.

1. Page Header

Figure 55.1. Page Header

Page Header

Region Docbook Element Relevant Templates js2doc Element
A header navigation parameters.xsl: navig.showtitles, suppress.header.navigation -
B <refentry xreflabel="<text>" id="LzText" ...> <xsl:template match="property" mode="refentry"> ("main class template") <property id="LzText" name="LzText" .../>
C header navigation parameters.xsl: navig.showtitles, suppress.header.navigation -
D <refsynopsisdiv> js2doc2dbk.xsl: insert-refinfo  
E <refsect1> js2doc2dbk.xsl: generated in main class template  
F <refpurpose> js2doc2dbk.xsl: generated in main class template  

2. A Live Example

Figure 55.2. A Live Example

A Live Example

All of the elements in the live example are contained within a <div class="informalexample"> (in html) which comes from a <informalexample role="live-example"> docbook element. That, in turn, comes from an <example> in the js2doc, which appears as something that matches this XPath query: "/js2doc/property/doc/text/example". All the way back in the source (WEB-INF/lps/lfc/views/LzText.lzs, in this case), here's what this started out as:

/**
  * <p>This class is used for non-editable text fields (as opposed to
  * <tagname>inputtext</tagname>.  A text field can be initalized
  * with text content at compile time.</p>
  * 
  * <example>
  * &lt;canvas height="30"&gt;
  *   &lt;text&gt;Hello world!&lt;/text&gt;
  * &lt;/canvas&gt;
  * </example>
  ... */

Many, many templates are involved in generating the inside of that live example. This is so complicated that we'll leave the table format used above, and instead break it down element by element, in excruciating detail.

2.1. Element H: The embedded OpenLaszlo application

In the output HTML, there's just a little script here:

<div class="embedded-canvas">
    <script language="JavaScript" type="text/javascript">
        lz.embed.swf({url: 'programs/LFC-$10.lzx?lzt=swf', id: 'd0e165236SWF',
                        history: false, width: 500, height: 30
    });
    </script>
</div>

The lz.embed.swf function is defined in embed-compressed.js, which is included in the page's head. The embed-compressed.js file comes from $LPS_HOME/lps/includes/embed-compressed.js, and calling lz.embed.swf generates an embedded flash player:

<div id="d0e165236SWFContainer" style="width: 500px; height: 30px;">
    <embed id="d0e165236SWF" width="500" height="30" align="middle" pluginspage="http://www.macromedia.com/go/getflashplayer"
        type="application/x-shockwave-flash" allowscriptaccess="sameDomain" swliveconnect="true"
        flashvars="lzt=swf&lzr=swf8&id=d0e165236SWF" name="d0e165236SWF" wmode="window"
        bgcolor="#ffffff" quality="high" src="programs/LFC-$10.lzx?lzt=swf&lzr=swf8"/>
</div>

The highlighted section above is the important part; it tells the flash player what content to load. In this case, it's loading the results of an http query programs/LFC-$10.lzx?lzt=swf&lzr=swf8, which, if you remember your OpenLaszlo query args, means compile the program named programs/LFC-$10.lzx for the swf8 runtime and return it as a compiled object, with no wrapper.

The file programs/LFC-$10.lzx contains just exactly the code that was in the <example> tag in the lzs source. Somehow, probably in dbkpreprocessexamples.xsl, the contents of the <example> tag were extracted and tucked away in docs/src/build/developers/programs/LFC-$10.lzx, and then that file was copied from the build directory to the output directory, as docs/developers/programs/LFC-$10.lzx.

lz.embed.swf was inserted by a template in common-html.xsl: <xsl:template match="programlisting[@language='lzx' and textobject/textdata/@fileref]">. This template both embeds the live example and handles the program listing and edit button, described below.

2.2. Element I: The program listing

The program listing seems like it should be simple, but notice that it's pretty-printed. The html output here looks like this:

<pre class="programlisting">
  <span>
    <span class="markup">&lt;</span>
      <code class="sgmltag-element">canvas</code>
      <code class="sgmltag-attribute">height</code>="
      <code class="sgmltag-attvalue">30</code>"
      <span class="markup">&gt;</span>

Notice that this sgmltag stuff isn't present in the lfcref.dbk intermediate file; it must be inserted by the docbook processing itself. Indeed, it is inserted by the docbook customization layer, in the lzx-pretty-print.xsl worksheet, which is included by common-html.xsl, which is in turn invoked in the ant task, book.html.generate.

2.3. Element J: The edit button

The edit button ties together a few separate threads of complexity. The windows builds, in particular, are subject to troubles here. The edit button must point an external jsp (editor.jsp) at the program file associated with this program listing. We leave the details of this as an exercise to the reader, except to note that the insertion of the edit button is guarded by the statement <xsl:if test="$live"> which in turn consults the value of a variable computed like this:

<xsl:variable name="live" select="ancestor::example[@role='live-example'] or 
    ancestor::informalexample[@role='live-example']"/>

Remember the docbook element that we found in the docbook intermediate file? <informalexample role="live-example"> matches the second option in the XPath query for $live above, and that's why this example is live.

3. The Attributes Table

Figure 55.3. The Attributes Table

The Attributes Table

The attributes table is generated by a set of coherent templates and patterns. There's a lot of them, but they're not very complicated. It is all run by this template, in js2doc2dbk.xsl:

<xsl:template match="property" mode="refentry-details">

This template calls the describe-members template repeatedly with different parameters, depending on which kind of members are being described. For the attributes table, the describe-members template calls the describe-members-grid template, which generates a <refsect2> element, which in turn generates the "Attributes" header indicated in region P. Region Q is the <thead> element of a docbook <informaltable>, and regions R, S, and T are each instances of the docbook element <row> Each row (regions R, S, T) in the attributes table are elements of the result of this XPath, which is passed in as the members parameter to describe-members-grid:

$ivars[not &isevent;] | $svars[not &isevent;]

$ivars is a local variable containing descriptions of the instance variables for the current class:

<xsl:variable name="ivars" select="&objectvalue;/property[@name='__ivars__']/object/property[&isvisible;]"/>

and $svars is a local variable containing descriptions of the "setters" for the current class:

<xsl:variable name="svars" select="&objectvalue;/property[@name='setters']/object/property[&isvisible;]"/>

The value of these variables is a result tree fragment; it's not just the name of the variables. This becomes important when we descend into the describe-members template.

[Note] Note

Review the table in Section 3.2, “JavaScript to js2doc” to get a feel for why these XPath's return the desired result sets.

This all ends up down in the member-data-row template in js2doc2dbk.xsl, which fill in columns K, L, M, N, and O in the diagram above. Turn to LzText.lzs, to find where these variables were declared:

/**  
  * @lzxtype numberExpression (region L)
  * @modifiers read-only (region O)
  */
  var maxlength; (region K)

4. Method Details

Figure 55.4. Method Details

Method Details

The reference for a function is generated by the call to <xsl:apply-templates select="." mode="describe-member"> in the template named describe-members-list in js2doc2dbk.xsl. select="." mode="desribe-member" means apply whatever templates match the current element in the describe-member mode.

That takes us to the template

<xsl:template match="initarg|property" mode="describe-member">

also in js2doc2dbk.xsl. Dancing through a variety of complex template matching, the XSL ends up examining mostly these elements of the js2doc:

<class extends="LzView" inherits="LzFormatter">
  <property access="private" id="LzText.tagname" name="tagname" value="text"><!-- region 6 -->
    <doc>
      <tag name="modifiers">
        <text>override</text>
      </tag>
    </doc>
  </property>
  ...
  <property id="LzText.prototype" name="prototype" access="public">
    <object>
      <property id="LzText.prototype.format" name="format"<!-- regions 1, 2 --> 
      access="public">
        <doc>
          <text>Formatted output.
            Formats its arguments using <xref linkend="LzFormatter.prototype.formatToString"/> and sets the text of the
            view to the result.</text><!-- region 7 -->
        </doc>
        <function>
          <parameter name="control"  <!-- region 3, 9 -->        
              type="string"> <!-- region 10 --> 
            <doc>
              <text>A control string where % indicates the
                conversion of the corresponding argument</text><!-- region 11 -->
            </doc>
          </parameter>
          <parameter name="args"  <!-- region 3, 9 -->        
              type="[*]"> <!-- region 10 --> 
            <doc>
              <text>arguments to be formatted according to the
                control string</text><!-- region 11 -->
            </doc>
          </parameter>
        </function>
      </property>
      ...
    </object>
  </property>
</class>

To carry this reasoning all the way back to the javascript code definining the method, in WEB-INF/lps/lfc/views/LzText.lzs:

      /**
      * Formatted output.
      * Formats its arguments using <xref
      * linkend="LzFormatter.prototype.formatToString"/> and sets the text of the
      * view to the result. 
      *
      * @param string control: A control string where % indicates the
      * conversion of the corresponding argument
      *
      * @param [*] args: arguments to be formatted according to the
      * control string
      */
      function format (control:String, ...args) {
        this.setAttribute('text', this.formatToString.apply(this, [control].concat(args)).toString().toHTML());
      }