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.
- Tooltip Data
- 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.
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
- Read JSON File
- Loop through all the Applets
- Loop through and select controls for each applet
- Add image and tooltip to valid controls
- 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