XUL Javascript

With XML component you describe template parameters with XUL controls. it's possible to add Javascript scripts in your XUL description XUL to update XUL controls according to another XUL controls.

Scripts to execute can be :

  • written into the XML component into a script.
  • written into external file *.js . The XML component can therefore refer to this script.
  • tested with Firefox navigator.

In order to understand the advantage of scripts, we will use a sample : the generation of simple JAVA class.

Scripts are used :

  • when you fill the className control, the outputFileName control must be updated by adding the .java extension to the value of className control.
  • when you fill the packageName control, the outputBaseDir control must be updated by replacing character '.' of the value packageName by the character '/' and by adding src/ in front of.

With Akrogen you can use objects Javascript :

  • document (getElementById,... ) to get XUL controls of the Wizard page.
  • window (alert, confirm,...) to call methods alert et confirm.

Script

You can find next sample into usecases-catalog/Components/Script/JavaClass/JavaClass-scripts.akgncpt.xml catalog.

Script is written like Javascript written into XUL or HTML. A script must be inserted into the script element which must be included in XUL root (box, ...).

<box flex="1" id="" orient="vertical" 
     xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" >  
     
  <script type="text/javascript" >
    ... Your script
  </script>
  
</box>

To access to XUL control, you must use standard Javascript with getElementById method of the document object :

The script :

  var className = document.getElementById('className').value;

get the value of the className textbox.

In our sample, we define :

  • updateOutputFileNameWithJavaClass Javascript function to update outputFileName XUL control with className :
    function updateOutputFileNameWithJavaClass() {
      var className = document.getElementById('className').value;
      className = className.replace(' ','_');                                       
      document.getElementById('outputFileName').value = className + '.java';
    }  
  • updateOutputBaseDirWithPackage Javascript function to update outputBaseDir XUL control with packageName :
    function updateOutputBaseDirWithPackage() {
      var srcBaseDir = 'src';
      var packageName = document.getElementById('packageName').value;
      packageName = packageName.replace('.','/');                                   
      document.getElementById('outputBaseDir').value = srcBaseDir + '/' + packageName;
    }  

Those functions must be fired when XUL controls className and packageName change, in other words :

  • updateOutputFileNameWithJavaClass function must be fired with onkeyup event of className XUL control :
    <textbox id="className" flex="1" onkeyup="javascript:updateOutputFileNameWithJavaClass();" />
  • updateOutputBaseDirWithPackage function must be fired with onkeyup event of packageName XUL control :
    <textbox id="packageName" flex="1" onkeyup="javascript:updateOutputBaseDirWithPackage();" />

Here the XML component :

<?xml version="1.0" encoding="UTF-8"?>
<component>
  <input>
    <page title="Simple Java Class" >
                <description>Generate simple JAVA class. Javascript events are linked 
to XUL control 'className' and 'packageName'.</description>                     
        <box flex="1" id="" orient="vertical" 
             xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" >             
          <script type="text/javascript" >
          
            function updateOutputFileNameWithJavaClass() {
                    var className = document.getElementById('className').value;
                    className = className.replace(' ','_');                                     
                    document.getElementById('outputFileName').value = className + '.java';
            }  
            
            function updateOutputBaseDirWithPackage() {
                    var srcBaseDir = 'src';
                    var packageName = document.getElementById('packageName').value;
                    packageName = packageName.replace('.','/');                                 
                    document.getElementById('outputBaseDir').value = srcBaseDir + '/' + packageName;
            }                                                   
                  
          </script>                                                  
          <hbox>
            <label value="className: " />
            <textbox id="className" flex="1" 
                     onkeyup="javascript:updateOutputFileNameWithJavaClass();" />
          </hbox>
          <hbox>
            <label value="packageName: " />
            <textbox id="packageName" flex="1" 
                     onkeyup="javascript:updateOutputBaseDirWithPackage();" />
          </hbox>          
          <hbox>
            <label value="outputBaseDir:" />
            <textbox id="outputBaseDir" flex="1" />
            <button type="folder" target="outputBaseDir" label="Browse..." />
          </hbox>
          <hbox>
            <label value="outputFileName:" />
            <textbox id="outputFileName" flex="1" />
          </hbox>       
          <hbox>
            <button type="preview" label="Preview..." />
          </hbox>                       
        </box>                  
    </page>
  </input>
  <output>
    <file>
      <template uri="/ftl/JavaClass/SimpleJavaClass.ftl" /> 
    </file>
  </output>
</component>

External script

You can find next sample into usecases-catalog/Components/Script/JavaClass/JavaClass-external-scripts.akgncpt.xml catalog.

It's possible to externalize scripts into files, to therefore refer it into XUL content of XML component. Script externalization is intersting when script can be used in another XML component.

In our sample, JAVA class generation can be done with several XML component. So it's interesting to externalize script into *.js file.

Scripts file must be stored into catalogue. To refer to a script into XML component :

<script type="text/javascript" src="/Scripts/javascript/java-functions.js" />                                                

java-functions.js file contains the two Javascript functions. It is stored into the catalog into /Scripts/javascript directory.

To use those functions in any XML component, those functions have the ID parameter of the XUL control :

function updateOutputFileNameWithJavaClass(classNameId) {
        var className = document.getElementById(classNameId).value;
        className = className.replace(' ','_');                                 
        document.getElementById('outputFileName').value = className + '.java';
}  
                
function updateOutputBaseDirWithPackage(packageNameId) {
        var srcBaseDir = 'src';
        var packageName = document.getElementById(packageNameId).value;
        packageName = packageName.replace('.','/');                                     
        document.getElementById('outputBaseDir').value = srcBaseDir + '/' + packageName;
}   

Functions must be called, like this :

...
<textbox id="className" flex="1" onkeyup="javascript:updateOutputFileNameWithJavaClass('className');" />
...
<textbox id="packageName" flex="1" onkeyup="javascript:updateOutputBaseDirWithPackage('packageName');" />  
...

Here the XML component :

<?xml version="1.0" encoding="UTF-8"?>
<component>
  <input>
    <page title="Simple Java Class" >
                <description>Generate simple JAVA class. Javascript EXTERNAL
                (/Scripts/javascript/java-functions.js) events are linked 
                to XUL control 'className' and 'packageName'.
                </description>                          
        <box flex="1" id="" orient="vertical" 
             xmlns="http://www.mozilla.org/keymaster/gatekeeper/there.is.only.xul" >             
          <script type="text/javascript" src="/Scripts/javascript/java-functions.js" />                                              
          <hbox>
            <label value="className: " />
            <textbox id="className" flex="1" 
                     onkeyup="javascript:updateOutputFileNameWithJavaClass('className');" />
          </hbox>
          <hbox>
            <label value="packageName: " />
            <textbox id="packageName" flex="1" 
                     onkeyup="javascript:updateOutputBaseDirWithPackage('packageName');" />
          </hbox>          
          <hbox>
            <label value="outputBaseDir:" />
            <textbox id="outputBaseDir" flex="1" />
            <button type="folder" target="outputBaseDir" label="Browse..." />
          </hbox>
          <hbox>
            <label value="outputFileName:" />
            <textbox id="outputFileName" flex="1" />
          </hbox>       
          <hbox>
            <button type="preview" label="Preview..." />
          </hbox>                       
        </box>                  
    </page>
  </input>
  <output>
    <file>
      <template uri="/ftl/JavaClass/SimpleJavaClass.ftl" /> 
    </file>
  </output>
</component>  

Test script

It's possible to test your scripts (non externalized) of your XML component into Firefox. To do that, you must rename your XML component with .xul extension.

Rename the JavaClass-scripts.akgncpt.xml XML component into JavaClass-scripts.akgncpt.xml.xul and open it into FireFox. You can test the script with FireFox :