Liquid UI - WS Reference Library

System Variable: _title in Tree based Multilevel Screens


Purpose

Create UI dynamically on the same screen based on data passed as an array by converting it to hierarchical tree structure.


User Interface

Log into SAP and on the SAP Easy Access Screen click on the first pushbutton and navigate all the way to land on MM02 screen.


 

 

 

 


Liquid UI Script

//SAPLSMTR_NAVIGATION.E0100.sjs


load('commonFunctions.sjs');

// This data may come from -
// a. Fixed File
// b. RFC Call
// The data from File or RFC needs to be built into an array similar to below
// "Parent,Child,Value,Tcode"
testData = [];
testData[0] = "1000,Uni Coiler A,K1-A,";
testData[1] = "Root,1000,K1,";
testData[2] = "1000,Uni Coiler B,K1-B,";
testData[3] = "2000,TEST_CASING A,100-100,";        
testData[4] = "1000,Uni Coiler C,K1-C,";
testData[5] = "Uni Coiler A,Uni Coiler A South East,K1-E-SE,";
testData[6] = "TEST_CASING A,Boiler 1,100-200,MM03";
testData[7] = "Uni Coiler A,Uni Coiler A North East,K1-E-NE,";
testData[8] = "Uni Coiler A South East,Uni Coiler A South East 1,K1-E-SE-1,";
testData[9] = "Uni Coiler A South East 1,Uni Coiler A South East 1A,K1-E-SE-1A,MM02";
testData[10] = "TEST_CASING A,Boiler 2,100-300,";
testData[11] = "Uni Coiler A South East 1,Uni Coiler A South East 1B,10030388,IW22";
testData[12] = "Root,2000,100,";
testData[13] = ",Root,,";        // ROOT - Not displayed on screen
testData[14] = "2000,TEST_CASING B,100-100,IW23";    
testData[15] = "3000,New Hire,1001-10,PA40";    
testData[16] = "Root,3000,,";    

// User Interface
clearscreen();
if(isBlank(first_time)){
    first_time = "X";
    createTree(testData,",");        // Pass seperator to the function and use that
}
drawUI();

//commonFunctions.sjs

// Function to trim blank spaces at the end of the string
String.prototype.trim=function(){return this.replace(/^\s+|\s+$/g,'');}
                     
// Function to check if the string value is blank
function isBlank(jvar){
   if(typeof jvar == 'string') {
      jvar = jvar.trim();
   }
   if(typeof jvar == 'undefined') {
      jvar = '';
   }
   return(jvar == 'undefined' || jvar == undefined || jvar == null || jvar == "" || jvar == void 0);
}

// Function to paint the User Interface
function drawUI(){
    if(!isBlank(current.getChildren())){
        title(current.name);
        for(x=0; x<current.getChildren().length; x++){
            pushbutton([(x+1)*2,10], current.children[x].name, "?", {"size":[2,30], "process":changeCurrent, "using":{"new_current":current.children[x]}});
        }

        // If the option to go back is possible
        if(current.getParentNode() != null){
            pushbutton([TOOLBAR],"@9S@BACK","?", {"process":changeCurrent, "using":{"new_current":current.getParentNode()}});
        }
    } else{
        tcode = current.txcode;
        value = current.val;
        if(!isBlank(tcode)){
            enter({"process":navigateToTransaction, "using":{"l_tcode":tcode, "l_val":value}});
        } else{
            message('E: No transaction specified');
            first_time = '';
            enter('?');
        }
    }
}

// Function to perform some action on the last level
// Navigates to the transaction code and uses the value passed
function navigateToTransaction(param) {
    var tcode = param.l_tcode;
    first_time = '';
    enter('/n'+tcode);

    onscreen '*'                // Rest of the navigation logic based on Transaction code
        title(_title);
        if(tcode == 'MM02'){        
            set('F[Material]',param.l_val);
        } else if(tcode == 'MM03'){        
            set('F[Material]',param.l_val);
            goto MM03_PROCESS;
        } else if(tcode == 'IW22'){        
            set('F[Notification]',param.l_val);
            goto IW22_PROCESS;
        }    
        enter('?');
        goto SCRIPT_END;    
    
    onscreen 'SAPLMGMM.0600'
    MM03_PROCESS:;
        enter();
        goto SCRIPT_END;
        
    onscreen 'SAPLIQS0.0100'
    IW22_PROCESS:;
        enter();
    
    SCRIPT_END:;
}

// Function to initialize the Node containing name, value and transaction code
function Node(name,val,txcode){
    this.name = name;
    this.val = val;
    this.txcode = txcode;
    this.children = [];
    this.parent = null;
    
    this.setParentNode = function(node){
        this.parent = node;
    }
    this.getParentNode = function(){
        return this.parent;
    }
    this.addChild = function(node){
        node.setParentNode(this);
        this.children[this.children.length] = node;
    }
    this.getChildren = function(){
        return this.children;
    }
}

// Function to refresh and paint the new screen based on button click
function changeCurrent(param){
    current = param.new_current;
    enter("?");
}              

// Function which creates the tree structure from an array and the data seperator passed to it
function createTree(arr,seperator){
    // Create the root
    for(i=0; i<arr.length; i++){
        arrTemp = arr[i].split(seperator);
        if(isBlank(arrTemp[0])){
            rootNode = new Node(arrTemp[1],arrTemp[2],arrTemp[3]);
            arr.splice(i,1);        // Delete the element in the array
            break;
        }
    }
    
    index = 0;
    while(arr.length > 0){          // While elements are in the array
        if(isBlank(arr[index]))        // Reached the end of the data array, break out of while loop
            break;
            
        arrTemp = arr[index].split(seperator);
        
        result = inTree(rootNode,arrTemp[0]);        // Check whether the Parent is in the Tree
        if(!isBlank(result)){
            result.addChild(new Node(arrTemp[1],arrTemp[2],arrTemp[3]));        // Add the child
            arr.splice(index,1);                // Delete the element in the array
            index = 0;
        } else{
            index++;
        }    
    }    
    current = rootNode;
}

// Function which checks to see if the Parent Node exists in current tree
function inTree(rtnode,parent){
    var nodeStack = [];
    nodeStack.push(rtnode);

    while(nodeStack.length > 0){                // Always 1 as 'nodeStack' contains the ROOT node
        processNode = nodeStack.pop();            // 'processNode' points to the beginning of the node
    
        if (processNode.name == parent) {
            return processNode;                    // Returns once the node is found and adds to the tree
            break;
        } else if (processNode.children.length>0) {        
            for (ii = 0; ii < processNode.children.length; ii++) {
                nodeStack.push(processNode.children[ii]);        
            }
        }
    }
    return '';                                    // Return an empty string if parent not found in the tree
}