Back to Contents


Tutorial - Working with the Genero Web Client

This tutorial provides you with some hands-on experience in running and customizing a Web application delivered by the Genero Web Client front-end.

Topics


Step 0: Run the tutorial demo application

The Genero Application Server installs with a demo application known as the Contact List (Card Manager) application.  The default configuration provided in the GAS configuration file allows you to run this demo application without any additional configuration.

To run the demo application, start the GAS and then enter the following URL in a browser:

http://localhost:6394/wa/r/demo/Card

Note: For the purpose of this tutorial, it is assumed that you are connecting to the GAS directly. If your browser is on a different host than the GAS, you will have to replace "localhost" with the name or IP address of the GAS host.  Likewise, if you have changed the port number from the installation default of 6394, you will have to modify the port number accordingly.

Figure 0-1: The application displayed with the Genero Desktop Client

Figure 0-2: The application displayed by the GAS with the Genero Web Client

Things to observe:

Card.xcf

<?xml version="1.0"?>
<APPLICATION Parent="defaultgwc"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:noNamespaceSchemaLocation="http://www.4js.com/ns/gas/2.10/cfextwa.xsd">
 <EXECUTION>
  <PATH>$(res.path.demo.app)/card/src</PATH>
  <MODULE>card.42r</MODULE>
 </EXECUTION>
</APPLICATION>

Back to the top


Step 1: Use a custom snippet file

For the next part of this tutorial, a custom snippet file has been created to display image widgets for this application.

Enter the following URL in a browser:

http://localhost:6394/wa/r/demo/CardStep1

Figure 1-1: Contact displayed prior to referencing the custom Image snippet in the application configuration file.

Figure 1-2: Contact displayed after referencing the custom Image snippet in the application configuration file.

Thing to observe:

Application Configuration File: CardStep1.xcf

Examine the application configuration file for this step in the tutorial.

<?xml version="1.0"?>
<APPLICATION Parent="defaultgwc"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:noNamespaceSchemaLocation="http://www.4js.com/ns/gas/2.11/cfextwa.xsd">
 <EXECUTION>
  <PATH>$(res.path.demo.app)/card/src</PATH>
  <MODULE>card.42r</MODULE>
 </EXECUTION>
 <OUTPUT>
  <MAP Id="DUA_AJAX">
   <THEME>
    <SNIPPET Id="Image" Style="Picture">$(res.path.demo.app)/card/tpl/set1/Image.xhtml</SNIPPET>
   </THEME> 
  </MAP>
  <MAP Id="DUA_AJAX_HTML">
   <THEME>
    <SNIPPET Id="Image" Style="Picture">$(res.path.demo.app)/card/tpl/set1/Image.xhtml</SNIPPET>
   </THEME> 
  </MAP>
 </OUTPUT> 
</APPLICATION>

Notes:

Modifications to the template and snippet files

A new snippet file has been created for the rendering of the Image widgets for this application.

To identify what is different, you can compare the Image.xhtml file provided with the default AJAX theme ($FGLASDIR/tpl/set1/Image.xhtml) with the snippet file specified by the SNIPPET element in the application configuration file. Using Genero Studio's Graphical Differential tool, we can quickly identify the differences between the two files, as shown in Figure 1-3 below:

Figure 1-3: The differences between the default and custom Image snippet files, with the customized values shown in blue.

Notes:

Usually, application pictures are configured through the picture component. In this example, the common pictures are handled by the picture component, alias "/pic", and the application images are served through alias "/card/img". Another solution could be to copy all the common picture in the application image directory and set the component picture path to alias /card/img.

<PICTURE>
  <PATH>$(connector.uri)/card/img</PATH>
</PICTURE>

In this case you do not need to customize your image snippet file.

Back to the top


Step 2: Customize the template and add additional CSS

For the next step in this tutorial, a header and footer have been added.

Enter the following URL in a browser:

http://localhost:6394/wa/r/demo/CardStep2

Figure 2-1: Application prior to adding header and footer.

Figure 2-2: Application after adding header and footer.

Things to observe:

Application Configuration File: CardStep2.xcf

Examine the application configuration file for this step in the tutorial.

<?xml version="1.0"?>
<APPLICATION Parent="defaultgwc"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:noNamespaceSchemaLocation="http://www.4js.com/ns/gas/2.10/cfextwa.xsd">
 <EXECUTION>
  <PATH>$(res.path.demo.app)/card/src</PATH>
  <MODULE>card.42r</MODULE>
 </EXECUTION>
 <OUTPUT>
  <MAP Id="DUA_AJAX">
   <THEME>
    <TEMPLATE Id="_default">$(res.path.demo.app)/card/tpl/set1/main.xhtml</TEMPLATE>
    <SNIPPET Id="Image" Style="Picture">$(res.path.demo.app)/card/tpl/set1/Image.xhtml</SNIPPET>
   </THEME> 
  </MAP>
 </OUTPUT> 
</APPLICATION>

Notes:

Modifications to the template and snippet files

Using Genero Studio's Graphical Differential tool, we can quickly identify the differences between the two files, as shown in Figure 2-3 and 2-4 below:

Figure 2-3: The addition of the custom CSS, with the customized values shown in blue.

Figure 2-4: The addition of the header and footer code to the template file, with the customized values shown in blue.

Add a header that displays a logo

To add a header to the application display, the following code is placed in the custom template file:

<div class="card-header" style="background-color:#e6e6e6">
<img src="..." gwc:attributes="src application/connectorURI + '/fjs/demo/card-logo.png'" alt="Genero logo"/>
</div>

Notes:

Add a footer that includes a mail link

To add a footer to the application display, the following code is placed in the custom template file:

<div class="card-footer">For any issues or comments please contact 
<a href="mailto:support@4js.com">support@4js.com</a></div>

Add a custom CSS file

To add a custom CSS file, an entry is made under the existing CSS entry and within the HEAD tags (as shown in Figure 2-3):

<link rel="stylesheet" gwc:attributes="href application/connectorURI+'/fjs/demo/card.css'" type="text/css" title="Default Theme"/>

For this example, we have provided a CSS for you. Before moving to the next step, you can make changes to this CSS file and view the results in the displayed application..

Back to the top


Step 3: Customize Snippet to vary Rendering based on Style

For the next step in this tutorial, various things are added:

First, the FormField snippet has been modified such that all fields where the REQUIRED attribute is set to true (1) are marked on the UI with an asterisk.

Second, customized Edit snippets are created to render Edit widgets based on their assigned styles.  If the field is representing an email address, that field is assigned the style of "Email", and a custom Edit snippet is called to render the field as a link that, when clicked, opens a new message to the clicked-on address. If the field is representing a Web address, that field is assigned the sytle of "OpenURL", and a custom Edit snippet is called to render that field: displaying an Open button that, when clicked, opens the specified URL.

Enter the following URL in a browser:

http://localhost:6394/wa/r/demo/CardStep3

Figure 3-1: Contact displayed after referencing the customized FormField and Edit snippets in the application configuration file.
Fields such as 'Email' and 'Web Site', while still being Edit fields, are rendered differently based upon their assigned styles.

Figure 3-2: In input, required fields are marked with an asterisk

Things to observe:

Application Configuration File: CardStep3.xcf

Examine the application configuration file for this step of the tutorial.

<?xml version="1.0"?>
<APPLICATION Parent="defaultgwc"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:noNamespaceSchemaLocation="http://www.4js.com/ns/gas/2.10/cfextwa.xsd">
 <EXECUTION>
  <PATH>$(res.path.demo.app)/card/src</PATH>
  <MODULE>card.42r</MODULE>
 </EXECUTION>
 <OUTPUT>
  <MAP Id="DUA_AJAX">
   <THEME>
    <TEMPLATE Id="_default">$(res.path.demo.app)/card/tpl/set1/main.xhtml</TEMPLATE>
    <SNIPPET Id="Image" Style="Picture">$(res.path.demo.app)/card/tpl/set1/Image.xhtml</SNIPPET>
    <SNIPPET Id="FormField">$(res.path.demo.app)/card/tpl/set1/FormField.xhtml</SNIPPET>
    <SNIPPET Id="Edit" Style="Email">$(res.path.demo.app)/card/tpl/set1/Edit_Email.xhtml</SNIPPET>
    <SNIPPET Id="Edit" Style="OpenURL">$(res.path.demo.app)/card/tpl/set1/Edit_OpenURL.xhtml</SNIPPET>
   </THEME> 
  </MAP>
 </OUTPUT> 
</APPLICATION>

Notes:

Modifications to the template and snippet files

Changes to the FormField snippet provide the code that places an asterisk next to required fields, when you are in input mode:

<span style="color:red" gwc:condition="item/isModifiable &amp;&amp; item/isRequired &amp;&amp; item/hidden!=1" >*</span>

isRequired notation is used to determine whether the required attribute is set to true, and if so an asterisk is displayed.

For the two custom Edit snippets, open the relevant files and observe the following:

For the Edit snippet for the style Email, the following has been added:

<a gwc:attributes="href 'mailto:'+value" gwc:content="'mail'" />

For the Edit snippet for the style OpenURL, the following has been added:

<input type="button" value="Open" gwc:attributes="onclick 'OpenURL(\''+value+'\')'"/>

Back to the top


Step 4: Customize Snippet to use JavaScript to render the widget

For the next part of this tutorial,  a custom Table snippet uses the gwc:marks instruction to make a call to a JavaScript that renders the table based on the value selected in the Page size list box.

Enter the following URL in a browser:

http://localhost:6394/wa/r/demo/CardStep4

Figure 4-1: Contact List with customized Table widget

Things to observe:

Application Configuration File: CardStep4.xcf

Examine the application configuration file for this step in the tutorial. Note that a new entry has been added, specifying a custom snippet file for all Table widgets.

<?xml version="1.0"?>
<APPLICATION Parent="defaultgwc"
 xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
 xsi:noNamespaceSchemaLocation="http://www.4js.com/ns/gas/2.10/cfextwa.xsd">
 <EXECUTION>
  <PATH>$(res.path.demo.app)/card/src</PATH>
  <MODULE>card.42r</MODULE>
 </EXECUTION>
 <OUTPUT>
  <MAP Id="DUA_AJAX">
   <THEME>
    <TEMPLATE Id="_default">$(res.path.demo.app)/card/tpl/set1/main.xhtml</TEMPLATE>
    <SNIPPET Id="Image" Style="Picture">$(res.path.demo.app)/card/tpl/set1/ImageStep4.xhtml</SNIPPET>
    <SNIPPET Id="FormField">$(res.path.demo.app)/card/tpl/set1/FormField.xhtml</SNIPPET>
    <SNIPPET Id="Edit" Style="Email">$(res.path.demo.app)/card/tpl/set1/Edit_Email.xhtml</SNIPPET>
    <SNIPPET Id="Edit" Style="OpenURL">$(res.path.demo.app)/card/tpl/set1/Edit_OpenURL.xhtml</SNIPPET>
    <SNIPPET Id="Table">$(res.path.demo.app)/card/tpl/set1/Table.xhtml</SNIPPET>
   </THEME> 
  </MAP>
 </OUTPUT> 
</APPLICATION>

Modifications to the template and snippet files

By this point, you should easily identify that a custom snippet for the Table widget has been created and specified for this application.

Adding a select to change the number of lines displayed in a table

<select gwc:marks="changePageSize [CID]" gwc:attributes="id 'pgsz_'+id">
  <option gwc:attributes="value makePageSizeIDID(id , 1)">1</option>
  <option gwc:attributes="value makePageSizeIDID(id , 5)">5</option>
  <option gwc:attributes="value makePageSizeIDID(id , 10)">10</option>
  <option gwc:attributes="value makePageSizeIDID(id , 15)">15</option>
  <option gwc:attributes="value makePageSizeIDID(id , 20)">20</option>
  <option gwc:attributes="value makePageSizeIDID(id , 30)">30</option>
  <option gwc:attributes="value makePageSizeIDID(id , 50)">50</option>
  <option gwc:attributes="value makePageSizeIDID(id , size)">all</option>
</select>

makePageSizeIDID is the template function that will send the action to change the pageSize of the table
changePageSize is the new function we add to the component Table

changePageSize is the function we declared in the Table.xhtml snippet using the gwc:marks instruction.
gwc.tk.SetEventEx is a function of the toolkit to handle (add/remove) events it take 4 arguments.
  polarity: boolean, to add or remove the handler
  elt: item on with the handler is set/removed
  ev: event name
  handler: function attached to the event

Warning! As with all functions in the CSF toolkit, this function is subject to changes.

gwc.componentSet.Table.sentPageSize = function(ev,elt){
  gwc.capi.Action(elt.value);
}

gwc.componentSet.Table.sentPageSize is the handler associate to the 'onchange' event of the select item.
gwc.api.Action sent an action to the engine.

<SNIPPET Id="Table">$(res.path.demo.app)/card/tpl/set1/Table.xhtml</SNIPPET>
<script type="text/javascript" gwc:attributes="src application/connectorURI+'/demo/card.js'" defer="defer"> </script>

Send an action to the engine (see the custom Image.xhtml snippet)

Clicking on the picture of the contact will send the "changeimg" action to the engine and open a window to upload a new image for the contact.
Note, accepting the dialog without changing the image will set the image to blank.

<a gwc:attributes="href 'javascript:gwc.capi.Action(gwc.core.state.ActionDidByName(\'changeimg\') )'">[...]</a>

Communicate with external web sites like googlemap, geonames

To use googlemap you need to to sign up for a key at http://code.google.com/apis/maps. You can use the current key if you are testing with localhost server.

Figure 4-2: The Check Location button is added to the form.

Google Map and geonames are used to fill the country name. Clicking on the button gives the focus to the country field and opens the Google map. Once the map opens, double click on a country name to populate the country field.

Excerpt from Edit_GoogleMap.xhtml snippet:

<input type="button" value="Choose"
  gwc:condition="isModifiable"
  gwc:attributes="onclick 'gwc.capi.Focus(\'' + cid + '\');' + 
  'OpenMap(\''+ application/connectorURI + '/fjs/demo/card-map.html\',\'wd_country\',\'' + value + '\')'"
/>

The field should have the focus, if you want the value to be taken in account by the 4GL application. To set the focus on a field, use the JavaScript api function gwc.capi.Focus.

Excerpt from card.js

function SetCountry(id,value) {
  var elt = gwc.tk.IdToElement(id);
  elt.value = value;
}

gwc.tk.IdToElement is a function of the toolkit that get the html object given the id of this element. The field is then filled with the value returned by geonames.
 

Figure 4-3: GoogleMap

GoogleMap is used to locate and check the address. In the Edit_GoogleMap.xhtml snippet, get the value of the fields address, town and country.

<input type="button" value="Check location"
  gwc:condition="!isModifiable"
  gwc:define="address FormField['formonly.address']/item/value;
    town FormField['formonly.town']/item/value;
    country FormField['formonly.country']/item/value;
  "
  gwc:attributes="onclick 'ShowLocation(\''+ application/connectorURI + '/fjs/demo/card-map.html\','
    + '\'' + escapeJS(translate(address, ['\'',','] ,' ')) + '\','
    + '\'' + escapeJS(translate(town, ['\'',','] ,' ')) + '\','
    + '\'' + escapeJS(translate(country, ['\'',','] ,' ')) + '\''
    + ')'"
/>

In card.js, the JavaScript function ShowLocation submits the data to the map page. GoogleMap locates and displays the address on the map.

function ShowLocation(url,address,town,country) {
  var args = "id=&value=&address=" + address + "&town=" + town + "&country=" + country;
  var win = window.open(url + "?" + args ,"CardMap","toolbar=no,menubar=no,location=no,height=500,width=500");
}

Figure 4-4: GoogleMap locates and displays the address on a map.

Back to the top


Tutorial Summary

Throughout this tutorial, you have customized your application's User Interface using CSS, snippets, template files, and JavaScript.

You should have noted that at no time did you have to change the application source code.

Back to the top