About View in Standard Interactivity - Part 2

In the previous article, we discovered a hidden object called SWEApplets, that provides us access to the rendered Siebel view.

We will learn how to utilise these objects to create funky developer tools, that will make your colleagues envious =)

To begin with, we need our tool to be as portable as possible, it has to work in any environment without requiring changes to the respository, srf, template files or environment.

We can do this, by hooking into the current Siebel session, and injecting our own code that interacts with these objects.

This can be achieved by typing typing javascript statement in the address bar of your browser, such as

javascript: alert( top.SWEApplets[0].ViewName );

Remember this particular object only responds correctly in SI, but you can still try it in HI.

The above technique is useful for simple discovery of objects, but for more advanced requirements, we can write our logic in an external file and inject the file into our session, by using a bookmarklet.

Now create your js file, and put the following line of code in it

//myfile.js
alert( top.SWEApplets[0].ViewName );

You can put this file anywhere, in your C drive, in your Siebel web directory, or on an external website. For local development, i like to put my file outside the Siebel web directory, so it doesnt get cached by the browser.

The next command allows us to inject this external file, and run all its contents in our browser session.

To use this, create a Favourite, and paste the following code into the URL of the bookmarket.

javascript:if(document.getElementById('fs') != null){document.getElementById('fs').removeNode(true);};
s=document.body.appendChild(document.createElement('script'));s.id='fs';s.language='javascript';
void(s.src='http://localhost/myfile.js');


Now with the basics out of the way, we can write any standard javascript, and this will be executed on the fly in the browser.

To get About View SI as promised, put the following code in your external file

var sView = "";

if (SWEApplets.length > 0) {
sView += "[ViewName]
";
sView += SWEApplets[0].ViewName + "

";
sView += "[Applets]
";

for ( var i = 0; i < SWEApplets.length; i++)
{
if ( CurrentAppletIndex == i )
sView += " * " ;
sView += SWEApplets[i].Name + "
" ;
}

if (PopupAppletName != "")
{
sView += "
[Last Popup]
";
sView += PopupAppletName;
}

}
alert( sView );


What we've done is iterate through the SWEApplets array, and construct our desired output using the values from the objects methods.

Notice that, we prefix the currently selected applet with a nice little "*". If you have 10 applets in a view, this quickly tells you which applet you are looking at.

There are better ways of displaying this information, and the alert will be annoying to some, but how you want to display this, is limited by your creativity

Its only taken us 5 minutes to build this developer tool, but the tricky part is discovering all the available objects.

If you are bored, you can find this information in the Siebel browser framework files in the public\files\ folder.

Siebel engineers will have access to internal information about these objects, but for people outside looking in, it may seem very cryptic. Not every object is useful or an object could be useful but without knowing what it does, it is infact useless, and not every useful object is easily discoverable.

The basis of most of my hacks rely on injecting javascript into the current Siebel session, although this tool only works in SI, the same technique can be used for HI, you just need to know which objects to access.

In closing, its important to note that, neither Siebel nor myself, recommend the referencing of these objects in the repository or web templates.

These objects belong to the Siebel browser framework, and can change at any time (Yes, this really happens =).

Any use of these objects will not be supported by Siebel, they are undocumented for a reason!

About View in Standard Interactivity - Part 1

The above title might seem like an oxymoron to all those experienced Siebel Standard Interactivity developers out there, but its true, there is something sadly missing in SI. I recently had my first taste of a SI application, since Siebel 6 Dotcom, and my first question was...

Wheres about view?

I wanted to know what view i was on, and what applet i was looking at.

I thought someone had customized the application and removed this option, and then i heard a snicker in the background. One of the seasoned SI developers responded, saying "everyone asks this question!", and provided me with the technique.


    How to find the Applet name
  1. Right click on the View and select 'View Source'
  2. Goto the bottom of the HTML source and start scrolling up
  3. You will see a list of applet names in reverse order

    How to find the View name
  4. Scroll up a little further and you will see the view name


This trick was provided by Siebel Expert Services, and although it works, you still have to hunt for the names.

Imagine using this method on a monday morning! I know this can be useful in HI for finding the name of a popup applet, but it is quite cumbersome and repetitive.

In summary, you dont have the luxury of About View in SI...

So what if i said, i can give you About View in SI + more than you bargained for? Welcome to Impossible Siebel.

The technique that i'm going to show, relies on accessing hidden objects in the Siebel frames. I mentioned this in passing in my first article about the Siebel HTML structure, and gave a clue to an undocumented interface, but to stay on track for this topic, we're going to look at the SWEApplets object and its related properties.

SWEApplets
The SWEApplets objects is an array that contains all the rendered applets in the Siebel UI, and by accessing this object, we can discover useful information about our current view.

Properties
Name: Name of Applet
ViewName: Name of Applet's View

CurrentAppletIndex
This property tells us which applet in the above array is selected by the user, usually it means the highlighted applet. For home pages, you can still click on an applet, and it will not be highlighted, but you can still get the current index.

PopupAppletName
This property contains the name of the last popup applet that was displayed.

Armed with the above information, we can construct the following program in < 5 minutes that displays About View information for us in SI.



For those who have never used SI, you can still follow this tutorial, because there are some common fundamentals worth knowing, that apply to both SI and HI.

There is enough information here, for the creative Siebel developer to pick up and implement, but for the law abiding Siebel citizens other there, stay tuned for the next episode to see the actual implementation...

Pop up window for dual screen computers from 8 +

In one of my recent articles, i gave a tip on how to make pop up windows display on the same screen as the browser window in Siebel 7.

Those people, who have 2 or more monitors, will understand this problem very well, but this trick no longer works in Siebel 8. After searching on ML without any luck, I started to do some trial and error.

The Siebel 8 client config file dosnt have a [SWE] section, and creating this section with the value PopupSizeConstrained = TRUE, dosnt do anything.

Neither does creating an Application user property with the same parameters under the Application object, but if we move it under the [InfraUIFramework] section, it should start working again!


[InfraUIFramework]
PopupSizeConstrained = TRUE


This has been tested in Siebel in 8.1.1.

Solution - Show creator full name on 'About Record Applet'

Impossible reader Sajan, has responded to the 'About Record Applet' Challenge.

The solution Sajan shares, higlights the use of ShowControl.

The WebApplet_ShowControl event is only supported in Standard interactivity, and allows us to modify a control as it is being rendered to the user.

By trapping this event, Sajan can intercept the rendering of the Created By and Last Updated By fields, send the login Id off to a server script function to resolve it to a persons name, then inject the value back into the HTML stream on the fly.

Sajan's solution

//Object: Applet
//Object Name: About Record Applet
//Event: WebApplet_ShowControl
//Script: Server Side

function WebApplet_ShowControl (ControlName, Property, Mode, &HTML)
{
if ((ControlName == "CreatedBy") && (Property == "FormattedHtml"))
{

var temp =HTML;

//Capture the LOGIN only
var temp1=temp.substring(temp.indexOf(">"));
loginid= temp1.substring(1,temp1.indexOf("<"));

//Method to pull Full Name based on the Login
HTML = fetchfullname(loginid);
}
}

This technique is useful for tricky client automation problems, and can be used to perform more complex logic, by injecting javascript into the HTML, which executes when it loads in the users browser.

Why would we want to do this?

  • Auto-completing fields
  • Auto submitting a form
  • Scrolling to a desired position in the view
  • Changing the look and feel of an applet dynamically


What if the business insisted that we change the background image of the 'About Record Applet', and have a different picture displayed every time it is opened?

We never say no around here =).






387uh4ap2x

Reader Challenge - Show creator full name on 'About Record Applet'

This is our second reader challenge, and i've come up with something more achievable, but still impossible (our definition of impossible is when Siebel says it can't be done).

As usual, this will take under 5 < minutes to prototype, and will be fun to try.

Requirement
When the user clicks on About Record, display the actual First Name + Last Name, instead of the Login Id next to the 'Created By' and 'Updated By' labels.

Before


After


Why its impossible
1. It runs from class code and the available fields are hard coded
2. There is no underlying BC

Some people will find the above challenge too simple, so have a go at the first reader challenge which is a lot tougher.

Return statement supressess error in script

The following tip belongs in the obscure category, and is worth understanding, because it can easily lead to mysterious problems in your code.

Requirement
Write a sub function that returns a boolean on wether a record exists or not in a BC, and do further processing based on the result.

The logic would look something like this.

function doesRecordExist()
{
var bExist = false;

try {
//query bc logic
//if record exists
bExist = true;
} catch (e) {
throw "doesRecordExist > Error: " + e.toString();
} finally {
return bExist;
}
}

There is nothing wrong with this code, and it works very well... except when there is an error.

So, what happens if we introduce a deliberate error in the code?

function doesRecordExist()
{
var bExist = false;

try {
var DummyObject = {};
DummyObject.dummyMethod();

//query bc logic
//if record exists
bExist = true;
} catch (e) {
throw "doesRecordExist > Error: " + e.toString();
} finally {
return bExist;
}
}

What we've done, is declared a dummy object and called a non existent method, this will cause it to error and jump to the catch statement.

The error will be thrown, but when it hits the finally statement, the function returns the boolean back to the originating caller and supresses the error from our sub function. This is very undesirable for obvious reasons.

In this scenario, the error will never make it out of this function alive... unless the exception happens in the finally block as seen in the solution below.

function doesRecordExist()
{
var bExist = false;
var sError = "";

try {
var DummyObject = {};
DummyObject.dummyMethod();

//query bc logic
//if record exists
bExist = true;
} catch (e) {
sError = e.toString();
throw "doesRecordExist > Error: " + sError;
} finally {
if ( sError.length > 0 ){
throw sError
}
return bExist;
}
}

In the above code, the system will raise the first exception which will be caught by the catch statement, it will then go into the finally and we re-throw the exception back to the caller. We can then bubble the error back up to the root function and handle the error there.

A simpler solution would be to put the return statement at the end of the function body, but purists will insist the return statement should go into the finally block.

function doesRecordExist()
{
var bExist = false;

try {
var DummyObject = {};
DummyObject.dummyMethod();

//query bc logic
//if record exists
bExist = true;
return bExist;
} catch (e) {
throw "doesRecordExist > Error: " + e.toString();
} finally { }
}

Another alternative solution comes from our friend, the creator of the ABS framework.

function doesRecordExist()
{
var bExist = false;
var bError = "";

try {
var DummyObject = {};
DummyObject.dummyMethod();

//query bc logic
//if record exists
bExist = true;
} catch (e) {
bError = true;
throw "doesRecordExist > Error: " + e.toString();
} finally {
if ( !bError ){
return bExist;
}
}

In this solution, we throw the error inside the catch, and in the finally block, we check if an exception occurred and prevent the function from return a value and therefore suppressing the exception, otherwise if no exception occurred, we allow the function to return the boolean, and we continue processing normally.

This behaviour may seem elementary, but it can easily trap junior and senior programmers alike, and is well worth recognising.

Pop up window for dual screen computers from 7.5.3 +

There is a little known trick that is documented in ML (Siebel CRM Fix Pack Guide, version 7.5.3 [Doc ID 546998.1]).

It is so useful and yet so sad that many people are living without it. For people with dual monitors, when you open up a popup, it appears only on the primary monitor.

For example, if you have your Siebel client on the secondary monitor and click on a popup applet, it opens in the primary monitor, to me thats almost half way round the other side of the world.

This is pretty unforgivable, and yet people just accept it as a fact of life, but there has been a fix for this since 7.5.3.

Who really looks through all the Oracle/Siebel fix documentation? Not until we are really annoyed with the behaviour.

The fix is simple, put the following line under the [SWE] section of your config file

[SWE]
PopupSizeConstrained = TRUE

Now like some sort of magic, all your popup windows will appear on the same monitor that your Siebel client is located.

Exporting different objects into one SIF

As a developer, we sometimes need to retrofit changes from one environment into another.

Siffing is dangerous and some projects have banned this practice because the likelyhood of inadvertantly overwriting someoneone elses work.

Reimplementing is safer and recommended, but there are times when you want to SIF.

Heres a tip that allows you to SIF out different objects into one SIF file.

Its easy to SIF out multiple objects of the same type, but if you have objects that lie in different parts of the explorer tree, you cannot do a group selection.

For example, if you have an applet and BC that you want to export, you can combine this into one file very easily, by performing the following process.

1. Find the first object that you want to export, and select 'Add to Archive'
Applet: ACD Transfer Call Applet


2. Leave the Archive window open, and move it out of the way. It will stay modal, but still allow you access to your explorer.


3. Find the second object that you want to Archive, and select again 'Add to Archive'
BC: AICC SCORM Import Course


4. Click Save, and Siebel combines all those object definitions into one SIF file.


Now you can import this SIF back into another repository. This is really useful, and a lot safer than doing project imports.

This is really simple, and potentially obvious to a lot of people, and would not normally meet the criteria to be posted here, so I asked some of the most senior people around me, if they could do this but was told it can't be done.