Siebel Open UI: See-Through Applets (Part 1)

advertisement
Siebel Open UI: See-Through
Applets (Part 1)
Have you ever asked yourself: “Wouldn’t it be nice to be able
to inspect an applet so that it reveals the underlying
business component fields or even the tables and columns where
the data is stored?”
You haven’t? Well, I know, I have.
I believe every determined Siebel developer or analyst gets a
bit weary over time with the limited amount of information in
the About View dialog box. Of course, we can always use Siebel
Tools and navigate through the layers to retrieve the
information. But this is a bit time consuming.
What I am talking about is something similar to the following
scenario. Here is a typical Siebel form applet (in all its
Open UI glory, needless to say):
Click to enlarge
Now, let’s imagine you can double-click anywhere in the applet
to make it “see-through”. The labels now display field name,
type, length and whether they are calculated and/or required.
A see-through applet, kinda NSFW. Click to enlarge.
Let’s drive our imagination further into the wild and doubleclick the applet again. Now the labels display the tables and
columns where the data comes from.
The naked truth. Click to enlarge if you dare.
And just for the sake of usability, another double-click
restores the original applet labels (see first screenshot).
Of course, all screenshots above are just taken out of my wild
imagination. But I have been able – thanks to the new Siebel
Open UI scripting framework – to create a prototype which
implements this imagination quite nicely.
I will tell you a bit about this prototype in this and the
next post. In the first part, I will introduce how to capture
the double-click on any given applet and how to display the
field information instead of the label. The next post will
discuss how to retrieve and display the physical database
information.
Let’s start with the recipe:
1. Capturing double-clicks on all form applets
2. Creating a custom global utility function
3. Get field data from the presentation model and toggle
labels
1. Capturing double-clicks on all form applets
Please note: The following prototype has been implemented with
the sole purpose of demonstrating the capabilities of Siebel
Open UI. It is NOT (repeat: “NOT”) intended for use in
production systems and brainless copying/pasting of code is
strongly discouraged.
Having said that, we must find a way to tell all (form)
applets to “listen” for double-clicks.
Thanks to jQuery, we can use the dblclick event handler
similar to the following:
$(selector).dblclick(function()
{
//some clever code goes here
});
Since Open UI has been released last December, a lot of
examples have been written which demonstrate customizing a
single applet using a custom presentation model and/or
physical renderer. But this time we want to change the
behavior of all form applets at once.
I found only one way to accomplish this, which is by
customizing the Oracle-provided phyrenderer.js file. Knowing
that this is a non-standard customization, I fight an internal
struggle to publish the prototype like this. If any of the
astute readers can share some more insight how to customize
all applets, please find the comments section quickly.
So, keeping in mind that we are on thin ice here, here is the
code I added to the OOB phyrenderer.js file
Click to enlarge
As you see, I modified the ShowUI method which is responsible
of rendering the UI for form applets. Here are the key lines
of code I added:
var myPM = this.GetPM();
This is just customary as I like to have a handy variable
instead of calling the GetPM() function over and over. The
GetPM() function is a physical renderer function and returns
the presentation model object.
target.dblclick( function ()…
I use the OOB jQuery target variable which is initialized by
the Oracle-provided code earlier. It represents the entire
applet DIV layer using the applet’s unique Id. Using the
jQuery dblclick() event handler I can now define what happens
at a double-click.
As you can see in the code snippet, I use the presentation
model’s Get() function to “get” the value of a property named
SE_ToggleCycle which is a custom property I intend to use to
determine the current toggle cycle (“Display Labels”, “Show BC
Fields”, “Show Tables and Columns”).
There might be more elegant ways to accomplish this but a
simple switch always does the trick for me.
So for example when the property SE_ToggleCycle is undefined
(which it is at the time of the first double-click), I set the
cycle variable to “ShowBCFields“. So at the next double-click,
the cycle variable is set “ShowTableColumns“, etc…
After leaving the switch, we can set the property to the
current cycle code using the PM’s SetProperty() function
myPM.SetProperty(“SE_ToggleCycle”,cycle);
So now we have a globally accessible property we can use to
determine the current toggle cycle. The logic of retrieving
metadata and actually toggling the display labels is done in a
custom function which we call as follows:
SiebelApp.CustomUtils.ToggleLabels(cycle, myPM);
The function accepts the cycle variable and the current PM
object as input and we will have a look at it in a few
moments.
Before we leave the custom code we could trace the cycle
variable to the JavaScript console using a line similar to
this:
SiebelJS.Log(“Current double click cycle: ” + cycle);
SiebelJS.Log() is a function provided by the Open UI framework
and should be used instead of the native console.log()
function. Of course this is optional, but a bit of tracing
should always be done in a prototype for the sake of easier
debugging.
For now, when we save the file and restart the Siebel
application, we can actually double-click anywhere in the
applet (preferably the title bar) and inspect the console log:
Click to enlarge
2. Creating a custom global utility function
As the requirement for our prototype is to provide global
behavior, we also must implement the logic on a global scale.
When you take a few minutes to inspect the Oracle-provided
JavaScript files you will stumble upon a utils.js file which
obviously contains a lot of utility functions.
I thought it would be a good idea to mimic this approach and
created my own custom_utils.js file (of course in the custom
folder). Before we forget, let’s ensure that this file is
always loaded by adding it to the <ROOT><COMMON> section of
the custom_manifest.xml file.
Click to enlarge
Here is a screenshot of the custom code and I will explain the
key lines below.
Click to enlarge
As is customary for good citizens in the Open UI framework,
this code adds our CustomUtils namespace to the SiebelApp
realm.
if(typeof (SiebelApp.CustomUtils) === “undefined”){
Namespace(“SiebelApp.CustomUtils”);
}
Now we can declare the ToggleLabels() function in the new
namespace
SiebelApp.CustomUtils.ToggleLabels = function(cycle, myPM){};
After declaring some variables we use the current applet’s
presentation model (passed by the myPM variable to get the
array of controls for the applet.
var arrControls = myPM.Get(“GetControls”);
Let’s spend a minute on the topic of object arrays within Open
UI. If you inspect the above code in the browser’s developer
tools, you can see the content of the arrControls variable.
The below screenshot is taken in Google Chrome but in other
browsers it might be similar.
Click to enlarge
In the screenshot I have expanded the Account control. For
each control of the current applet you can clearly see the
available methods such as GetFieldName or GetDisplayName.
Inspecting object arrays using the browser’s developer tools
provides deep insight into the Open UI framework, a little bit
deeper than the documentation writers would probably like…
The next part of the code is similar to what we have seen in
the phyrenderer.js file customization. Depending on the value
of the cycle variable (passed to the custom function) we call
different local functions. In today’s post I will further
explain the first one, namely ShowBCFields().
3. Get field data from the presentation model and toggle
labels
As discussed above, the goal of the prototype is to
demonstrate that – with Siebel Open UI – it is fairly easy to
accomplish a “see-through” applet. So the ShowBCFields()
function should retrieve BC level metadata from the
presentation model and manipulate the browser’s DOM (Document
Object Model) so that the labels for each control display the
underlying BC field name, logical type, length and whether it
is required or calculated.
We might first be tempted to retrieve that information from
the repository but that would require a server round-trip.
Good to know that the presentation model can provide us with
all this information, so we can reduce load on the server.
Here is the code for the ShowBCFields() function. I will
discuss the key lines below.
Click to enlarge
The first two lines actually show how to get BC level
information. If you pass “GetBusComp” to the PM’s Get()
function, it will return the current applet’s underlying
business component as an object.
var oBC = myPM.Get(“GetBusComp”);
We can use the GetFieldMap() function of the BC object to
retrieve an object array which contains each field used in the
current applet (so its comparatively small).
var oBCFieldMap = oBC.GetFieldMap();
Again, inspecting the object arrays in the browser’s developer
tools provides us with a lot of insight.
Because we have to manipulate each control’s label, we must
implement a for loop for each control in the controls array:
for(sControlName in arrControls){}
This will populate the sControlName variable with the name of
the current control in the loop.
After checking that the control is really a member of the
array, we can instantiate the current control as an object by
accessing it by name in the controls array:
oControl = arrControls[sControlName];
Now we can retrieve the name of the underlying BC field:
sNewLabel = oControl.GetFieldName();
If the control is a button, there is no underlying BC field,
so we should exclude those:
if (sNewLabel != “”){}
Now we can use the field map array to retrieve the desired
information. The following lines get the field’s logical data
type, its length and in addition we inspect whether the field
is required and/or calculated
oField = oBCFieldMap[sNewLabel];
sDataType = oField.GetDataType();
sLength = oField.GetLength();
sReq = oField.IsRequired() ? “*” : “”;
sCalc = oField.IsCalc() ? “C” : “”;
Open UI renders control labels by replacing characters such as
spaces with underscores and appending “_Label“. So in order to
be able to target the label using jQuery we must do something
like the following, showing off our regexp skills with the
replace() function.
sLabelName = sControlName.replace(/ /g,”_”) + “_Label”;
This works for most of the labels, but not for those with
brackets or hash (#) in the name BTW.
Labels are rendered as <span> elements, so we must create a
similar element but with different enclosed text.
sLabelHTML = “<span id='” + sLabelName + “‘>” + sNewLabel + ”
(” + sDataType + “/” + sLength + “)” + sReq + sCalc +
“</span>”;
As you see, we concatenate the variables collected above to a
new label which looks like this for a calculated field:
BCFieldName (type/length)C
Now we are ready to swipe the jQuery magic wand. We declare
the parent element of the label the current target:
target = $(“span#” + sLabelName).parent();
then we replace the HTML with our concoction:
target.html(sLabelHTML);
and finally (just for the sake of demo) apply some makeup. In
a real life implementation, please do not use hard-coded
styles, instead use proper CSS classes.
target.css({‘font-style’: ‘italic’, ‘color’: ‘#FF0000’});
And that’s it!
We already know how the result looks like but it’s really
stunning that it works on almost every form applet and is
super-fast thanks to the Open UI framework.
Click to enlarge
Summary
In today’s part of a two-post mini-series we explored how to
teach all form applets at once to capture double-clicks.
Furthermore, we introduced the comfort zone of the
presentation model which allows us to retrieve all kinds of
useful metadata such as BC field properties without a server
round-trip.
Again, please understand that all examples and code that I
present on this blog are solely for illustrative purposes and
that it has NOT been tested against a production system. So I
hold absolutely no liability for any issues or damage should
you decide to use the code presented in this blog.
In the next part, we will explore how to actually do a server
round-trip in order to retrieve repository metadata which is
not available via the presentation model such as table and
column names.
have a nice day
@lex
Download