I’ll give it a try and submit my Weblog to the SDN: End of the Year SDN POINTS BLOW OUT!! Contest () initiated by Craig Cmehil (/people/craig.cmehil/blog). With this hack you get a BSP Page which displays a flicker-free updated chart of how many SDN Users are currently online in the Forum.
This example will only run in Safari and Firefox 1.5. SAP's official Charting tool is IGS (Internet Graphics Server). You find a Example how to use the IGS in the Weblog:
thomas.jung3/blog/2004/08/31/bsp-150-a-developer146s-journal-part-x--igs-chartingfrom Thomas Jung (/people/thomas.jung3/blog).
First I had to retrieve the actual number of Forum Users. This is done by using the HTTP_CLIENT Class which is described in an excellent example in Brian McKellar’s (/people/brian.mckellar/blog) Weblog
BSP Programming: RSS = HttpClient + XML + XSLT.0.1.
0.2.
JKL.ParseXML- parse remote XML file into JavaScript object.0.1.
0.2.
Finally the Canvas Front end was implemented by using the Charting Example (http://overstimulate.com/projects/canvas/) of Jesse Andrews (http://overstimulate.com/).</li>
</ul>
I’ve built this example on a Web AS ABAP 6.40. The Web AS must have Internet access so he can open the URL http://forums.sdn.sap.com/online.jspa.
To store the retrieved Data I’ve created a new database table and called it “ZSDNFORUMUSERS”. It consists of this fields:
Field | Key | Data element | Data Type | Length |
MANDT | X | S_MANDT | CLNT | 3 |
ERZET | X | ERZET | TIMS | 6 |
ERDAT | X | ERDAT | DATS | 8 |
USERS | INT4 | 10 |
This table is filled by the Program “ZGET_SDN_FORUM_USERS” which I’ve run as a background job every 2 minutes:
REPORT zget_sdn_forum_users.
*
Retrive HTML
*
DATA: url TYPE string,
http_client TYPE REF TO if_http_client,
return_code TYPE i,
content TYPE string,
users TYPE i,
wa_users TYPE zsdnforumusers.
HTTP URL
url = 'http://forums.sdn.sap.com/online.jspa'.
cl_http_client=>create_by_url( EXPORTING url = url
IMPORTING client = http_client ).
http_client->send( ).
http_client->receive( ).
http_client->response->get_status( IMPORTING code = return_code ).
content = http_client->response->get_cdata( ).
http_client->close( ).
*
Find 'There are' and ' user(s) online.'
*
DATA: dummy TYPE string.
IF content CS ' There are ' AND content CS ' user(s) online.'.
SPLIT content AT 'There are ' INTO dummy content.
SPLIT content AT ' user(s) online.' INTO dummy content.
ENDIF.
wa_users-mandt = sy-mandt.
wa_users-erzet = sy-uzeit.
wa_users-erdat = sy-datum.
wa_users-users = dummy.
*
Save the Data into ZSDNFORUMUSERS
*
INSERT INTO zsdnforumusers values wa_users.
IF sy-subrc = 0.
COMMIT WORK AND WAIT.
ELSE.
WRITE: 'Could not append line'.
ENDIF.
</pre>
In Transaction SE80 I created a BSP Application called it “ZSDNFORUMUSERS”. The application consists of two parts. The Backend is split into two parts. Part one retrieves the history of the last 24 Hours to fill the chart initially. Part two retrieves the actual number of Forum Users and provides this value for the Front end in a simple XML Structure. The Front end calls the Backend via XmlHttpRequest.
Part 2 of the backend is also a BSP Page with Flow logic called “usersonline24h.xml”. It has a page attribute called “it_users” which if from type tt_users. This type is defined in the Types tab:
TYPES: tt_users TYPE TABLE OF zsdnforumusers.
the handler is called whenever a request is made for a particular page
it is used to restore the internal data structures from the request
DATA: datefrom LIKE sy-datum.
datefrom = sy-datum - 1.
SELECT * FROM zsdnforumusers INTO TABLE it_users
WHERE erdat >= datefrom
ORDER BY erdat ASCENDING erzet ASCENDING.
</pre>
Part 1 of the backend is also a BSP Page with Flow logic called “usersonline.xml”. It has a page attribute called “users” which if from type I.
the handler is called whenever a request is made for a particular page
it is used torestore the internal data structures from the request
CLEAR: users.
DATA: it_users TYPE TABLE OF zsdnforumusers,
wa_users LIKE LINE OF it_users.
Read Users Online from History Table
SELECT * FROM zsdnforumusers INTO TABLE it_users
ORDER BY erdat DESCENDING erzet DESCENDING.
IF sy-subrc = 0.
READ TABLE it_users INTO wa_users INDEX 1.
users = wa_users-users.
ENDIF.
</pre>
<p>The front-end is also a BSP Page. Here is only the Layout filled with this Code:</p>
<pre class="sapCode">
<%@page language="abap" %>
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>How many SDN Forum Users are online?</title>
<style type="text/css">
#windowcontainer
.chartLayer
#high {font-family: arial; left: 10px; top: 4px }
#low {font-family: arial; left: 10px; top: 479px }
#minutes {font-family: arial; left: 712px; top: 500px }
(d+) </;
/@CC_on @/
/*@if (@_jscript_version >= 5)
// JScript gives us Conditional compilation, we can cope with old IE versions.
// and security blocked creation of the objects.
try {
xmlhttp = new ActiveXObject("Msxml2.XMLHTTP");
} catch (e) {
try {
xmlhttp = new ActiveXObject("Microsoft.XMLHTTP");
} catch (E) {
xmlhttp = false;
}
}
@end @*/
if (!xmlhttp && typeof XMLHttpRequest!='undefined') {
xmlhttp = new XMLHttpRequest();
}
var livectx = document.getElementById('live-chart').getContext('2d');
var chartData = [];
function updateChart( newVal ) {
chartData.push( parseInt(newVal) );
if (chartData.length > width) {
chartData.shift();
}
var maxVal=height;
for (var i=0; i<chartData.length; i++)
if (chartData[i] > maxVal) maxVal=chartData[i];
// Draw Border
livectx.beginPath();
livectx.clearRect(0,0,width,height);
livectx.rect(0,0,width,height);
// Go to Starting point
livectx.moveTo(0,height-(height*chartData[0]/maxVal));
for (var i=1; i<chartData.length; i++) {
// Draw Line
livectx.lineTo( i, height-(height*chartData[i]/maxVal) );
}
livectx.stroke();
}
function getStats() {
xmlhttp.open("GET", g_urlsingle, true);
xmlhttp.onreadystatechange=function() {
if (xmlhttp.readyState==4) {
updateChart( scrapper.exec(xmlhttp.responseText)[1] );
document.f.users.value = scrapper.exec(xmlhttp.responseText)[1];
setTimeout('getStats()', 120000 );
}
}
xmlhttp.send(null)
}
// Load 24h XML
var xml = new JKL.ParseXML( g_url24h );
var data = xml.parse();
for (var i=0; i < data.sdnusers.users.length; i++) {
chartData.push( parseInt(data.sdnusers.users[i]) );
if (chartData.length > width) {
chartData.shift();
}
}
getStats();
</script>
</body>
</html>
</pre>
Before you can run the BSP Application you have to upload the
JKL.ParseXMLas a mime-object. Then you need Firefox 1.5 (http://www.mozilla.com/firefox/) to run the application. It will look like: