Quantcast
Channel: siebel open ui – Siebel Unleashed
Viewing all 32 articles
Browse latest View live

Siebel Open UI – MouseOver Tooltips – Solution details

$
0
0

In this post I will explain the details of the solution to implement Mouse Over tooltips in Siebel UI using View PR. This was inspired by Jason’s article posted almost an year ago and some of the code has been used as it was provided in the post. So, I would like to thank Jason for sharing the approach and initial code, with us to make it possible.

There are two part to the solution.

  1. Tooltip Data
  2. View PR

So, Lets get started.


Tooltip Data: Tooltip data stored in text file using JSON format. This file is located it in same folder (siebel/custom) as the JS File. The data is hierarchical data with Top level object being the “View” followed by the “Applets” for which we wanted to display tooltip and finally the “Controls” for each applet.  I am not going to go into detail of explaining JSON format. Below is how the data when stored in the file looked like.

{
 "Account List View": {
    "SIS Account List Applet": {
       "Row Status": "Status of Account.",
       "Name": "Name of the Account",
       "Type": "Type of Account"
    },
    "SIS Account Entry Applet": {
       "Name": "Name of Account",
       "SalesRep": "Sales Team for Account"
    }
 }
}

You need to provide “Control Name” in JSON data file to identify the labels that should display the information icon.

Control Name

Once you have setup the data then we can go ahead and create the View PR. The basic structure of View PR was taken from siebel-essentials.

View PR:

View PR can be divided into following functionalities

  1. Read JSON File
  2. Loop through all the Applets
  3. Loop through and select controls for each applet
  4. Add image and tooltip to valid controls
  5. Initialize jQuery tooltip functionality

So, let go through code of some of the functionalities:

Read File: For this particular functionality we using jQuery’s ajax capability to read files

/* function to read the tooltips from the json file */
ToolTipPR.prototype._readTips = function (viewName){
  var msgData = "";
  $.ajax({
    url: "23030/scripts/siebel/custom/tooltip.txt",
    dataType: 'json',
    success: function(data){
      msgData = data[viewName]; //retrieve all the data related to this view
    },
    async: false //need to make async false in order to return data
  });
return msgData;
}

The code in SetRenderer function performs the next set of steps. Before going into details of SetRenerer function here are couple of other important functions that are used in it.

_GetAppletProp: This function is responsible for getting ListApplet selector that is needed to select the columns of a list applet (provided by Jason)

//Check if it is list applet or not
//in case of list applet also return the grid selector
//taken from Jason's post for MouseOver tooltips
ToolTipPR.prototype._GetAppletProp = function (sAppletId){
   //get the list applet grid id
   var oGridId=$("#"+sAppletId+" .ui-jqgrid-view");
   var sDataTablePrefix="";
   //if gridid not blank means list applet
   if(oGridId.length>0){
       sGridId=oGridId.attr("id").replace("gview_","");
       //column headers are prefixed with 'jqgh_' plus the table id
       sDataTablePrefix="jqgh_"+sGridId;
      var isListApplet=true;
    }
   else{
      var isListApplet=false;
   }
 return {"isListApplet":isListApplet,"sDataTablePrefix":sDataTablePrefix}
}

_GetControlListColSelector : Function that returns the selector for the column. It handles both list and form applets.

//Function to get the label selector based on control name
ToolTipPR.prototype._GetControlListColSelector=function(oAppletProp,sControlName){
   var sControlNameUnd=sControlName.replace(/\s/g,"_");    //replace space with _
   //in case of control name is prefixed with jqgh_ + grid id + Control Name
   //in case of form applet it is suffixed with Control Name  + "_Label"
   //space is replaced with _
   //you do all that you have got yourself a selector to select the right control through jquery
   var sIdSelector=( oAppletProp.isListApplet ) ? "#" + oAppletProp.sDataTablePrefix + "_" + sControlNameUnd : "# " + sControlNameUnd + "_Label";
   return sIdSelector;
}

Now the main function where all the magic happens:

SetRenderer: Main function to read file and add tooltips to individual columns

ToolTipPR.prototype.SetRenderer = function () {
   var viewName = this.GetPM().GetName();
   //pass view name so that we get only data for that view
   var tipsObject = this._readTips(viewName);
   var appletTipsObj = "", strTip = "", ctrlName = "", ctrlSelector = "", oCtrl = "";
   var oApplets = this.GetPM().GetAppletMap();
   /*run through all the applets in the view*/
   for(var oApplet in oApplets){
     appletTipsObj = tipsObject[oApplet]; //check if we have tooltip definition for this applet
     if(typeof(appletTipsObj) === "object"){//if applet found
        SiebelJS.Log("Processing Tips");//process the tooltip data
        var appletProp = this._GetAppletProp(oApplets[oApplet].GetFullId()); //get the current applet id
        var oControls = oApplets[oApplet].GetControls(); //get the controls
        //run loop around all the controls in file for this applet
        for(var tip in appletTipsObj){
          strTip = appletTipsObj[tip]; //get the tooltip text
          oCtrl = oControls[tip]; //get the control from the applet
          if(typeof(oCtrl) === "object"){ // make sure specified control is found
            ctrlSelector = this._GetControlListColSelector(appletProp, oCtrl.GetName()); //get the label selector
           //append our image to control and add tooltip text as title of image
           $(ctrlSelector).append("<img title='" + strTip + "' class='help-icon' height='12px' width='12px'  src='images/help-icon.jpg' true=''/>");
       }//end of if
     }//end of for
    }//end of if
    else{
    SiebelJS.Log("No Tips found for Applet :: " + oApplet );
    }
 }//end of for loop of applets

  //initalize tooltip for our images
  $("img.help-icon").tooltip({
  //content needed for basic HTML support (Line Break) in tooltips
     content: function() {
       return $(this).attr('title');
     },
     position: {
     my: "center bottom-20",
     at: "center top",
     using: function( position, feedback ) {
     $( this ).css( position );
     $( <div>" )
     .addClass( "arrow" ) //needed for the arrow pointing to element
     .addClass( feedback.vertical )
     .addClass( feedback.horizontal )
     .appendTo( this );
     }
   }
  });
}

The final part is the css to style your tooltips

.ui-tooltip, .arrow:after {color:#FFF;background:#FFEE00}
.ui-tooltip {padding: 10px 20px;color: #fff;font-size: 14px; font-family: "Helvetica Neue", Arial, "Liberation Sans", FreeSans, sans-serif;box-shadow: 0 0 7px #f26524;}
.arrow {width: 70px;height: 16px;overflow: hidden;position: absolute;left: 50%; margin-left: -35px;bottom: -16px;}
.arrow.top {top: -16px;bottom: auto;}
.arrow.left {left: 20%;}
.arrow:after {content: "";position: absolute;left: 20px;top: -20px;width: 25px;
height: 25px; -webkit-transform: rotate(45deg);
-moz-transform: rotate(45deg); -ms-transform: rotate(45deg);-o-transform: rotate(45deg);
tranform: rotate(45deg); }
.arrow.top:after {bottom: -20px;top: auto;}

I have tried to include as many comments to explain what is happening but if you still have any questions or are not able to make work, feel free to post your comments. I will try my level best to answer them.

Now you just need to include this “View PR” (usual steps) in your application and it should work without problem. I was planning to post the complete PR file but I like @lex’s idea of promoting learning so, I have not mentioned some of the obvious things (Init function in View PR) that you will have to do to make it work. Hopefully I have not made it as difficult as him (screenshots ??) ;) to use the code :) .

Keep reading!! Lot of things in store


Siebel Open UI – Modify Calendar control

$
0
0

As I had said in my initial post about Siebel Open UI that it has a long way to go when it comes to real project implementation. This post is provides another example reaffirming my opinion. Oracle has gone ahead and replaced the Active X calendar control and legacy SI calendar control with jQuery calendar control. Unlike Active X calendar control that could be customized using user and system preferences they have provided no documentation or way to customize the jQuery based calendar control.

We were asked by the client to make the changes to calendar and make Monday as the first day of week and in addition to change the text “Now” to “Today”. Since no documentation was available I tried searching Siebel Unleashed :) and Siebel Essentials but found nothing. Next step was to open an SR with Oracle support and as usual it didn’t help. Only thing it resulted in is an Enhancement request. It also exposed skill level of Oracle Support when they said that it is just not possible to customize the calendar control in Open UI.

Then the last step was to try to find the answer on our own and it turned out, that it wasn’t that difficult. After a bit of string search, customizing couple of files we were able to achieve this and as usual sharing it here, for everybody’s benefit.

Problem Statement:

  • Change the button Label from “Now” to “Today”
  • Change the Calendar control to make Monday as the first day of the week instead of the default Sunday.

Solution:

For the first requirement a simple text search for string “Now” in the scripts folder brought up a file named “swemessages_enu.js”. This file contains many string definitions that are used by Siebel in various controls and errors messages. You would see line shown below in the file and changing the string “Now” to “Today” will do the trick.

Before Modification

_SWEmsgAry["IDS_SWE_TIMEPICKER_CURRENT_TEXT"] = “Now”;

After Modification

_SWEmsgAry["IDS_SWE_TIMEPICKER_CURRENT_TEXT"] = “Today”;

 

The second part of requirement was a bit more tricky. After struggling for a few hours I again performed a text search in the scripts folder for string “IDS_SWE_TIMEPICKER_CURRENT_TEXT” and that brought up name of another file “datepicker-ext.js”. This file turned out to be the key file containing initialization information of jQuery calendar control.

image

But I still couldn’t figure out how to make Monday as the first day of the week. I tried changing the array definition but it only effected the UI. A bit of research on net revealed that jQuery datepicker control has an option called “firstDay” that controls the day of the week.

So adding the following line did the trick

image

firstDay : 1

And the result was as you can see below:

image

But this didn’t seem the right way to do it, so I actually did it the way other options had been define which was as following:

  1. In swemessages_enu define a new option
    _SWEmsgAry["IDS_SWE_TIMEPICKER_FIRST_DAY"] = 1;
  2. In datepicker-ext.js file define firstDay parameter
    firstDay        : _SWEgetMessage( “IDS_SWE_TIMEPICKER_FIRST_DAY” ),

The final result is as shown below:

image

Hope this help!! Happy Customizing :)

Siebel Open UI – Useful JavaScript tips

$
0
0

We are moving away from eScript and going towards JavaScript and in future you will be writing more code in JavaScript than in eScript. I believe that eventually Oracle will dump eScript and move to pure JavaScript since it is better, faster and leaner than eScript. It becomes really important that we understand small nuisance and behavior of  JavaScript early in order write better and efficient code. In this post I am sharing few tips/tricks/useful functions that I picked from internet and my experience of working with JavaScript which. I believe these are really important/useful and will come pretty handy while writing Open UI PM/PR.

1. Don’t forget the var keyword when assigning variable’s value for the first time.
Assignment to an undeclared variable automatically results in a global variable being created. Avoid global variables.

2. use === instead of ==
The == (or !=) operator performs an automatic type conversion if needed. The === (or !==) operator will not perform any conversion. It compares the value and the type, which could be considered faster than ==.

'10' == 10     // is true
'10' === 10 // is false

3. Use Semicolon for line termination.Although JavaScript engine automatically inserts ; but using it considered as best practice.

4. Verify if given argument is a number

function isNumber(n){
    return !isNaN(parseFloat(n)) &amp;&amp; isFinite(n);
}

5. Get the Max or Min in an array of numbers

var  numbers = [5, 458 , 120 , -215 , 228 , 400 , 122205, -85411];
var maxInNumbers = Math.max.apply(Math, numbers);
var minInNumbers = Math.min.apply(Math, numbers);

6. Empty an array

var myArray = [12 , 222 , 1000 ];
myArray.length = 0; // myArray will be equal to [].

7. Truncate an array using length

var myArray = [12 , 222 , 1000 , 124 , 98 , 10 ];
myArray.length = 4; // myArray will be equal to [12 , 222 , 1000 , 124].

8. Using Logical AND/OR for conditions

var foo = 10;
foo == 10 && doSomething(); // is the same thing as if (foo == 10) doSomething();
foo == 5 || doSomething(); // is the same thing as if (foo != 5) doSomething();

The logical OR could also be used to set a default value for function argument.

function doSomething(arg1){
    arg1 = arg1 || 10; // arg1 will have 10 as a default value if it’s not already set
}

9. Rounding number to N decimal places

var num =2.443242342;
num = num.toFixed(4);  // num will be equal to 2.4432

toFixed() returns a string not a number

10. Comma Operator

var a = 0;
var b = ( a++, 99 );
console.log(a);  // a will be equal to 1
console.log(b);  // b is equal to 99

11. Using switch/case statement with numeric ranges
You can use numeric ranges in a switch/case statement using below approach

function getCategory(age) {
    var category = "";
    switch (true) {
        case isNaN(age):
            category = "not an age";
            break;
        case (age >= 50):
            category = "Old";
            break;
        case (age <= 20):
            category = "Baby";
            break;
        default:
            category = "Young";
            break;
    };
    return category;
}
getCategory(5);  // will return "Baby"

12. Avoid using try/catch/finally inside a loop
The try-catch-finally construct creates a new variable in the current scope at runtime each time the catch clause is executed where the caught exception object is assigned to a variable.

That’s it for this post, I hope this is helpful. I will be sharing more as and when I find them. Have some of your own tips to share??? Find the comments section.

List Applet scroll using mouse wheel – Siebel Open UI

$
0
0

I was going through Open UI themes a really nice site dedicated to paid themes and plugins for Siebel Open UI. While browsing the plugin section I came across a plugin that was titled Auto-Scroller Plugin. The description said that it allows you to navigate through list applet (Next Page, Previous Page, Next Record , Previous Record) using scroll action (mouse wheel scroll) instead of clicking the icon and scrolling.

I really liked the idea and set about implementing it and soon I had a working PR which included in a list applet allows following behavior:

  1. If CTRL Key is pressed and scroll action is preformed, then record by record navigation will occur.
  2. If SHIFT key is pressed and scroll action is preformed, then page by page navigation will occur.
  3. Scrolling without any key will perform normal behaviour i.e. page scrolling

Want to know how to do it ? So, lets get started

I used a jQuery plug-in named jquery-mousewheel to track mouse wheel although technically you can write your own code to track mouse wheel but I didn’t see any point in re-inventing the wheel so went the plug-in route.

jQuery-mousewheel plugin details:

The plug-in gives you two events “mousewheel” and “unmousewheel”.

mousewheel: When this event is bound to a particular element it gives you direction, X and Y co-ordinates when ever mouse wheel is used on that element.

unmousewheel: This event is used to unbind tracking of mouse wheel.

Here are the steps for the plug-in:

  1. Download the plugin js from here.
  2. Copy the jquery.mousewheel.min file in the 3rd party folder.
  3. Go to manifest administration and query for entry Create a manifest entry for the file in the PLATFORM INDEPENDENT
    image

That’s it for the plugin part. Now comes the PR part.

List Applet PR:


var pHolder = this.GetPM().Get("GetFullId"); //get placeholder to bind the mousewheel event
var siebConsts = SiebelJS.Dependency( "SiebelApp.Constants" ); //get the constants

//code to add mouse scrolling to list applets
$('#' + pHolder).on('mousewheel', {ctx:this,consts:siebConsts}, function(event){
    var that = event.data.ctx; //get instance
    var directionNext = "", directionPrev = ""; //initialize

    if(!(event.ctrlKey) && !(event.shiftKey)){ //if no key pressed then do nothing
       return true;
    }
    if(event.ctrlKey && event.shiftKey){ //if both are pressed do nothing
       return true;
    }

    if(event.ctrlKey){ //in case of CTRL Key get the constants for Next Record and Previous Record
       directionNext = event.data.consts.get("PAG_NEXT_RECORD");
       directionPrev = event.data.consts.get("PAG_PREV_RECORD");
    }
    else if(event.shiftKey){ //in case of shift key - Next Page and Previous Page
       directionNext = event.data.consts.get("PAG_NEXT_SET");
       directionPrev = event.data.consts.get("PAG_PREV_SET");
    }

    if(event.deltaY === -1){ //delta Y = -1 means scroll down
     //invoke the physical action
     that.GetPM().OnControlEvent( event.data.consts.get( "PHYEVENT_VSCROLL_LIST" ), directionNext );
     event.preventDefault(); //stop default action (page scrolling)
    }

    if(event.deltaY === 1){//delta Y = 1 means scroll up
      //invoke the physical action
      that.GetPM().OnControlEvent( event.data.consts.get( "PHYEVENT_VSCROLL_LIST" ), directionPrev );
      event.preventDefault(); //stop default action (page scrolling)
    }
});

Including the above code in ShowUI method will make the PR complete. The code itself is not as complex as was the finding, how to do it. This code basically is

“Whenever mousewheel (thanks to plugin) action happens on the list applet div (applet placeholder) then check if either Shift key or CTRL key is down at that time then based on the scroll direction either perform page up/page down/next record/previous record.”

Inclusion of keys (CTRL / SHIFT) was not compulsory but then you would end up with following problems

  1. Normal page scroll functionality wouldn’t work on list applet
  2. You would have to calculate based on distance if user intended next record or next page. There are chances of doing what the user didn’t intend

Explicit use of keyboard keys helps us to do exactly what user intends to do, rather than guessing.

The key to whole functionality is knowing how to trigger the list applet scroll event using onControlEvent and Siebel Constant. Hopefully the code is simple enough to understand but if you still have questions find the comments section.

Happy Scrolling !!! Don’t forget to rate the post and encourage through comments.

Note: In case you end up using this in anywhere please don’t forget to credit the author (that’s me! ). This will keep me motivated :) to build bigger and better things in Open UI and most importantly share it with all of you.

Another Note: It seems there were some problems in trying to use the code. So, I am posting the link to the PR that is working for me. Hopefully just including this along with the plugin should get the functionality working

Download PR From Here

Correcting the Tab Index – Siebel Open UI

$
0
0

Imagine that you have a view where you have several form applets stacked vertically. You would like to allow users to be able to navigate from top to bottom using keyboard (Tab Key). Where you would like to skip read only fields, mvg fields and some other fields.

This requirement is not possible in using normal field indexing capability provided by Siebel in Siebel Tools. I had this type of situation and I came up with a small piece of code when plugged in View PR would add Tab Index attributes to the form fields that are active and allow seamless navigation across applets on the view. You can put your custom logic to vary the tab index for different sections or fields.

Below is the code that should be put in View PR SetRenderer function

var tabindex = 1;
//add the selectors depending on your needs (text area, radio etc)
$("input[type='text'], input[type='checkbox'], button").each(function() {
     //put the filter condition or custom logic to vary tab index for fields
     //in this example we skip read only fields, and any thing that has disabled attribute (buttons) to it
     if ($(this).attr("aria-readonly") === "true" || $(this).attr("disabled") === "disabled") {
        $(this).attr("tabindex", "-1"); //no need for focus on these fields
     }
     else{
         $(this).attr("tabindex", tabindex); //assign the index using tabindex attribute
         tabindex++; //increment tab index
    }
});

A little tid bit that can come in handy while you are working on Siebel Open UI.

Open UI cannot teach you good manners!

$
0
0

I couldn’t not stop laughing when I read when I read @lex’s post “What Open UI does for you – and what not”. Those were some really funny but true lines and I couldn’t agree more with him.  Here is some of the excerpts from his post.

Open UI does NOT teach you good manners: That you have to do yourself. What I have seen often is that when Open UI is introduced in a project, everyone gets so excited that all ‘good manners’ are thrown overboard. Business process analysis? Requirements mapping? Design? Source control? Forget it, we’ve got Open UI, so we do all the fancy stuff because we can do it. That of course is a recipe for disaster.

So True! In addition to that I would like to add another syndrome that I experienced myself during an Open UI project implementation. I call that syndrome as Open UI First. Before Open UI the normal way of thinking about a solution was or rather should be:

  1. Is declarative solution possible ?
  2. How can we achieve using configuration?
  3. Workflow VS Scripting?
  4. Business Service VS Object Scripting (BC or Applet)
  5. When all else fails find the appropriate event to script.

Once you start feeling confident in Open UI the first question that comes to mind is “Is it possible using PM or PR?”. This can lead to fragmented solutions where you end up writing scripts here and there in addition to creating PM and PR’s. Remember Open UI is just a layer on top of same old Siebel and the rules of solution have not changed yet (but I think they are going to change soon). Think in terms of Traditional Siebel and not Open UI.

 

It does NOT make you a web developer overnight: With Open UI, the typical Siebel developer can be easily overwhelmed with all the web technologies such as JavaScript, HTML and CSS. Oh, you wrote eScript for the last ten years? Jolly good but sorry, that does not make you a web developer even if you argue that JavaScript is based on the same standard (ECMA) as eScript. Most of us will have to start learning, not only the Open UI API but also web standards. And it’s better to start learning today than tomorrow.

The experts have spoken. If you don’t want to be a dinosaur in Siebel World then start learning these web technologies today and believe me these are relevant even if you think Siebel is dead. All leading platforms use these including Salesforce. I started learning it the day I first found about Siebel Open UI.

@lex has made some more really good points in his post and you can read the rest of the post here and I suggest, you read it carefully.

Client Side Business Service- Siebel Open UI

$
0
0

Writing script on client side in Siebel is a nightmare. In the name of IDE we only a text area where we have to write the code. Here are some of the major problems that I see with this

  • Formatting is a real pain as the only way to indent the code is spaces.
  • Hitting tab key will take focus out of text area.
  • There is no intellisense or syntax highlighting
  • Debugging is a pain.

While thinking about use cases of Siebel Open UI I wondered if there is any way we can fix these problems. After doing some analysis I found that yes it is possible to change all this. Below is the approach to implement the final solution:

  • Replace text area with either contenteditables or third party jQuery editor like TinyMCE
  • Implement intellisense again using third party jQuery plugin
  • Basic Syntax checking can also be implemented
  • Finally the code needs to be saved to  Business Service field so that it can execute properly

I didn’t had time to create an elaborate solution to accomplish all the enhancements in my wish list but with small piece of code and a plugin I was able to overcome what I consider major nuisances such as

  • Functional Tab Key to help format the code
  • Intellisense (kind of..) using jQuery plugin called textcomplete
  • Increased font size for better readability

Not wasting any time further here are the steps to make it happen:

This snippet of code is used to get the tab key functional

$('textarea').keydown(function(e) {
   if(e.keyCode == 9) {
        var start = $(this).get(0).selectionStart;
        $(this).val($(this).val().substring(0, start) + "\t" + $(this).val().substring($(this).get(0).selectionEnd));
         $(this).get(0).selectionStart = $(this).get(0).selectionEnd = start + 1;
       return false;
   }
});

Following snippet is required to get the intellisense functionality working

//create array with all the keywords
var elements = ['TheApplication','RaiseErrorText','GetBusObject','GetBusComp','NewPropertySet','substring','InvokeMethod',
'ActivateField','ActivateMultipleFields','Associate','BusObject','ClearToQuery','CountRecords','DeactivateFields','DeactivateFields',
'DeleteRecord','ExecuteQuery','FirstRecord','FirstSelected','GetAssocBusComp','GetNamedSearch','GetFieldValue','GetFormattedFieldValue',
'GetLastErrCode','GetMVGBusComp','GetLastErrText','GetMultipleFieldValues','GetPicklistBusComp','GetSearchExpr','GetSearchSpec',
'GetUserProperty','GetViewMode','InvokeMethod','InvokeMethod','InvokeMethod','InvokeMethod','InvokeMethod','InvokeMethod','LastRecord',
'Name','NewRecord','NextRecord','NextSelected','ParentBusComp','Pick','PreviousRecord','RefineQuery','Release','SearchExpr','SetFieldValue','SetFormattedFieldValue',
'SetMultipleFieldValues','SetNamedSearch','SetSearchExpr','SetSearchSpec','SetSortSpec','SetUserProperty','SetViewMode','UndoRecord','WriteRecord',
'ActiveMode','BusComp','BusObject','FindActiveXControl','FindControl','InvokeMethod','GetFirstProperty','GetNextProperty','GetProperty','PropertyExists',
'RemoveProperty','SetProperty','GetChild','RemoveChild','GetChildCount','SetType','GetType','AddChild','Copy','GetPropertyCount','GetValue','InsertChildAt',
'RemoveProperty','Reset','SetValue','Applet','BusComp','SetLabelProperty'];

$('textarea').textcomplete([
{ // html
     match: /\b(\w{2,})$/, //regex to match characters
     search: function (term, callback) { // function to find a match and return the match keyword
         term = term.toLowerCase(); //to implement case insensitive search
         callback($.map(elements, function (word) {
             return word.toLowerCase().indexOf(term) === 0 ? word : null;
          }));
      },
      index: 1,
      replace: function (value) {
           var fVal = "";
           if(value === "TheApplication"){ fVal = "TheApplication().";    }
           else{ fVal = [ value + '("', '");']; }
           return fVal;
      }
}]);

Optionally you can include following CSS rule to increase the font size and margin of the script


.siebel-bs-script{color:#000;font-size:14px!important;padding-left:10px!important;margin-left:10px!important}

You can see it action here

If interested you can download actual PR file from here.

Fixing Textarea in Siebel Open UI

$
0
0

In Siebel HI application all the description fields or the fields that were suppose to hold large amount of data (controls with HTML Type as “TextArea”) you would see an icon on the side of the field.Clicking on that icon opens up a popup allows you to view and edit the text in the field.

image                   image


This is a pretty important piece of functionality that you loose when you move to Siebel Open UI. In Siebel Open UI you just see plain Text area control.Although latest browsers gives you the ability to expand the textarea field manually by clicking and dragging the icon located in the bottom right of the text area (shown below). But it is pretty annoying to do that every time you want see what is in the field.

image                    image

This post explains a simple (although not perfect) solution to this problem using a jQuery plugin (again) with name AutoSize. We create a View Level PR for the solution so that we can address all textareas in a view in one go.  The code that we have to write is pretty minimal. Here are the steps that you need to follow

  1. Download the View PR template (if you already don’t have it) from here
  2. Include the Plugin file using instruction in this post.
  3. In SetRenderer function write following code
$('textarea').focus( function() {
    $(this).autosize(); //resize when user focus on the textarea
});

$('textarea').blur( function() {
    $(this).trigger('autosize.destroy'); //revert back to original size when user leaves focus
});

Curious to know what it does?

Autosize plugin automatically resizes the textarea to display complete text that is being entered. So, basically what our View PR code is doing is that :

As soon as Textarea gets focus (user clicks on it) autosize will resize the text area to show complete text. Once user has completed editing/viewing of the text and field looses focus, revert the text area back to original size.

image          image

This is not an ideal solution because of following reasons

  1. The layout of the applets gets distorted when the textbox is expanding.
  2. Flickering that happens when the textbox is resized suddenly can cause confusion to the user and loss of focus.

So, I am looking for better solution but till that time something is better than nothing.


Tooltips makover – Siebel Open UI

$
0
0

Few weeks back I had published a post that showcased how you can use power of Siebel Open UI to actually implement tooltips for fields in List and Form applets in truly SRF independent way. If you haven’t gone through the post I would suggest doing that before continuing. You will also be able to see it in action next year in first ever Siebel Open UI book published by packt along with several other advanced example that allow to fully understand and use power of Open UI for creating truly wonderful User Experience. So, don’t forget to get your hands on as soon as one comes out (I know I will be getting one :) ).

I felt it was good and really useful example but it lacked one thing ability to truly style the tooltips in the way you want. Let’s say for some fields I would like to emphasize the tooltip, for others I would like to appear it in red color so that user pay  more attention to it or for some fields you would like to present it in blue (you get the point). I really wanted it to be flexible in terms of style so I started exploring ways to achieve it. Soon I realized that it would not be possible without a plugin and after some research I zeroed in on qTip2.

Here is what I have achieved with the plugin.

imageimageimage

The starting point of our new solution will be the old solution. So, if you don’t have that handy download it from here

Before diving into the code let’s discuss the new structure of the JSON file :

{
  "Account List View": {
     "SIS Account List Applet": {
        "Row Status": {
           "tooltip": "Status of Account.",
           "type": "warning"
         },
        "Name": {
           "tooltip": "Name of the Account",
           "type":"warning"
         },
        "Type": "Type of Account"
      },
     "SIS Account Entry Applet": {
        "Name": "Name of Account",
        "SalesRep": "Sales Team for Account"
     }
  }
}
  1. Basic structure of the file is same having following hierarchy
    1. View Name
    2. Applet Name
    3. Control details
  2. Control tooltip can be plain string  OR
  3. Control can be an object having following properties
    1. content (required) : The content of the tooltip.
    2. type (Optional): define the tooltip at this point it can have info or warning as possible values but you can extend it as you want.

Now the code changes:

I have introduced a new function to get the tooltip string. Now the tooltip string will be inserted as a span tag next the control instead of title attribute of the control.

TooltipPR.prototype.buildTooltip = function(tooltipObj){
    var tooltip = "";
    //if string then just process it as text
    if(typeof(tooltipObj) === "string" &amp;&amp; tooltipObj){
        tooltip = "<span style='display:none'>"  + tooltipObj + "</span>";
    }
    //if it is a object then process the properties that comes along with it
    if(typeof(tooltipObj) === "object"){
       var text = tooltipObj.tooltip; //get the content
       if(typeof(text) === "undefined")// there is no content property
         return tooltip; //go back .. do not process

       var spanClass = "";
       var type = tooltipObj.type; //get the type
       //making sure type is defined otherwise
       //can there be a better way to do it ????
       if(typeof(type) === "string"){
         //differnt types are just different type sytle based on classes
         //you can create your own if you want.
         switch(type){
            case "info":
              spanClass = "class='qtip-blue'";
            break;
            case "warning":
               spanClass = "class='qtip-red'";
            break;
            default:
              spanClass = "class='qtip'";
            break;
          }//end of switch
        }//end of if type
       //create the tooltip span
       tooltip = "<span style='display:none' " + spanClass + ">" + text + "</span>";
   }
  return tooltip;
}

The finally few modifications in the code of SetRenderer function

TooltipPR.prototype.SetRenderer = function(){
     var viewName = this.GetPM().GetName();
     //pass view name so that we get only data for that view
     var tipsObject = this._readTips(viewName);
     var appletTipsObj = "", strTip = "", ctrlName = "", ctrlSelector = "", oCtrl = "",sTooltipSpan = "";
     var oApplets = this.GetPM().GetAppletMap();
     //run through all the applets in the view
     for(var oApplet in oApplets){
        appletTipsObj = tipsObject[oApplet]; //check if we have tooltip definition for this applet
        if(typeof(appletTipsObj) === "object"){//if applet found
           SiebelJS.Log("Processing Tips");//process the tooltip data
           var appletProp = this._GetAppletProp(oApplets[oApplet].GetFullId()); //get the current applet id
           var oControls = oApplets[oApplet].GetControls(); //get the controls
           //run loop around all the controls in file for this applet
           for(var tip in appletTipsObj){
               strTip = appletTipsObj[tip]; //get the tooltip text
               oCtrl = oControls[tip]; //get the control from the applet
               if(typeof(oCtrl) === "object"){ // make sure specified control is found
                  sTooltipSpan = this.buildTooltip(strTip); //this is the new function to get tooltip data in span
                  ctrlSelector = this._GetControlListColSelector(appletProp, oCtrl.GetName()); //get the label selector
                //append our image to control and add tooltip span next to image for tooltip to work
                if(sTooltipSpan){ //process only if something's there
                    $(ctrlSelector).append("<img class='help-icon' height='12px' width='12px'  src='images/help-icon.jpg' true=''/>" + sTooltipSpan);
}
                }//end of if
           }//end of for
         }//end of if
         else{
             SiebelJS.Log("No Tips found for Applet :: " + oApplet );
         }
      }//end of for loop of applets

//initalize tooltip for our images
$("img.help-icon").each(function(){
     $(this).qtip({
          content: {
           text: $(this).next('span') // Use the "span" element next to this for the content
          },
         style:{
           classes: $(this).next('span').attr("class") + ' qtip-shadow'
        }
     });
 });
};//end of setr

Following are the differences in code:

  1. The way to get the tooltip text instead of straight processing we evaluate if it is an object or string and then create a span tag
  2. The way tooltips are initialized. We are using a 3rd party plugin qTip2 for tooltips so the initialization based on it requirements.

Now something about qTip plugin

This is one of the leading tooltip plugin used across thousands of website. It supports HTML tooltips and offers plethora of features such as ajax, iframe, embedded videos etc. All I had to do was to include the JS and CSS file of this plugin and I was good to go.

On a side note I tried to use code from my last post to recreate it in my local and I ran into some issues. So this time I am sharing link of the actual JS file that is working on my local so that you don’t have to go through the same issues. You can download it by clicking here.

Below is video that shows the functionality in action along with another surprise functionality so don’t forget to watch till the end.

Eagerly waiting for your comments/suggestions/feedback. So, what are you waiting for?

Siebel Open UI annoying message on popup close

$
0
0

We recently upgraded to Patchset 11 as it promised improvement in performance up to 35% (in some areas) along with other things but after upgrading we encountered a really weird functionality (seems like a bug). After applying the patch if you try to close any popup using “X” button then you get another popup saying

“Click OK to discard unsaved data and close all popups.”

image

This happens for all popups (MVG, Pick Applet, About View .. you name it). This is really annoying as it doesn’t seem to serve any purpose and our client also expressed the same sentiment. In addition, this message is hard coded in JS files which means in multilingual environment even Non-English application will show the message in English.

I can only assume that Oracle was working on some functionality and left this code by mistake.  Our Client asked this functionality to be removed as it was more of an annoyance than useful. My initial thought was to open an Oracle SR but due to my prior experiences of not getting answers I decided to give a try myself first. It wasn’t difficult to find the answer

A quick string search in the scripts folder with message text revealed that message was coming from “phyrenderer.js” and after un-minifying the code I found the following piece of code responsible for it.

b.prototype.BindEvents = function() {
      SiebelAppFacade.PopupRenderer.superclass.BindEvents.call(this);
      var k = $("[name=popup]");
      k.data("context", this);
      k.dialog({
         beforeClose: function(m, n) {
           if ($(m.currentTarget, "[class*=ui-dialog-titlebar-close]").length > 0) {
               var l = $("[name=popup]").data("context");
               if (g.Confirm("Click OK to discard unsaved data and close all popups.")) {
                   l.GetPM().OnControlEvent("ClosePopupByX", m);
                   return true;
               }
           return false;
          }
      }
    });
};

When compared with code in earlier patches the same event had following code

b.prototype.BindEvents = function() {
   SiebelAppFacade.PopupRenderer.superclass.BindEvents.call(this);
   var k = this.GetPM();
   if (SiebelApp.S_App.IsMobileApplication() === "false") {
      $("[class*=ui-dialog-titlebar-close]").bind("click", function(l) {
         k.OnControlEvent("ClosePopupByX", l)
      })
   }
};

So, in order to remove this confirm message all you have to do is change the code to following:

b.prototype.BindEvents = function() {
   SiebelAppFacade.PopupRenderer.superclass.BindEvents.call(this);
   var k = $("[name=popup]");
   k.data("context", this);
   k.dialog({
      beforeClose: function(m, n) {
      if ($(m.currentTarget, "[class*=ui-dialog-titlebar-close]").length > 0) {
         var l = $("[name=popup]").data("context");
         //if (g.Confirm("Click OK to discard unsaved data and close all popups.")) {
             l.GetPM().OnControlEvent("ClosePopupByX", m);
             return true;
         //}
      //return false
      }
   }
})
};

I have tested and it doesn’t seem to effect anything else but remember this is a core file that we are not suppose to touch so you are responsible for any damage it might cause in your environment. Also you will have to make this change again after applying future patches if oracle doesn’t remove this code itself. I hope this will save somebody few hours of headache.

Enter Key on home page search IP-2013

$
0
0

This article has been contributed by Gururaj Basavaraj a reader of Siebel Unleashed.


If you are in IP2013 you might be having problem search on home page by pressing enter key instead of

Go click. For that below is the PR code, associate this to all home page search applets.

if(typeof(SiebelAppFacade.EnterKeySearch) === "undefined"){
       SiebelJS.Namespace("SiebelAppFacade.EnterKeySearch");
       define("siebel/custom/EnterKeySearch", ["siebel/phyrenderer"], function(){
          SiebelAppFacade.EnterKeySearch = (function(){
          function EnterKeySearch(pm){
             SiebelAppFacade.EnterKeySearch.superclass.constructor.call(this,pm);
          }
       SiebelJS.Extend(EnterKeySearch, SiebelAppFacade.PhysicalRenderer);
       EnterKeySearch.prototype.BindEvents = function(){
           SiebelAppFacade.EnterKeySearch.superclass.BindEvents.call(this);
           Search.call(this);
      };
 
     function Search() {
         var oPM = this.GetPM();
         var sAppletId = "#S_A"+oPM.Get("GetId");
         $(sAppletId).delegate("input","keydown",function(){
         });
     }
  return EnterKeySearch;
}());
return "SiebelAppFacade.EnterKeySearch";
});
}

Debugger to the rescue for global js files – IP2015

$
0
0

Guess what, I am working on OpenUI again and it feels really good. I recently, got an opportunity to work on IP 2015 and developing some really cool functionalities (Favorites, Broadcast Message Bar etc) as part of project.

A lot of things have changed as compared to 8.1.1.11, PM’s & PR’s have become more structured. Themes have moved in to manifest but with all the good things comes the complexity. We all know that we can have our custom js file included at the application level by copying the “PLATFORM INDEPENDENT” manifest entry and linking our custom js file. This comes in really handy when you are trying to work functionalities that are global in nature (Application level tooltips, anyone ??).

Let me clarify, I know this is not a new feature but when you did that in earlier versions you would see your file included in the sources tab of the browser

sources_1

This comes in really handy to debug and verify your changes have taken effect, change and test code on the fly. Also in case there were errors in your code it would show in console what the error is and what is causing that error.

But, it seems that in IP2015 (may be IP2014 also) due to core framework changes the global level JS inclusions just don’t show up in Sources tabs (it took me several hours to find this out).  To make matters worse in case if your code has errors then all you get is error shown below

sources

Error in downloading file require:null

It seems that Siebel OpenUI framework handles even the syntax errors of all the global files and then shows a generic message. This means the only way to debug is to either use alert or log (SiebelJS.Log or console.log) statements at each at every line to find out where the problem is.

Don’t fret, there is an easy way out and that is the debugger statement. Just write the “debugger” statement in your code where you would like to set a break point and open browser console and clear the cache.

debugger

This debugger statement acts as debug point but the difference is that it is only takes effect when browser console is open. So, instead of using sources tab of browser to set break point you can do it right from your code.debugger_in_effect

This is what happens as soon as debugger statement is encountered. I hope this tip helps somebody save hours worth of effort.

I know I have been pretty inactive but time to get active again. Lot more in store keep reading.

Viewing all 32 articles
Browse latest View live