Package com.sapportals.portal.prt.service.epcftoolbox

Client framework available in EP 5.0 provides basic JavaScript-based API for sharing data on the client using the Client Eventing and Client Data-Bag mechanism.  As the content developer builds their component in Java on the Server-side without a deep JavaScript knowledge (typically using a HTMLB classes), they can use the below described classes which support the automatic generation of the necessary JavaScript code.

See:
          Description

Interface Summary
IClientEventReceiver interface for receiver object in the eventing pattern.
IClientEventSender interface for sender object in the eventing pattern.
IEpcfToolbox interface for EpcfToolbox service.
IScriptGenerator interface for objects which generate any form of script code
 

Package com.sapportals.portal.prt.service.epcftoolbox Description

Client framework available in EP 5.0 provides basic JavaScript-based API for sharing data on the client using the Client Eventing and Client Data-Bag mechanism.  As the content developer builds their component in Java on the Server-side without a deep JavaScript knowledge (typically using a HTMLB classes), they can use the below described classes which support the automatic generation of the necessary JavaScript code.

Use case

Let’s have two portal components on the same portal page. First of them called “sender” allows you to select some value(s). The second component called  “receiver” should then display some data dependent on the current values of the sender whenever a new selection in sender has been done.

Basic schema

In a typical way the dependent data in receiver are taken from a component system or database. In order to avoid the rendering of the whole page again, we can consider the approach in following steps:

No:Step
1)The user selects a new value in the sender component
2)Sender stores his data in the Client Data-Bag
3)Sender raises a new event via Client Side Eventing
4)Receiver, which has subscribed this event, is informed about this incoming event
5)Receiver takes all necessary data from the Data-Bag
6)Receiver starts his own reload, caused by scripting on the client. The data from the client are transferred in the HTTP request to the backend
7)Receiver process his doContent() method on the backend. He takes the values transferred in the HTTP request, decodes and uses them to assembly updated content.
8)The HTTP response is then displayed in the browser to replace out-dated content.

 

The sender needs a JavaScript code which handles the steps 2) and 3). The typical JavaScript coding-stub looks like following example. Either it can be a part of a JavaScript function (function handler) or these calls can be include directly as a handler properties in a HTML Tag (i.e. <BUTTON onclick=”…”>)

Sender JavaScript Sample

EPCM.storeClientData(“myurn”,<key>,<value>);
EPCM.raiseEvent(“myurn”,”onSelect”);

The receiver side needs a JavaScript code, which handles the steps 4), 5) and 6).  The typical example could be as following

Receiver JavaScript sample

function  receiveMyEvent(){
    myReceivedData = EPCM.loadClientData(“myurn”,<key>);
 
    // enhances a query string with the coded event data
    // which will be send to backend.
    location.search = <myReceivedDataAsQueryString>
}
 
// sucbscribe a receiver handler on the sender’s event
subscribeEvent(“myurn”,”onSelect”,receiveMyEvent)
 

Both these JavaScript code should be generated by a proper Java classes, which can easily be instantiated using a dedicated portal service.

Common usage of the package

1) Include the service reference

When implementing sender or receiver using the EpcfToolbox service, you have first to include the corresponding service reference in the component’s profile

ServicesReference=epcftoolbox

2) Include the proper packages in your component

import com.sapportals.portal.prt.runtime.PortalRuntime;
import com.sapportals.portal.prt.service.epcftoolbox.IEpcfToolbox;
import com.sapportals.portal.prt.service.epcftoolbox.IEpcfToolbox;
import com.sapportals.portal.prt.service.epcftoolbox.IClientEventSender;
import com.sapportals.portal.prt.service.epcftoolbox.IClientEventReceiver;

3) Then instantiate the service and the sender or receiver classes using the following calls. Get a service instance in  the component’s doContent methods

IEpcfToolbox myServ = (IEpcfToolbox) PortalRuntime.getRuntimeResources().getService(IEpcfToolbox.KEY);

4) Sample of the usage of the sender in the Java-code

 
      // Instantiate the sender object
      IClientEventSender  mySender =  myServ.getClientEventSender(request,"XURN","XEVENT");
 
      // store all parameter in the sender Object
      mySender.setRawParameter("PAR1","document.xform.x1.value");
      mySender.setRawParameter("PAR2","document.xform.x2.value");
      mySender.setParameter("PAR3","NoEvent");
      mySender.setParameter("PAR4","0815");
 
      // you can then overwrite some parameters
      response.write("<FORM name=\"xform\">\n");
      response.write("<TABLE>\n");
      response.write("<TR><TD>PAR1:</TD><TD>");
      response.write("<INPUT type=INPUT name=x1 value=\"123456\">\n");
      response.write("</TD></TR>\n");
      response.write("<TR><TD>PAR2:</TD><TD>");
      response.write("<INPUT type=INPUT name=x2 value=\"ABCDEF\">\n");
      response.write("</TD></TR>\n");
      response.write("<TR><TD>PAR3:</TD><TD>");
 
      mySender.setParameter("PAR3","Event1");
      response.write("<INPUT type=BUTTON onclick=\""+ mySender.getScript() +"\" value=\"SendEvent1\">\n");
 
      mySender.setParameter("PAR3","Event2");
      response.write("<INPUT type=BUTTON onclick=\""+ mySender.getScript() +"\" value=\"SendEvent2\">\n");
 
      mySender.setParameter("PAR3","Event3");
      response.write("<INPUT type=BUTTON onclick=\""+ mySender.getScript() +"\" value=\"SendEvent3\">\n");
 
      response.write("</TD></TR></TABLE>\n");
      response.write("</FORM>\n");
      response.write("<HR>");
    }
 

In this sample there are 4 event parameters PAR1 – PAR4, that should be transferred shared with the receiver component. The values will be taken either from an JavaScript variables or a DOM reference (PAR1, PAR2), or they are used as fix values (PAR3, PAR4). The getScript()   methods will returns inline JavaScript which can be integrate in the response. When using a HTMLB, you have to pass this generated inline JavaScript on the proper objects (i.e. Form or Button …)

5) Sample of the usage of the  receiver in the Java-code

      // Instantiate one receiver
      IClientEventReceiver  myReceiver  =  myServ.getClientEventReceiver(request,"XURN","XEVENT");
 
      // Let the necessary script blocks generate in the response
      // of the ordinary component content
      response.write(myReceiver.getWrappedScript() );
 
      // Now the response content on the backend can be generated depending on
      // the parameters transmitted in the request from the frontend to backend.
      if (myReceiver.isReceived() ){
         // If the request originates from the frontend/backend data transmission,
         // the isReceived() method returns true. In such case the event parameters
         // can be obtained by getParameter() calls
         response.write("<H3>Event&Data in the current request</H3>");
         response.write("<TABLE>\n");
         response.write("<TR><TD>PAR1</TD><TD>"+myReceiver.getParameter("PAR1") +"</TD>\n");
         response.write("<TR><TD>PAR2</TD><TD>"+myReceiver.getParameter("PAR2") +"</TD>\n");
         response.write("<TR><TD>PAR3</TD><TD>"+myReceiver.getParameter("PAR3") +"</TD>\n");
         response.write("<TR><TD>PAR4</TD><TD>"+myReceiver.getParameter("PAR4") +"</TD>\n");
         response.write("</TABLE>\n");
      } else {
         // If the request doesn't originate from the data transmission,
         // someting else can, i.e. displaing of default screen ...
         response.write("<H3>No Event&Data in the current request</H3>");
      }

In this sample the method getWrappedScript() returns the JavaScript block similar to the example (see Basic schema for Receiver), wrapped in the usual script and comment tags.

When the response contains the event data (isReceived() method will returns true), the data transmitted to the backend can be retrieved using the methods getParamer().

Additional features

Filtering of Events

In some scenarios the sender and receiver component can be the same. This will raise the problem, whether such component should reacts to his own events or not.  The method SetEventFilter allows you explicitly define this behavior using the following constants:

IClientEventReceiver.EVENT_FILTER_ALL  
IClientEventReceiver.EVENT_FILTER_FOREIGN 
IClientEventReceiver.EVENT_FILTER_OWN

If not defined explicitly, the method accept only the incoming events from foreign component, (IClientEventReceiver. EVENT_FILTER_FOREIGN), but not his own. 

Example of the usage:

myReceiver.setEventFilter(IClientEventReceiver.EVENT_FILTER_ALL);

Displaying of message when reloading of content takes a lot of time 

The method setWatingMessage allows you to enable a displaying an message, which is then visible during the reload of the component (Steps 6) – 8) in the Basic schema)

Important Notes:

The message must be localized in the component itself, the service pass it only through.

Only the text using the current stylesheet is displayed via DHTML methods. There is no sand-glass waiting picture !

Example of the usage

myReceiver.setWaitingMessage("Loading the content ...");

Known Restrictions

Both “sender” and “receiver ” components must be configured as iViews with bypassing of iView-Server.  Otherwise the component will try do display the content recursively in the same frame.

Both components “sender” and “receiver” must be on the same portal page rendered in IFRAMES (in the current EP 5.0 done by page builder automatically, in EP 6.0 you have to use isolation mode = URL);

As the event data are passed in the HTTP request in the query string which is a limited size (2KB) you should always use only minimum of necessary parameters. Typically you should pass only the keys (like material number) in the event, but not the depending values (i.e. material description) !

All event data (urn, event name , parameter keys and values) are included in the generated JavaScript code. In order to avoid JavaScript syntax errors, the event data may not contain the JavaScript string delimiters (single or double quote) and also no special characters (like \n \t   etc.).  The following checks are built-in the package:

The factory methods getClientEventSender and getClientEventReceiver  will raise exception when the urn and event name is not in valid range.

The  IClientEventSender methods setParameter and setRawParameter, will simply ignore the parameters and values which are not in the valid range.

If the parameter values are to be passed indirectly using a JavaScript variable  or another DOM reference (IClientEventSender.setRawParameter method),  such variable name is copied in the generated coding as is. There is no check, if the variable really exists in the JavaScript context.

Receiver component has to change his own location (location.search command) in order to cause his own reload.  As this has no effect to the URL which is associated to the iView’s-tray (i.e. expand button), all links associated with this tray will remain associated with the origin URL (without event data) generated by the assembling the page for the first time.

The generated JavaScript code uses Features of the Verstion 1.3 of the JavaScript standard, assuming the possibility scripting in IFRAMES. Therefore the supported browsers are  MSIE 5.0+, Netscape 6.0+. It is strongly recommended to restrict the valid browsers and versions in each iViews