Monday, 2 February 2015

Siebel Open UI: What you can Get from Applet PM

Have you ever wondered what are all the objects, functions, arrays, constants and values we can Get and make use in an Applet PM or PR file. Well, I tried to find out all the functions and variables we can use for rendering and business logic in Open UI. 

I am talking about Get function in PM which can be accessed from PR also (using this.GetPM() function). There are many variables which can be retrieved from an Applet PM. By digging down to the JavaScript files, I finally found the list of variables that can be obtained from Applet. Below is the list of all the variables. This is not the complete list. Based on type of applets (List, Tree, Calendar etc), the list grows. But these are common list of variables.


"GetName","GetId","GetVarName","GetFullId","GetTitle","GetControls","GetActiveControl","GetSelection","GetRecordSet","GetDefaultFocusOnNew","GetAppletSummary","GetAppletLabel","IsInQueryMode","GetQueryModePrompt","GetDefaultFocusOnQuery","GetMapFields","GetPrsrvControl","GetUIEventMap","IsPure","GetScrollDir","GetScrollAmount","GetMode","GetBusComp","GetRowListRowCount","GetWSEndRowNum","GetNumRows","IsNumRowsKnown","GetObjectType","GetRepstrName","GetUIName","GetRawRecordSet","GetParentApplet","IsActive","IsEditable","HasPickError"

Now I tried to get all the variables in a debug window and see what these variables hold. Here is the screenshot.




Well, most of the names are self explanatory. I have explained few functions below. 

GetName : gets the applet name. 
GetId : gets the applet order in the view (1 from top)
GetFullId : gets the applet's html id
GetTitle: gets the applet title defined in Tools
GetControls: gets the controls objects in the applet (I will discuss about the control objects in another post)

GetActiveControl : gets the active control object

GetSelection: gets the index of selected record starting from 0 for first record
GetRecordSet: Array of records in the applet

GetRawRecordSet : Array of records in the applet including the hidden columns

GetMode: gets applet mode like Base, Edit, Edit List
GetBusComp: gets the buscomp object. This is very useful for doing business layer logic

GetRowListRowCount: gets the max number of records that can be shown in applet. This is applet's HTML no of rows property. If we click on show more, this value changes in list applet
GetNumRows: Get the number of rows showing in the applet. This is not the record count of all the records in the applet.
IsActive : if the applet is selected applet in the view, it returns true
IsInQueryMode: true if applet is in query mode

You can test this in browser console. Refer below.





I am still trying to find out about other variables and functions. I will keep posting about this. 

I have created a code snippet to get all the properties for an Applet. Check this out Post on Get Properties

Understanding Siebel Open UI Javascript

JavaScript is a programming language understood by almost all the web browsers. JavaScript is an Object Oriented programming language. In Open UI, we use JavaScript objects to render and perform actions in the User Interface. This actually needs understanding of OOPS concepts and a little bit of JavaScript

But what is an object? Well, everything that we define as an entity that can be individually identified is an object. For example, in a Siebel view, applet is an object. Each object has properties and methods. For example, applet has a name (property) and it can do an action like invoke method (method).
Its features include

    1.   Inheritance: We can create a hierarchy of objects and the child objects inherit the parent features. If you are creating a custom Presentation Model or Physical Renderer, we are using Extend statement which defines the inheritance.

    2.   Polymorphism: The same task can be done separately by separate objects. Different types of applets perform same action in different ways.

    3.   Encapsulation: Binding code and data together and making them into one unit. We can use the encapsulated code to create multiple objects of same type.

In Open UI client, everything you see in UI is an object, created by the JavaScript files that Siebel loads. The view is an object, the applets in the view are child objects and the controls in the applets are child objects to applets.

For example, if you are in a view, each applet is an object. The object is created during run-time by accessing JavaScript files. Let us say we are navigating to Account List View, once the view is clicked, the definition of applets in the view is fetched from SRF. It contains two applets SIS Account List Applet and SIS account Form Applet. Now, the application will check if there is a manifest entry for the applets in Manifest administration screen. If not found, it will load default Presentation model and Physical Renderer files for these applets. If found, it will download the files on top or default files (because we use extend in our script). These files will render and contain the behaviour of Applet objects.

An example script can be explained as below.

if( typeof( SiebelAppFacade.CustomPM ) === "undefined" ){
    SiebelJS.Namespace( "SiebelAppFacade.CustomPM" );
   
// check if CustomPM is already present. If not, name our present code as CustomPM . Namespace is nothing but giving name to our object.

    define("siebel/custom/CustomPM", [], function () {
        SiebelAppFacade.CustomPM = ( function(){
            function CustomPM ( proxy ){
                SiebelAppFacade.CustomPM.superclass.constructor.call( this, proxy );
            }
            SiebelJS.ExtendCustomPM , SiebelAppFacade.PresentationModel );
// CustomPM is an extension or child or PresentationModel 
            CustomPM.prototype.Init = function(){
                SiebelAppFacade.CustomPM.superclass.Init.call( this ); 
// call super class functions. This calls SiebelAppFacade.PresentationModel functions. 

//.........write your custom code here..................//
            };
            return CustomPM;
        } ());
        return "SiebelAppFacade.CustomPM";
    });

}

So, any PM or PR we write, we extend existing functionality and on top of that we add our custom functionality.

Wednesday, 21 January 2015

Siebel Open UI Mobile Simulation

If you are planning to implement Open UI mobile, you probably might be wondering how to unit test mobile application in your local machine. Well, if you open mobile client in a desktop browser, it will show you the application in normal mode not in mobile mode. 

If you had followed the instructions in bookshelf, you probably might have set the parameter  SupportedMobileBrowser ="Tablet:iPad,Android-Chrome-GT-P7510,Android-Chrome-Nexus,Android-Chrome-Micromax P500(Funbook),webOS,MSIE-Windows NT-Touch,MSIE-Windows NT-ARM|Phone:iPhone,iPod,Android-Chrome-Mobile,MSIE-Windows Phone,BB10-Mobile"

This means that your application supports these tablet browsers Pad,Android-Chrome-GT-P7510,Android-Chrome-Nexus,Android-Chrome-Micromax P500(Funbook),webOS,MSIE-Windows NT-Touch,MSIE-Windows NT-ARM and these phone browsers iPhone,iPod,Android-Chrome-Mobile,MSIE-Windows Phone,BB10-Mobile.


So, to test the mobile application, you need to simulate these browsers. Let me give you an example to simulate this for iPhone.

Open your safari browser, check if the developer menu is available or not. 



If you don't see this, go to Edit --> Preferences,



In advanced, check Show Develop menu in menu bar

Now in Develop menu, select the user agent. 



Now the browser behaves like iPhone or iPad browsers. By doing this, you can set the browser mode and unit test in local machine. This is quite useful for developers to test while developing mobile applications.

Open your dedicated client with safari (/b argument in client) and do above setting to test mobile applications. Hope this helps!!

Wednesday, 14 January 2015

Siebel Open UI: Right Click Menu in Applets

If you have been using Open UI for a while, you can list out many differences you observe from HI client and Open UI client. One difference is if you right click on a list applet, it does not open the menu as it did in HI client. If you are looking to make this work similar to HI client, this post is for you.

Below is the PM code to open the applet menu on right click on Applet.
---------------------------------------------------------------------------------------------
if( typeof( SiebelAppFacade.openmenupm ) === "undefined" ){
    SiebelJS.Namespace( "SiebelAppFacade.openmenupm" );
    define("siebel/custom/openmenupm", [], function () {
        SiebelAppFacade.openmenupm = ( function(){
var consts  = SiebelJS.Dependency( "SiebelApp.Constants" ); 
            function openmenupm( proxy ){
                SiebelAppFacade.openmenupm.superclass.constructor.call( this, proxy );
            }
            SiebelJS.Extend( openmenupm, SiebelAppFacade.ListPresentationModel );
            openmenupm.prototype.Init = function(){
                SiebelAppFacade.openmenupm.superclass.Init.call( this );
this.AddMethod( "ShowSelection",  SelectionChange, { sequence : false, scope : this } );

            };

function SelectionChange(){
var FullId = this.Get("GetId"); // get applet Id

$(".ui-jqgrid-btable").mousedown(function(event){
if(event.which == 3) //this is the right click event on table body
{

$("#s_at_m_" + FullId).click(); // simulate click on the menu object
return false;
}
});
$(function () {
 $(".ui-jqgrid-btable").bind("contextmenu",function(e){
e.preventDefault(); // prevent the right click browser menu to open like view source, inspect element
});
 });
};
            return openmenupm;
        } ());
        
return "SiebelAppFacade.openmenupm";
    });

}
------------------------------------------------------------------------------------------------------------
This code is working fine but please test this thoroughly if you are trying to use it in your application. 

The only issue is this PM opens the menu of the Applet as if the user clicked on the Menu button. The only difference is that the menu opens near the menu button and not at the location of mouse click. This can be taken care by setting the menu object's top and left coordinates like below. You can try and see if the code similar to below can be used to set the coordinates. 
---------------------------------------------------------------------------------------------
var y = event.clientY; // get current click Y coordinate
var x = event.clientX; // get current click X coordinate
$("#s_at_m_" + FullId).click(); // open Menu
var off = $("#s_at_m_" + FullId).offset().top; // get the height of menu button
y = y - off; // calculate the Y of the menu click with respect to Menu button
$(".siebui-appletmenu").css("position","absolute");
$(".siebui-appletmenu").css("top",y);
$("siebui-appletmenu").css("left",x); // set the coordinates
return false; // this is a psuedo code and it works for y coordinate, x coordinate is not working.. give it a try and try opening the menu at the click location
---------------------------------------------------------------------------------------------
Well this is not full functional code, but give it a try to open the menu at the click coordinates. 

So, we can make the Applet Menu to open on right click of the Applet. If you have a requirement to make the applet work similar to HI mode, this code will take care of it. 

Hope this helps!!

Saturday, 3 January 2015

Upgrading to Open UI

Are you planning to upgrade to Siebel Open UI!! This post might help you!!

I am going to discuss about few product issues observed in Open UI. 

Behaviour and Performance: Do not expect Open UI to work the same way as ActiveX application. Open UI and ActiveX applications are based on different technologies. Open UI runs on JavaScript plug-ins and ActiveX application uses ActiveX objects which are proprietary IE plug-ins. Though Open UI is built to provide the same functionality as earlier, it might behave differently. Open UI is comparatively slow than ActiveX client. This is because every UI element needs a JavaScript file loading to function and render in UI. 

Open UI provides you the ability to modify any UI object and functionality. If you are well versed in CSS, JavaScript and JQuery you can fix most of the UI product issues. But remember to test all your changes rigorously.

Below are some product issues.

1. Blank screen on login - If you see a blank screen on login for the first time, replace the srf with a new full compile file. If you are seeing this issue even after the full compile, check your browser console. You might observe an error related to customizations to JS files. Note that latest patch set on 8.1.1.11 is not working in IE8. You will see a blank screen in this case.

2. MVG applets are blank - If you see this issue, sett the Open UI object manager component parameter AppletSelectStyle to Applet Select

3. Set Profile attribute in JS or Browser scripts - Set Profile Attribute is not allowed in JS files or Browser scripts as a fix to security defect. To enable this, set the Open UI object manager parameter EditProfileAttr to TRUE. If you are using HI client, then also you need to set this parameter for browser scripts to work. This is applicable to versions 8.1.1.9 and above.

4. Control Labels wrapped to next line - If you are using long labels in UI, they will get wrapped to new line. To prevent this, 

In theme-base.css modify the below line from pre-wrap to no-wrap
-------------------------
div.mceGridLabel {white-space: no-wrap;}

5. Side by Side applets render beyond viewable area - In some views, for e.g., Views with 50-50,25-75 templates, side by side applets are rendering beyond the viewable area. User has to scroll to right to view the applets. 
The issue is resolved by modification to the web template parameter: "table-layout: fixed" in the view SWT file.

6. SI mode applets do not render in Open UI - In home page you will see the error "why can't i see this applet? open ui cannot display this type of applet contact system administrator" in salutation applet. This is because it is a SI mode applet and they do not work in Open UI. You need to recreate or modify the applets to HI mode. 

7. HTML captions does not work as earlier - In some cases, HTML tags in controls do not work as expected. You can move the HTML attributes to a custom PR file to render as expected. Test all the objects that had html embedded.

8. List Applet column headers behave differently - Sometimes the list applet column headers are aligned differently (right or left) compared to ActiveX client. This may cause another issue for which we have a fix to move the label to align left.

You can make the column alignment uniform across the application by making below change.

Add "text-align:left;" to \23030\SCRIPTS\3rdParty\jqGrid\current\css\ui.jqgrid.css file under the block ".ui-jqgrid .ui-jqgrid-htable th div", which updated all list applets header to left.

If you are trying to resize the column width by dragging the column header, drag it only horizontally, if you move your mouse down to the table, the control will get lost. It is a minor user issue but users do complain about this sometimes.

9. Import or Export XML files - In open UI, writing an XML file to a location, importing or exporting workflow XMLs etc will work only with temp folder. To make this work for other locations, use below cfg parameter. Provide a list of locations with semi colon seperated list. If you face the error with code SBL-EAI-50228 anywhere, this might be the solution for the issue.

[EAIFileTransportConfigSubsys]
EAIFileTransportFolders = D:\TEST;D:\FS

For server, Navigate to Administration - Server Configuration > Enterprises > Parameters > set "EAI File Transport Folder List" (alias EAIFileTransportFolders), i.e.:

    EAI File Transport Folder List = D:\TEST;D:\FS

10. Application unresponsive - In Open UI, if you are doing an action that takes more than 30 seconds to complete, after 30 seconds you will get the cursor back but the application will not respond to your action. If you feel it is ok to have performance of more than 30 seconds (30000 milliseconds), modify the loadindicator.js file. 

In loadindicator.js, note that 30000 milliseconds (30 seconds) is hardcoded: you can increase this value

    var that = this;
    if( this.m_gbusy > 1 && config.timeOut ){
        clearTimeout(this.timeoutid);
        this.timeoutid = setTimeout( function(){
              that.timeout = true;
              that.Free();
            }, 30000);
        return this;

    }

I will keep adding more items to this list. 

Tuesday, 4 November 2014

Siebel Open UI : Profile Attributes vs Browser Cookies

Profile Attribute Security

If you have used Siebel profile attributes, you know that these are name-value pairs used to store any information including user profile and retrieved any time during the application session. If the session is closed, the profile attributes will get nullified. This is custom functionality in HI client. 

In earlier versions like 8.1.1.3 or before, we can set profile attributes by entering code like the below line in browser address bar. 

Javascript: theApplication().setprofileAttr("ABC","ABC");

This has been disabled to fix security issues. Now that Oracle has identified security vulnerabilities in the browser scripting, in Open UI, they have disabled setting profile attributes. But for users who are OK with security constraints, the profile attribute setting from browser scripts are enable after setting server parameter EditProfileAttr = TRUE. Now, the security reasons for disabling the profile attribute setting are unknown, but if it is a consideration for you, we have another option in Open UI. 

Browser Cookies

We might have heard of this term many times, but a few really know about these. Browser cookies are name value pairs of data that a browser saves from the sites the user visit. Follow this link to know more about cookies.

Now, let us observe the similarities between Profile attributes and cookies. 

1. Scope: Both are name value pairs, profile attributes are used almost everywhere in application like browser scripts, server scripts and business services or workflows. You do not need a browser session for profile attributes to work. But, cookies need a browser session. They work only for javascripted objects like PM, PR or postload.js or preload.js and so on. 

2. Security: Cookies are vulnerable to attacks from hackers or people in same network who are trying to steal information. But, they are secure if you are using them to write non-sensitive information. If you are writing a view name in cookie, it is fine but do not consider saving phone number, credit card information etc in cookies. There are ways to create secure cookies. Profile attributes have some security issues when used in browser script.

3. Life time: Profile attributes get nullified after session is closed. Cookies on the other hand has a life time. We can set the end date of a cookie to a future date. But, each browser stores cookies in a separate location. There are ways to share cookies across browsers, but this is not in the scope of this post. If you clear your browser cookies, the cookies get deleted even when you have a session open. 

Overall, for a Siebel developer, Profile attributes is the preferable option. But web developers will look to use cookies as much as they can. Siebel is in a phase of moving to a web standard application with Open UI and cookies are going to play their role in future. It would be interesting to see how useful cookies are going to be when used in Open UI.

Sunday, 2 November 2014

Siebel Open UI Vertical Scrollbar Continued..

Here is the final version of the PR to move the List Applet horizontal play bar to vertical scrollbar. The PR is tested for basic functionalities like query, resize, save record etc. I have fixed another issue where the list applet header getting aligned with list columns in the script.


if( typeof( SiebelAppFacade.vscrollpr ) === "undefined" ){

    SiebelJS.Namespace( "SiebelAppFacade.vscrollpr" );

    //Module with its dependencies


    define("siebel/custom/vscrollpr", ["siebel/jqgridrenderer"], function () {
        SiebelAppFacade.vscrollpr = ( function(){
            function vscrollpr( pm ){
                SiebelAppFacade.vscrollpr.superclass.constructor.call( this, pm );    
            }
            SiebelJS.Extend( vscrollpr, SiebelAppFacade.JQGridRenderer );
   vscrollpr.prototype.Init = function () {
            SiebelAppFacade.vscrollpr.superclass.Init.call(this);    
            };
   vscrollpr.prototype.ShowUI = function(){
                SiebelAppFacade.vscrollpr.superclass.ShowUI.call( this );
     var currbwidth = $(".ui-jqgrid-bdiv").width(); //get current body width
     var btabwidth = currbwidth - 60; // provide 60px space for scroll bar
var currhwidth = $(".ui-state-default.ui-jqgrid-hdiv").width(); // get current header width
var htabwidth = currhwidth - 60; // provide 60px space for scroll bar
$(".ui-state-default.ui-jqgrid-hdiv").css("width",htabwidth); // set header width
$(".ui-state-default.ui-jqgrid-hdiv").css("float","left"); // float it to left
     $(".ui-jqgrid-bdiv").css("width",btabwidth); // set body width
     $(".ui-jqgrid-bdiv").css("float","left");   // float it to left
     var html = $(".ui-pager-control").html(); // get the play bar html
     $('.ui-pager-control').appendTo('.ui-jqgrid-view'); // remove the playbar and append it to grid 
     $(".ui-pager-control").css("float","left"); // float it to left
     $(".ui-pager-control").css("width","60"); // set playbar width to 60 px;
     $(".ui-pager-control").css("-ms-transform","rotate(90deg)"); // rotate 90 degrees in IE
     $(".ui-pager-control").css("-webkit-transform","rotate(90deg)"); // rotate 90 deg in chrome
     $("span.ui-separator").parent().css("width","45"); // set separator width to 45px. this should be calculated based on height of applet
            };       
  vscrollpr.prototype.resize = function( )
          { // recalculate the widths after resize
 SiebelAppFacade.vscrollpr.superclass.resize.call( this );  
var currbwidth = $(".ui-jqgrid-bdiv").width();
     var btabwidth = currbwidth - 60;
var currhwidth = $(".ui-state-default.ui-jqgrid-hdiv").width();
var htabwidth = currhwidth - 60;
$(".ui-state-default.ui-jqgrid-hdiv").css("width",htabwidth);
$(".ui-state-default.ui-jqgrid-hdiv").css("float","left");
     $(".ui-jqgrid-bdiv").css("width",btabwidth);
     $(".ui-jqgrid-bdiv").css("float","left");   
     var html = $(".ui-pager-control").html();
     $('.ui-pager-control').appendTo('.ui-jqgrid-view');     
     $(".ui-pager-control").css("float","left");
     $(".ui-pager-control").css("width","60");
     $(".ui-pager-control").css("-ms-transform","rotate(90deg)");
     $(".ui-pager-control").css("-webkit-transform","rotate(90deg)");
     $("span.ui-separator").parent().css("width","45");
 }
return vscrollpr;
    } ());
        return "SiebelAppFacade.vscrollpr";
    });
}



Note: The code needs full testing before implementing. Also, I have hardcoded the value in below line. You need to do the calculation in this case for list applets with different heights.
$("span.ui-separator").parent().css("width","45");

Disclaimer: This is not production ready code. Do not use this code without proper testing. The JQGrid model provides this scroll bars by default as horizontal playbars. So, this is vanilla and it is not a good idea to modify it.