ITS (Internet Transaction Server) Cookbook
The ITS libraries
Anatomy of a template: the TEMPLATE.html
model
Submitting an OKcode: image inputs vs. hyperlinks
Search helps: providing input help
CALL TRANSACTION
: services that call a secondary service
Overview
The following is a collection of frequently used techniques and coding practices employed in the construction of MIT Administrative Computing: Internet Design & Development Team (IDD) – Web Development Standards compliant ITS templates.
This document assumes the reader is familiar with ITS development concepts and practices. It does not attempt to instruct a novice developer but rather to be a resource to current developers engaged in the development of ITS applications that comply with the MIT Administrative Computing: IDD Web Development Standards.
The ITS libraries
The R/3 development and prototyping environments (SF2 and SF8, respectively) each contain two toolkits for ITS development. These toolkits, also referred to as libraries, are ZSAPWEB, used in the development of ITS applications for the SAPweb product, and ZSAPWEBSS, used in the development of ITS applications for the SAPweb Self Service product. Each library provides a collection of standard, commonly-used objects used in ITS application development and is organized as follows:
Theme 00 directory
The HTML templates directory for Theme 00 contains functions from the S.U.I.T. Javascript API. To use a S.U.I.T. function in an ITS template, the HTML template containing the function definition must be included via bHTML function, `include()`, within the <head></head> section of the calling template.
Example
<head>
<server>
include(~service="{LIBRARY}",~theme="00",~name="always_js.html");
include(~service="{LIBRARY}",~theme="00",~name="getObject_js.html");
</server>
</head>
<body onLoad="suit.getObject('objectName').focus()" marginwidth="0" marginheight="0">
.
.
.
<script type="text/javascript">suit.getObject(l_fieldName)</script>Theme 10 directory
The HTML templates directory for Theme 10 contains functions from a bHTML user-interface (UI) toolkit developed by Administrative Computing: IDD. To use a function from the bHTML toolkit in an ITS template, the HTML template containing the function definition must be included via bHTML function, `include()`, within the <head></head> section of the calling template.
Example
<head>
<server>
include(~service="{LIBRARY}",~theme="10",~name="func_outputTitle.html");
include(~service="{LIBRARY}",~theme="10",~name="func_outputHomeHelp.html");
</server><title>`outputTitle("")`</title>
</head>
<body marginwidth="0" marginheight="0">
.
.
.
<!-- PRODUCT BANNER -->
`outputTitle("banner")`<!-- NAVIGATION BAR -->
`outputHomeHelp(l_homeURL,l_helpURL,"l_username_variable")`
Theme 99 directory
The MIME objects directory for Theme 99 contains the master cascading style sheet (CSS) used for the product along with three subdirectories:
- EXITURL - contains one or more HTML templates that can be used in conjunction with bHTML parameter, `~exitURL`, to redirect a URL upon termination of an ITS session.
- IMAGES - contains graphics files for commonly used buttons and icons.
- SEARCHHELP - contains custom search help templates used in the product.
The HTML templates directory for Theme 99 contains a model template,
TEMPLATE.html
, that can be used as the basis for developing a custom template. The model, intended to both reduce the time required to produce a custom template and promote uniformity of code, may be copied and pasted into an internet service template file and modified locally as needed. Section Anatomy of a template: the TEMPLATE.html model of this document offers an interactive look at the components of theTEMPLATE.html
model.
Anatomy of a template: the TEMPLATE.html model
The ZSAPWEB and ZSAPWEBSS libraries each contain
a template model that can be used as the basis for developing a
custom template specific to the SAPweb
or SAPweb Self Service
products. Below is shown a mock-up web page built using the ZSAPWEB
TEMPLATE.html
model. This mock-up demonstrates the
use of the template model components. Clicking on different areas
within the mock-up will bring the reader to the section of the model
code where that area of the web page is generated.
ZSAPWEB TEMPLATE.html mock-up
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
![]() |
ZSAPWEB TEMPLATE.html model code
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<link rel="stylesheet" href="`mimeURL(~service="zsapweb",~language="","styles.css")`"
type="text/css">
<meta http-equiv="Content-Type" content="text/html;
charset=iso-8859-1">
<meta http-equiv="Content-Style-Type" content="text/css">
<server>
<!-- Template {NUMBER}: {BRIEF DESCRIPTION OF TEMPLATE PURPOSE} -->
<!-- ZSAPWEB S.U.I.T. JAVASCRIPT INCLUDES -->
include(~service="zsapweb",~theme="00",~name="alwaysjs.html");
include(~service="zsapweb",~theme="00",~name="getObjectjs.html");
include(~service="zsapweb",~theme="00",~name="windowDialogjs.html");
<!-- ZSAPWEB BHTML INCLUDES -->
include(~service="zsapweb",~theme="10",~name="func_outputTitle.html");
include(~service="zsapweb",~theme="10",~name="func_outputMessage.html");
include(~service="zsapweb",~theme="10",~name="func_outputhomehelp.html");
include(~service="zsapweb",~theme="10",~name="func_required.html");
include(~service="zsapweb",~theme="10",~name="func_footer.html");
<!-- LOCAL SERVICE INCLUDES (FULL PATH
NEEDED BY CALLER SERVICES) -->
include(~service="{SERVICE}",~theme="99",~name="{TEMPLATE_1}.html");
include(~service="{SERVICE}",~theme="99",~name="{TEMPLATE_2}.html");
l_homeURL = {SAPWEB_TAB_URL};
l_helpURL = {HELP_DOC_URL};
</server>
<title>`outputTitle("")`</title>
</head>
<body marginwidth="0" marginheight="0">
<!-- OPEN FORM -->
<form name="{FORM_NAME}" id="{FORM_NAME}"
action="`wGateURL()`" method="post">
<!-- SAPWEB BANNER -->
`outputTitle("banner")`
<!-- NAVIGATION BAR -->
`outputHomeHelp(l_homeURL,l_helpURL,"{USER_NAME_VARIABLE}")`
<br />
<!-- PAGE TITLE -->
<table align="center" width="95%" border="0"
cellspacing="2" cellpadding="2">
<tr>
<td class="pageTitle">`~windowTitle`</td>
</tr>
</table>
<br />
<!-- SYSTEM MESSAGES -->
`if ( ~messageline != "" )
outputMessage(~messageline,"error");
outputMessage(~messageline,"message");
write("<br />");
end;`
<!-- PAGE NOTE -->
`if ( {PAGE_NOTE_EXISTS} )
outputMessage({PAGE_NOTE},"");
write("<br />");
end;`
<!-- FORM BUTTONS -->
<table align="center" width="95%" border="0"
cellspacing="2" cellpadding="2">
<tr>
<td nowrap>
{BUTTON_1}
{BUTTON_2}
{BUTTON_3}
</td>
</tr>
</table>
<br />
<!-- TABLE LAYOUT OPTION #1 -->
<table border="0" align="center" width="95%"
cellspacing="2" cellpadding="2">
<tr>
<td class="label" nowrap>{FIELD_LABEL_1}</td>
<td width="1%">`required()`</td>
<td class="data" nowrap>`{FIELD_VALUE_1}`</td>
<td width="99%" /> <!-- FORMATTING -->
</tr>
<tr>
<td class="label" nowrap>{FIELD_LABEL_2}</td>
<td width="1%" /> <!-- SPACER: FIELD NOT REQUIRED -->
<td class="data" nowrap>`{FIELD_VALUE_2}`</td>
</tr>
<tr>
<td class="label" nowrap>{FIELD_LABEL_3}</td>
<td width="1%">`required()`</td>
<td class="data" nowrap>`{FIELD_VALUE_3}`</td>
</tr>
</table> <!-- END TABLE LAYOUT OPTION #1 -->
<!-- TABLE LAYOUT OPTION #2 -->
<table border="0" align="center" width="95%"
cellspacing="2" cellpadding="2">
<tr>
<!-- TABLE TITLE -->
<td colspan="{COLSPAN}" class="tableTitle" nowrap>{TABLE_TITLE}</td>
<!--
SORT BY -->
<td colspan="{COLSPAN}" class="label"
align="right" nowrap>
Sort by
<select name="`{SORT_KEY}`"
id="`{SORT_KEY}`" onChange="{CUSTOM_SCRIPT}">
<option value="`{OPTION_VALUE_1}`">
{OPTION_LABEL_1}</option>
<option value="`{OPTION_VALUE_2}`">
{OPTION_LABEL_2}</option>
</select>
</td>
</tr>
<tr>
<!-- RECORDSET BUTTONS -->
<td colspan="{COLSPAN}" nowrap>
{RECORDSET_BUTTON_1}
{RECORDSET_BUTTON_2}
</td>
<!-- RECORDSET NAVIGATION -->
<td colspan="{COLSPAN}" align="right">
<table width="1%" border="0"
cellspacing="0" cellpadding="0">
<tr>
<td class="small" nowrap>`{RECORDSET
SUMMARY}`</td>
<td>`{SCROLL_AREA_START}`</td>
<td>`{SCROLL_BUTTON_FIRST}`</td>
<td>`{SCROLL_BUTTON_PREVIOUS}`</td>
<td>`{SCROLL_BUTTON_NEXT}`</td>
<td>`{SCROLL_BUTTON_LAST}`</td>
<td>`{SCROLL_AREA_END}`</td>
</tr>
</table>
</td>
</tr>
<!-- TABLE COLUMN HEADERS -->
<tr>
<th class="tableHead" align="left"
nowrap>`{COLUMN_1_LABEL}` </th>
<th class="tableHead" align="left"
nowrap>`{COLUMN_2_LABEL}` </th>
<th class="tableHead" align="left"
nowrap>`{COLUMN_3_LABEL}` </th>
<td width="99%" /> <!-- FORMATTING -->
</tr>
<!-- RECORDSET -->
`repeat with j from {TABLE_CONTROL}.firstvisible to {TABLE_CONTROL}.lastvisible`
<tr>
<td class="data" nowrap>`{COLUMN_1_VALUE[j]}`
</td>
<td class="data" nowrap>`{COLUMN_2_VALUE[j]}`
</td>
<td class="data" nowrap>`{COLUMN_3_VALUE[j]}`
</td>
</tr>
`end; <!-- end repeat -->`
</table> <!-- END TABLE LAYOUT OPTION #2 -->
<!-- FORM BUTTONS -->
<table align="center" width="95%" border="0"
cellspacing="2" cellpadding="2">
<tr>
<td nowrap>
{BUTTON_1}
{BUTTON_2}
{BUTTON_3}
</td>
</tr>
</table>
<br />
<!-- CLOSE FORM -->
</form>
<!-- SAPWEB FOOTER -->
`footer({PARAMETER_STRING})`
</body>
</html>
Submitting an OKcode: image inputs vs.hyperlinks
Submitting an OKcode via an image input form element vs. a hyperlink
OKcodes may be submitted to the backend via one of two basic methods. The first approach associates the OKcode with a graphical form element, such as a button, by naming the button, ~okcode(OKCD). An alternative notation, ~okcode=OKCD, may be used and produces the same effect; when a user clicks the graphical form element, ITS submits the HTML form in its entirety and processes the contents of the ITS template according to the screen PAI (post-input) logic.
Notation 1
<input type="image" name="~okcode(OKCD)" id="~okcode(OKCD)" src="..." width="..." height="..." alt="..." title="..." border="0">
Notation 2
<input type="image" name="~okcode=OKCD" id="~okcode=OKCD" src="..." width="..." height="..." alt="..." title="..." border="0">
Example
![]()
<input type="image" name="~okCode(NEWP)" id="~okCode(NEWP)" src="`mimeURL(...)`" border="0" width="85" height="17" alt="Add a Person" title="">
<input type="image" name="~okCode(DELP)" id="~okCode(DELP)" src="`mimeURL(...)`" border="0" width="99" height="17" alt="Delete Selected" title="">
The second approach associates the OKcode with a hypertext link. In this approach, standard business-HTML (bHTML) function, `wGateURL()` is embedded within the href attribute of an opening HTML <a> tag. The `wGateURL()` function generates a dynamic URL based on the current system, ITS session, and other information.
A URL may be generated in this manner for either a single hyperlink or for a series of hyperlinks output in a repeating loop.
Notation 1
<a href="`wGateURL(~okcode="OKCD")`"> `TABLE-FIELD.value`</a>
Notation 2
`repeat with j from l_firstVisble to l_lastVisible`
<a href="`wGateURL(~okcode="OKCD",'G_HTML_INDEX'=j)`">
`TABLE-FIELD[j].value`</a>
`end;`
In notation 2, l_firstVisble and l_lastVisble represent the first and last records of either an internal table or a table control housing the data to be output, and G_HTML_INDEX represents an ABAP variable used in the PAI (post-input) logic to determine the selected table index.
Example
![]()
`repeat with j from l_first_record to l_last_record`
<tr>
<td align="center" width="1%" nowrap>
`checkbox_mode("T_ROOM-SELECT",j,"")`
</td>
<td class="data" nowrap>
<a href="#" onclick="drillDown('hazmat3000','XROM',`j`);
return false;" > `T_ROOM-NUMBER[j].value`</a>
</td>
<td class="data" nowrap>
`T_ROOM-TYPETEXT[j].value`
</td>
.
.
.
</tr>
`end; <!-- end repeat -->`
Note that the example uses a combination of:
- cascading style sheet elements class="data"
- local bHTML variables l_first_record
- ZSAPWEB bHTML function calls `checkbox_mode(...)`
- javascript events onclick="..."
- local javascript function calls drillDown(...)
to output the data for this repeat loop. This is a good example of how ITS development uses an assortment of different coding and scripting components in the design of a good application screen.
Using a hyperlink to both submit an OKcode and trigger a form submit
Hyperlinks do not trigger a form submit. When a user clicks a hyperlink:
<a href="`wGateURL(~okcode="OKCD")` ">`TABLE-FIELD.value`</a>
the OKcode is processed according to screen PAI (post-input) logic, however the contents of the HTML form are not submitted back to the server. Notice what the function call is requesting: ~okcode="OKCD" is submitted to the server via the WGate, but no other fields are included in the request. If a template contains both form input fields and hyperlinks, any changes a user makes to input fields will be lost when the user clicks a hyperlink.
To avoid losing user changes, when an ITS template contains both hyperlinks and form input fields, it is necessary to implement a mechanism to submit the HTML form in its entirety when a hyperlink is clicked. More than one mechanism is possible; the mechanism used in standard Web Services practice requires three components:
HTML
A hidden form element must be included within the form for bHTML parameter, ~okcode. This parameter maps to ABAP system variable,
sy-ucomm
, and will hold the OKcode to be submitted when the hyperlink is clicked.<!-- HIDDEN FORM DATA -->
<input type="hidden" name="~okcode" id="~okcode" value="">Javascript
A locally defined function must write the OKcode value into the hidden form element and trigger a form submit when the hyperlink is clicked. In this example, the fieldChange() and formSubmit() functions from the SUIT API are used by the locally defined function.
<script type="text/javascript">
function drillDown(p_form,p_ok)
{
suit.fieldChange("~okcode",p_ok);
suit.formSubmit(p_form);
}
</script>
.
.
.
<a href="#" onclick="drillDown('formName','OKCD');
return false;">`TABLE-FIELD.value`</a>ABAP
Per usual, PAI (post-input) logic must recognize and process the value for the OKcode that is submitted.
Search helps: providing input help
The ZSAPWEB and ZSAPWEBSS libraries provide bHTML
function, `matchCode()`, to output a
standard searchHelp button for an input field. This function makes
use of an SAP-delivered macro called ~searchhelp
to
output a button that, when clicked, generates a field-specific searchHelp
screen. Note that in order to use the ~searchhelp
macro,
the field must have an associated searchHelp on the GUI screen.
Function `matchCode()` requires two parameters. The first contains the literal name of the field for which the searchHelp is generated. The second may be used to specify the table index of the field when multiple searchHelps are output via a loop statement. The second parameter is left empty for a searchHelp output as an individual field.
Example
Individual field
![]()
<td nowrap>
.
.
.
<input type="text" name="`WA_ROOM-NUMBER.name`"
id="`WA_ROOM-NUMBER.name`" value="`WA_ROOM-NUMBER.value`"
maxlength="20" size="20">
`matchCode("WA_ROOM-NUMBER","")`
</td>Multiple fields via a loop
![]()
`repeat with j from TC_ROOM.firstvisible to TC_ROOM.lastvisible`
<tr>
<td nowrap>
.
.
.
<input type="text" name="`T_ROOM-NUMBER[j].name`"
id="`T_ROOM-NUMBER[j].name`" value="`T_ROOM-NUMBER[j].value`"
maxlength="20" size="20">
`matchCode("T_ROOM-NUMBER",j)`
</td>
</tr>
`end; <!-- end repeat -->`
CALL TRANSACTION: services that call a secondary service
The back-end GUI transaction associated with an
internet service may call a secondary transaction through ABAP statement,
CALL TRANSACTION
:
CALL TRANSACTION l_secondary_transaction.
To duplicate this functionality in an ITS service,
secondary transaction l_secondary_transaction
must
have an associated internet service whose templates are included
in the main Theme folder of the primary service.
Example
![]()
In this example, ZVERI
is the primary
internet service and is associated with program SAPMZVERI
,
which has a single screen, 100
. During processing of
this screen, the following ABAP statement may be executed depending
on user action:
CALL TRANSACTION 'Z_TRANSACTION' AND SKIP FIRST SCREEN.
Transaction Z_TRANSACTION
has its
own internet service, Z_SERVICE
, which may be executed
independently or may be called from another service.
Here, primary service ZVERI
accommodates
the CALL TRANSACTION
ABAP statement by including in
its main Theme folder the ITS templates for secondary service Z_SERVICE
.
Each secondary template included may either completely redefine
the template for its own purposes in the primary service or may
simply contain a call to include the original template as-is directly
from the secondary service:
`include(~service="Z_SERVICE",~theme="99",~name="SAPMZGLWEBJV_100.html")`
In addition to including the templates from the
secondary service, the primary service should declare ITS service
parameter ~sources
. This service parameter is not required,
but is recommended, when an internet service uses templates from
multiple sources.