Understanding the scope of "this" in Browser script

Due to the un-holy interest in the browser script tracing feature of the ImposSiebel Toolbar poll, this article is a little treat for all the closet Browser Script fans out there.

The behaviour described below is fundamental to ECMA script, but will catch most Siebel professionals off guard, and theres a very good reason for this.

Lets start with an example to set the scene. This scenario is lifted from the following Article on the Siebel Support Website, and summarised below.

[Goal]
How Can You Use Browser Script in Siebel 7 onwards to Set Focus on a Different Applet or Control? [ID 477070.1]

[Solution]
1. Query for the applet that you want to receive focus. Add the following to the (general) (declarations) section of the browser script:

setTimeout("DoSetFocus()",1000);


2. Create the following function

function DoSetFocus()
{
var appFocus = theApplication().FindApplet("Account Entry Applet");
var objControl = appFocus.FindActiveXControl("MainPhoneNumber");
if (objControl.canHaveHTML == false) {
objControl.focus();
} else {
objFocus = objControl.getElementsByTagName("Input");
objFocus = objFocus[0];
objFocus.focus();
}
}

Since there is no error handling provided by the Siebel examples, we'll add some of our own.

1. We'll modify the solution a little, and put the setTimeOut in the Applet load section.


function Applet_Load ()
{
try {
setTimeout("DoSetFocus()",1000);
} catch(e) {
//handle error here
alert( e.toString() );
}
finally {
}
}


2. And here is the set focus function with a try/catch, but instead of hard coding the applet name, we'll just use this.Name().


function DoSetFocus()
{
try {
var appFocus = theApplication().FindApplet( this.Name() );
var objControl =
appFocus.FindActiveXControl("MainPhoneNumber");//change this to a valid
control

if (objControl.canHaveHTML == false) {
objControl.focus();
} else {
objFocus = objControl.getElementsByTagName("Input");
objFocus = objFocus[0];
objFocus.focus();
}

} catch(e) {
//bubble the error back up the chain to be handled
throw ( " > DoSetFocus > "+ e.toString() );
} finally {
}
}


3. Compile and run it.

If you've tried it, you will notice that all it does, is generate an IE javascript error.

We expect this code to get into DoSetFocus, and set focus to our desired field, and if there is any error, it should throw an error back to the caller, which will be handled by the alert() in Applet_Load.

So can anyone see anything wrong with this code?
There are actually two fundamental flaws.

To prevent any spoilers, do not scroll down any further, scroll back up now....




























If you've gotten this far accidentally, and wondered ...WHAT THE HECK WAS THAT? That is "Modern Talking", the best of 80s music from Europe.

This will bring back some good memories for GenX europeans, but for our majority US readers, i apologize, because sadly, Pop synth never caught on in the US, Australia or the UK, but in Europe and Asia this band was as big as the Beattles.

"You're my heart, you're my soul" was a master piece from this classic german duo.

If you are still following this genre, Thomas Anders "Good Karma (2009)", has that classic Modern Talking sound that is so hard to find now days.



And for good measure, you cannot mention MT without Sandra Cretu. Again for our US readers, MT and Sandra's success can be closely paralleled to MJ and Madonna in the states. If i could only pick one Sandra song, it would be "Maria Magdalena", this is quintisential 80s pop synth, and unmistakable euro disco.

This is your last chance, if you dont want to be spoiled, go back now, but if you've endured through that, it means you really want to know the answer by now...

Okay, have you had enough of 80s German pop bands? Here is the answer

[Issue 1]
the throw from DoSetFocus() is not caught


This should be self explanitory, the root of the function is no longer Applet_Load, so when we try to throw the error, there is no one there to
catch it.

The setTimeOut function causes the scope to change, and DoSetFocus becomes the root calling function. With that in mind, we just need to change the throw to an alert to handle the error.


[Issue 2]
this.Name() is out of scope


this.Name() will return the name of the current Applet inside the vanilla
applet events (listed below)

Applet_PreInvokeMethod
Applet_InvokeMethod
Applet_ChangeRecord
Applet_ChangeFieldValue
Applet_Load

But when it is used in a custom function or the declarations section, the behaviour is different.

[So what does 'this' refer to?]

'this' can refer to the parent or current object depending on the current context.

In the case above, under the vanilla events, 'this' refers to the current applet, but inside a custom function 'this' actually refers to the view frame.

This isnt a bug, and the behaviour is expected, if we understand how these functions are created or instantiated by Siebel. The exact mechanism behind this behaviour deserves another article, but for now just keep this behaviour in mind when designing your functionality.

If you want to reference the current applet, in our custom functions, the workaround is quite simple, just use a global pointer to the current object.

Under your (declarations) section put this code


var that = this;


Now, we can reference the current applet correctly in every function, by using that.Name()

After writing this article, i found this document on Siebel Support

What Is the Scope of the "this" Object in Browser Script? (Doc ID477659.1).

This article documents this behaviour just as i have, spooky!

There is an important point worth taking from this Siebel article. Any code that is written in the declarations of an applet, is shared among all the other applets in the same view.

This is because the code that is written in the declarations section is part of the view frame, and since all the applets are part of the same container, all the variables will be shared.

Let me put together a diagram, so we can see it visually...Here it is.



It just occured to me, this diagram reveals something i never thought about before, are you guys thinking what i'm thinking? This really belongs in the next article.

But to conclude this topic, there is something about Siebel (Doc ID 477659.1) that i would like to add. In this arcticle it states...


"In server script:

The this or Me object is the object whose script you are editing at the moment.".


What its saying is, if you are on a BC, this.Name(), will always return the name of the BC no matter which function you call it from, likewise for applets, and business services, this.Name() will return the name of the object you are in.

The author who wrote this support web document, had Siebel professionals in mind, and while this is true in most cases, it is not not entirely accurate.

In the continuation of this article, i'll show you an exception to this rule, and the reason for this, is the same reason why the scope is different in Browser script.

ImposSiebel Toolbar, UI Search Spec

In this article, we'll use the IS Toolbar to reveal the following information

1. Find hidden search specs
2. Find the BC field name without going into tools

Hidden Search Spec

The UI Search Spec feature is quite un-assuming, but it deserves some attention, because it can come in handy when trouble shooting problems.

When talking about search specs, people immediately think of Applet or BC search specs. These are a couple of objects in tools where we can configure hard search specs in the application.

We can also set search specs in script, but this can be dynamic and is harder to tell if the search spec is applied or not. Damn those crazy scripters for making our lives more complicated.

The same thing happens when we go to a view with a PDQ applied. The PDQ applies a runtime filter on top of the BC and Applet search specs.

The UI Search Spec feature dosnt (yet) pin point where these conditional search specs are hidden, but it does reveal if theres a hidden search spec applied.

The UI search spec feature will reveal any runtime search specs, and allows the user to see what is not obvious.

Instructions

1. Goto any view with a PDQ, or where you know there is script that sets a search spec, such as in the PreQuery event, or simply execute a UI query (this will set a UI search spec)

2. Double click on any Applet title bar to bring up About view

You should see the About View dialog, with the UI search spec information.


Find BC Field Name

By the very nature of UI Search Specs, we can also reveal the BC field name behind applet field labels.

Instructions

1. Goto any applet and find a field to investigate

2. Click on the Siebel Query button, and type in "AAA" in that field.

3. Execute the Query

Now, double click on the Applet title bar to bring up About View again, and you will see the BC field name for that label in the UI Search Spec.

I tried this on the First Name control label on an Activities applet and got the following information.



And we can see that the actual field name is [Act First Name].

Its simple and time saving but to be honest its kind of a hack, but i have a much more elegant solution in mind. This is on the horizon, so keep your eyes peeled for this feature.

For the record, here is the list of places in the application where you can set search specs.

Applet SearchSpec
BC SearchSpec
Picklist SearchSpec
Link SearchSpec
Script SetSearchSpec
Script SetSearchExpr
Script SetNamedSearch
WF Siebel Operation SearchSpec
Report SearchSpec
Task SearchSpec

Theres also the implicit search spec on Drilldowns, which catches some people off guard, because you do not actually set a search spec, but it is implied when you set the source id.

ImposSiebel Toolbar, SQL Profiling

How many of us actually care about SQL performance? Mostly, only Solution Designers, but its important that we *all* consider how much impact our config has on the system.

Have you ever clicked on a button and waited a good 30 seconds before the system comes back? If yes, then this article is for you.

There could be a number of factors contributing to performance issues, but i'm going to focus on SQL performance.

Siebel produces a spool file for us to analyse, which is really useful, but only a speed reading SQL geek would be able to correlate the SQL generated with the Application usage and add up the SQL cost in their head on the fly.

For the rest of us, we have the ImposSiebel SQL profiling feature.

This feature brings SQL profiling to the masses. The idea is, that any junior should be able to use this to identify parts of the config that is taxing the system, and suggest ways of improving performance.

Before you start, make sure you are running a thick client connection, and have specified a spool file. This can be done, by adding " /s c:\spool.sql" to your Siebel Client shortcut.

Scenario
Identify a part of your application that takes a long time to respond.

It could be a button, or navigating to a certain view, or triggering a bunch of scripts, or generating some data.

Find it, but dont touch it.

Profile it!
I assume at this point, you already have the ImposSiebel toolbar running.

Now click the SQL profile icon, its that funny looking icon, which looks like two cyclinders behind a refresh icon. It should be next to the IS menu.


This starts the profiling feature. The first time you click this, it will prompt you for the location of your SQL spool file. The default is c:\spool.sql, just accept this if you've followed the instructions above or enter your own file location.


If you want to specify another file, this can be accessed by the following menu option.


Now engage your performance hogging function, and wait until it has finished.

Click that SQL profiling icon again to toggle it off. We are now ready to analyse the SQL.


You should be presented with the following dialog.


This shows you the total SQL cost of your function, and also displays the top 10 SQL ordered descending by Cost, along with the corresponding line numbers in the spool file.

When a button is taking 30 seconds to return control, its usually caused by 1 or 2 bad SQLs, with this tool, we can instantly identify the culprit, and focus our efforts in reducing this cost.

Click on the cost for the desired result, and the offending SQL will be shown to you.


Now, unless that speed reading geek has photographic memory as well, i think we have the competitive advantage here, and have just saved ourselves atleast 30 minutes, swimming around neck deep in SQL statements.

Although this tool was designed for analysing SQL, another un-intended benefit, is general troubleshooting.

This dialog can reveal some interest things, just browsing the application can trigger database updates, such as read audit insert/updates in Siebel 8, docking inserts and unexpected write records.

I hope this encourages people to think more about the SQL cost of their config, and proactively address any issues before it becomes a BAU problem.

Troubleshooting
ActiveX warning


This dialog needs to be accepted. The profiling feature needs ActiveX to function.

IE Settings

If you are still having problems. Go into your IE Trusted Zone security settings, and enable the above options.

Remember to add impossiblesiebel.com and your localhost to your trusted zone.