XUL Javascript

Un XML component permet de décrire les paramètres du template à l'aide de contrôles XUL. Il est possible d'ajouter des scripts Javascript dans votre description XUL pour mettre à jour des contrôles XUL en fonction d'autres contrôles XUL.

Les scripts à exécuter peuvent être :

  • écrits dans le XML component dans un script.
  • écrits dans un fichier externe *.js . Le XML component peut ensuite faire référence à ce script.
  • testés dans un navigateur Firefox.

Pour mieux comprendre l'interêt de ces scripts, nous allons tout au long de cette section s'appuyer sur un exemple concret : la génération d'une simple classe JAVA.

Les scripts interviennent dans les cas suivants :

  • lorsque vous saisissez le champs className, le champs outputFileName doit se mettre à jour en ajoutant à la valeur du champs className l'extension .java.
  • lorsque vous saisissez le champs packageName, le champs outputBaseDir doit se mettre à jour en remplaçant le caractère '.' de la valeur du champs packageName par le caractère '/' et en y ajoutant src/ devant.

Akrogen met à disposition les objets Javascripts :

  • document (getElementById,... ) pour récupérer les contrôles XUL constituant la page du Wizard.
  • window (alert, confirm,...) pour appeler les méthodes alert et confirm.

Script

Vous pouvez trouver l'exemple ci dessous dans le catalogue usecases-catalog/Components/Script/JavaClass/JavaClass-scripts.akgncpt.xml.

L'écriture d'un script s'effectue comme si vous écrivez un script Javascript dans une page XUL ou HTML. Un script doit être contenu dans la balise script qui doit être OBLIGATOIREMENT inclus dans l'élement XUL racine (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>

Pour accéder au contrôle XUL, vous utilisez le Javascript standard à l'aide de la méthode getElementById de l'objet document :

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

permet de récupérer la valeur de la texbox className.

Dans notre cas, nous définissons :

  • une fonction Javascript updateOutputFileNameWithJavaClass qui permet de mettre à jour le contrôle XUL outputFileName avec className :
    function updateOutputFileNameWithJavaClass() {
      var className = document.getElementById('className').value;
      className = className.replace(' ','_');                                       
      document.getElementById('outputFileName').value = className + '.java';
    }  
  • une fonction Javascript updateOutputBaseDirWithPackage qui permet de mettre à jour le contrôle XUL outputBaseDir avec packageName :
    function updateOutputBaseDirWithPackage() {
      var srcBaseDir = 'src';
      var packageName = document.getElementById('packageName').value;
      packageName = packageName.replace('.','/');                                   
      document.getElementById('outputBaseDir').value = srcBaseDir + '/' + packageName;
    }  

Ces fonctions doivent être déclenchées lorsque les contrôles XUL className et packageName sont modifiés, autrement dit :

  • la fonction updateOutputFileNameWithJavaClass doit être déclenchée sur l'évenement onkeyup du contrôle XUL className :
    <textbox id="className" flex="1" onkeyup="javascript:updateOutputFileNameWithJavaClass();" />
  • la fonction updateOutputBaseDirWithPackage doit être déclenchée sur l'évenement onkeyup du contrôle XUL packageName :
    <textbox id="packageName" flex="1" onkeyup="javascript:updateOutputBaseDirWithPackage();" />

Voici le XML component complet :

<?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>

Script externe

Vous pouvez trouver l'exemple ci dessous dans le catalogue usecases-catalog/Components/Script/JavaClass/JavaClass-external-scripts.akgncpt.xml.

Il est possible d'externaliser les scripts dans des fichiers, pour ensuite y faire référence dans le contenu XUL d'un XML component. L'externalisation de script devient intéréssante lorsque le script est susceptible d'être utiliser dans plusieurs XML components.

Dans notre cas d'utilisation, la génération de classe JAVA peut se faire à travers plusieurs XML component. Il est donc intéressant d'externaliser le script dans un fichier *.js.

Les fichiers scripts doivent être stockés dans le catalogue. Pour faire référence à un script dans un XMl component :

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

Le fichier java-functions.js contient les deux fonctions Javascript. Il est stockés dans le catalogue dans le répertoire /Scripts/javascript.

Pour pouvoir utiliser ces fonctions dans n'importe quel XML component, ces deux fonctions attendent l'ID des deux contrôles XUL.

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;
}   

L'appel de ces fonctions se font donc comme ceci :

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

Voici le XML component complet :

<?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

Il est posible de tester vos scripts (non externes) de vos XML component dans Firefox. Pour cela vous devez renommer votre XML component avec l'extension .xul.

Renommez le XML component JavaClass-scripts.akgncpt.xml en JavaClass-scripts.akgncpt.xml.xul et ouvrez ce dernier dans FireFox. Vous pouvez maintenant tester le script sous FireFox :