Skip to Content

In my previous blog post we created a restful service that returns with ALV metada and data. Now we will develop a jquerymobile web client that calls this service and represents data in jquery datatables plugin.

Part 1 – Create RESTful service

Part 3 – Visualize ALV Data with Highcharts for iPad

Creating JqueryMobile Web Application

Pre-requisites:

  1. It is assumed that you are already familiar with HTML and the basic javascript usage
  2. Check over jquery ajax: http://api.jquery.com/jQuery.ajax
  3. Check over jquerymobile fundamentals & documentation: http://jquerymobile.com/demos/1.1.1/docs/about/intro.html
  4. Check over datatables usage: http://datatables.net

Steps:

  1. Create jquerymobile web page
  2. Call restful service to get alv data
  3. Parse alv metadata to create columns of datatables
  4. Initialize datatables plugin with alv data

index.html

<!DOCTYPE html>

<html>

    <!–<html manifest=”app.appcache”>–>

    <head>

    <title></title>

    <meta http-equiv=”Content-Type” content=”text/html; charset=UTF-8″>   

    <meta name=”apple-mobile-web-app-capable” content=”yes”/>

    <meta name=”viewport” content=”width=device-width, minimum-scale=1.0, maximum-scale=1.0, user-scalable=no” />

    <link rel=”shortcut icon” href=”images/mysapreport.jpg” />

    <link rel=”stylesheet” href=”css/jqm/jquery.mobile-1.1.1.min.css” />

    <!– DataTables CSS     –>

    <link rel=”stylesheet” type=”text/css” href=”css/datatables/jquery.dataTables.css”/>  

    <link rel=”stylesheet” type=”text/css” href=”css/datatables/ColVisAlt.css”/>

    <script src=”js/jqm/jquery-1.7.2.min.js”></script>

    <script src=”js/jqm/jquery.mobile-1.1.1.min.js”></script>

    <!– DataTables –>

    <script type=”text/javascript” src=”js/datatables/jquery.dataTables.min.js”></script>              

    <script type=”text/javascript” src=”js/datatables/ColVis.min.js”></script>    

    <script type=”text/javascript” src=”js/datatables/TableTools.min.js”></script>    

    <script type=”text/javascript” src=”js/settings.js”></script>

    <script type=”text/javascript” src=”js/table.js”></script>

    <script>

        $.support.cors = true;

        jQuery.support.cors = true;                 

    </script>

</head>

<body>

<div data-role=”page” id=”alv” data-theme=”e”>

    <div data-role=”header” data-position=”fixed”>

        <h1>ALV</h1>

        <a href=”#settings”  data-role=”button” data-icon=”gear” data-theme=”b”>Settings</a>

    </div>

    <div data-role=”content” >

        <div data-role=”fieldcontain”>

            <label for=”transaction”>Transaction:</label>

            <input type=”text” name=”transaction” id=”transaction” value=”” />      

        </div>

        <div data-role=”fieldcontain”>

            <label for=”variant”>Variant:</label>

            <input type=”text” name=”variant” id=”variant” value=”” />

        </div>

        <a href=”javascript:getALV()”  data-role=”button” data-icon=”grid” data-theme=”b”>Call Report</a>      

        <br>

    </div>

</div>

<div data-role=”dialog” id=”settings”>

    <div data-role=”content” >

        <label for=”connectUrl”>Connect to:</label>

        <input type=”url” name=”connectUrl” id=”connectUrl” value=”” data-mini=”true” />

        <label for=”username”>Username:</label>

        <input type=”text” name=”username” id=”username” value=”” data-mini=”true” />

        <label for=”password”>Password:</label>

        <input type=”password” name=”password” id=”password” value=”” data-mini=”true” />

        <br>

        <a href=”javascript:exitSettings()” data-role=”button” data-icon=”delete”>Exit</a>

        <a href=”javascript:saveSettings()” data-role=”button” data-icon=”check” data-theme=”b”>Save</a>               

    </div>

</div>

<div data-role=”page” id=”showDatatable” data-theme=”e” data-add-back-btn=”true” data-dom-cache=”true”>

    <div data-role=”header” data-position=”fixed”>

        <h1 id=”datatableHeader”>ALV</h1>

        <div class=”ui-btn-right”>          

            <a href=”#chartRules” data-role=”button” data-icon=”star” data-theme=”e” data-back=”true”>Chart</a>          

        </div>

    </div>

    <div data-role=”content”>

        <div id=”dynamicDatatableDIV” >          

            <!–<table id=”dynamicDatatable” class=”tbl_basket_style”></table>–>

        </div>

    </div>

</div>

</body>

</html>

Call Restful Service:

function getALV(){

    alvData = [];

    alvMetadata = [];

    $.ajax({

        type: “GET”,             

        url: ‘http://‘ + $(“#username”).val() + ‘:’ + $(“#password”).val() + ‘@’ + $(“#connectUrl”).val() + ‘?tcode=’ + $(“#transaction”).val() + ‘&variant=’ + $(“#variant”).val(),

        data: “”,

        dataType: “jsonp”,

        contentType: “application/javascript”,

        username:$(“#username”).val(),

        password:$(“#password”).val(),       

        jsonpCallback:”jsonp_success”,

        crossDomain: true,

        cache: false,

        timeout: 10000,

        xhrFields: {

            withCredentials: true

        },

        beforeSend: function(xhr, settings){                                          

            $.mobile.showPageLoadingMsg();

        },

        complete: function(xhr, textStatus) {

            $.mobile.hidePageLoadingMsg();

            if (alvMetadata){

                createDynamicTable(getColumnData(alvMetadata),alvData);

                $.mobile.changePage(‘#showDatatable’);

                $(‘#datatableHeader’).text(reportDescription);              

            }

        },

        success: function(sys){      

        },

        error: function( result ){

            if (result.statusText !== “success”){

                alert(‘Error!! Unable to call ALV Report. Please check your settings & SAP connection’);

                $.mobile.changePage(‘#settings’);

            }

        }

    }); // Ajax posting  

}

function JSONP_SUCCESS(result){  

    reportDescription = result.description;

    alvMetadata = result.alvMetadata;             

    alvData = result.alvData;

    //sort ALV metadata according to col_pos

    alvMetadata.sort(function(a,b) {

        return (parseInt(a.col_pos) > parseInt(b.col_pos)) ? 1 : ((parseInt(b.col_pos) > parseInt(a.col_pos)) ? -1 : 0);

    } );

}

Datatables Columns Creation

function getColumnData(alvMetadata){

    var column = new Array();

    var type;

    var just;

    var sclass;

    var visible;     

    var visCount = 0;

    for(i=0;i<alvMetadata.length;i++){

        type = alvMetadata[i].inttype;

        just = alvMetadata[i].just;

        visible = alvMetadata[i].no_out;

        switch (type){

            case ‘D’:

                type = “date”;

                break;

            case ‘N’:

                type = “string”;

                break;      

            case ‘P’:

                type = “numeric”;

                break;

            case ‘I’:

                type = “numeric”;

                break;

            case ‘F’:

                type = “numeric”;              

                break;

            default:

                type = “string”;

                break;

        }

        switch (just){

            case ‘L’:

                sclass = “left-align”;

                break;

            case ‘R’:

                sclass = “right-align”;

                break;

            case ‘C’:

                sclass = “center-align”;

                break;

            default:

                sclass = “left-align”;

                break;

        }       

        if (visible == ‘X’ || visCount > 5)

            visible = false;

        else{

            visible = true;

            visCount++;

        }

        column.push({

            “mDataProp”:alvMetadata[i].fieldname.toLowerCase(),

            “sName”: alvMetadata[i].fieldname,

            “sTitle”: alvMetadata[i].seltext,

            “sType”: type,

            “sClass”: sclass,

            “bVisible”: visible              

        });

    }

    return column;

}

Initialize Datatables

function createDynamicTable(aColumnData,aDataSet){     

    $(‘#dynamicDatatableDIV’).html( ‘<table id=”dynamicDatatable” class=”tbl_basket_style”></table>’ );             

    var alvTable = $(‘#dynamicDatatable’).dataTable( {

        “sDom”: ‘rfCtip’,     

        “bStateSave”: true,//length, filtering, pagination and sorting not change when refresh(cooki)

        “sPaginationType”: “full_numbers”,                      

        “iDisplayLength”: 65536,      

        “oColVis”: {          

            “bRestore”: true                      

        },        

        “bUseRendered”: false,

        “aaData”: aDataSet,      

        “aoColumns”: aColumnData

    } );  

}

Test

After publishing service on your own system, you can call it only by editing settings in MySapReport . Web client saves your settings on localstorage except password. Password is saved on sessionstorage. So don’t need to edit connection url and username in each visit of client application but password is asked for each session.

You can run demo with empty settings.

If you want, you can publish client as BSP pages on sap ITS. For step by step instructions read John Moy’s blog .

You can find all sources codes on https://github.com/basarozgur/MySapReport

Screen Shots:

   Transaction code entry

/wp-content/uploads/2012/09/m1_140952.jpg

   Settings

/wp-content/uploads/2012/09/ms_141014.jpg

 

   Report Data

/wp-content/uploads/2012/09/dt_141015.jpg

  

   Datatables Show / Hide Columns

/wp-content/uploads/2012/09/sh_141016.jpg

To report this post you need to login first.

5 Comments

You must be Logged on to comment or reply to a post.

  1. Steve Oldner

    Amazing! Wow!  Just been learning and using BSP + jQueryMobile for a payroll app (John Moy inspired) and launchpad BUT I still have a tremendous amount of background to learn.

    Did I see correctly that you used Python?

    (0) 
    1. Basar Ozgur Kahraman Post author

      Hi Steve,

      Only jquery and compatible plugins are used. Html+Css+Javascript enough for client side.

      If you check whole blog series, you will find all sources that you need. please feel free to ask questions at any point..

      (0) 
      1. Steve Oldner

        It was over in your Github account where I saw the , main.py.

        I do have a question about using the cache manifest with BSP. Specifically about linking to the jquery, jqueryui and jquerymobile links.  How do I use/code that in a BSP?  Currently I am  linking stylesheet to http://code.jquery…css and the scripts to http://code.jquery….min.js and mobile.js.  From what I have read, I can copy these to the MIME and use them from there.  But haven’t found example code on how to use mime at a public level.

        Since our project is primarily focused on mobile html5, having the jquery coding in cache would simply and speed it up.

         

        Could you point me somewhere? Or indicate what I missed?

        Thanks!

        (0) 

Leave a Reply