ITS (Internet Transaction Server) Cookbook
Overview
The following is a collection of frequently used
techniques and coding practices employed in the construction of
MIT
FSS 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 FSS 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 FSS Web Services. 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 the TEMPLATE.html model.
TOP
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>
TOP
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.
TOP
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 -->`
TOP
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.
TOP
|