Showing posts with label Solution. Show all posts
Showing posts with label Solution. Show all posts

Solution - Popup Applet "X" button

This is the long awaited solution to the Popup Applet X button challenge, which was solved by Master configurator Michael Feng.

[Background]

Siebel provides us with two events on popup applets, represented by the buttons "Ok" and "Cancel" which provides the neccessary hooks to capture most business requirements around closing of popup applets.

But the "X" button is an exception case, where the user forced closed the applet without completing the required interaction. In these cases, you might want to rollback any changes that were made since the applet was opened, or popup an alert to educate the user of the consequences of not closing the Applet properly.

[Siebel popup applets]

It is important to understand what happens when we click on the "X" on a popup applet in Siebel. The developer who requested help from the Oracle forums, tried attaching a custom method on window.onunload, which is a native browser event for when the current view has been navigated away from or closed.

This is the right line of thinking, and isnt far off from Michael Fengs solution below. This would normally work for traditional web apps, but Siebel dosnt close the popup applet when you click "X", it just minimizes it and hides it under your taskbar, which is why the window.unload event never fires.

The way to see this in action, is to set your taskbar to auto hide, watch what happens when you click "X" on a popup applet. You'll see it minimized to a short title bar on the bottom left of your screen, underneath where the taskbar would normally sit when displayed.

[Usability]

The reason why Siebel does this is for usability. When you log into your Siebel application, the first time you open any popup applet will always be the slowest, thats because Siebel has to spawn a new instance of an IE window. When you click "X", siebel will minimise and hide the window. The next time when you open another popup applet, Siebel will re-display and re-use this same popup window.

Re-displaying an existing window is in order or magnitudes faster than opening a brand new window, and greatly enhances the user experience in HI applications.

[Solution]

As mentioned in the original post, there are various solutions to this problem. When the popup applet is closed, focus will return back to the control/applet that invoked the popup applet, and you could, pop up a confirmation at this point, but it is ugly, if the popup applet is used in many places then you would have code on a lot of base applets.

Since the Popup applet is never closed, another idea is to set a looping timer to determine the position of the applet, and if it disappears below the taskbar then we know it has been closed. Its not a desirable solution as polling adds overhead. So the ideal solution is to trap the X event on the popup applet itself.

One alternative is to attach a custom function to the window.onmove event of the Popup applet which would give us a real time notification everytime the applet gets moved, and if it moves to the taskbar position, we know the user clicked X.

Or we could do better by detecting when the physical dimensions of the Popup applet has been shrunk by monitoring the window.onresize event.

Heres how it can be done, the following code is provided by courtesy of Michael Feng.

function Applet_Load () {
var oCon = this.FindActiveXControl("NewQuery");
var obody = oCon.document.body;
var odiv = oCon.document.createElement("script");
odiv.type = "text/javascript";
odiv.language = "javascript";
odiv.text = "window.onresize=UnloadTrigger;function UnloadTrigger(){if(document.body.clientHeight==0&&document.body.clientWidth==0){alert('You close the popup applet');}}";
obody.appendChild(odiv);
}

An interesting question is, what happens to the UnloadTrigger that is attached to our first popup window, when a second popup is called after the first? Does it still linger around, even when if its unwanted on the second window? Siebel re-renders the entire contents of the applet everytime it is "re-used", but keeps a cache of the last applet.

Base applet --> Popup Applet A --> Popup Applet B

Siebel will cache the contents of Popup Applet A when it is opened, Siebel re-uses the popup window, and renders the HTML for Popup applet B when it is opened.

When Popup Applet B is closed, Siebel will reuse the popup window, and restore Popup Applet A from its cache, therefore restoring our UnloadTrigger.

So we have to modify the solution to deal with the fact that popups can spawn other popups.

function Applet_Load () {
var oCon = this.FindActiveXControl("NewQuery");
var obody = oCon.document.body;
var odiv = oCon.document.createElement("script");
odiv.type = "text/javascript";
odiv.language = "javascript";
odiv.text = "window.onresize=UnloadTrigger;function UnloadTrigger(){if(document.body.clientHeight==0&&document.body.clientWidth==0&&!Top().SWEPopupGainFocus()){alert('You close the popup applet');}}";
obody.appendChild(odiv);
}


The above code uses and undocumented function Top().SWEPopupGainFocus() to determine if a popup is in focus or not. We only want to display a message when there is no popup open.

The last piece to this puzzle is to handle the positive events when the user click on "Ok" and "Cancel", in which event we do not want to display our message. You'll need to set profile attributes, or view variables to indicate that the applet was closed properly, and check for these variables in the unload function.

function Applet_Load () {
var oCon = this.FindActiveXControl("NewQuery");
var obody = oCon.document.body;
var odiv = oCon.document.createElement("script");
odiv.type = "text/javascript";
odiv.language = "javascript";
odiv.text = "window.onresize=UnloadTrigger;function UnloadTrigger(){if(document.body.clientHeight==0&&document.body.clientWidth==0&&!Top().SWEPopupGainFocus()&&App().GetProfileAttr('ProperlyClosed')!='Y'){alert('You close the popup applet');}}";
obody.appendChild(odiv);
}

Thanks to Michael for providing this solution, and for helping solve another impossible problem and breaking new grounds on creativity =).

Solution - Mouseover Tooltips (Scriptless) Part 2

This is the final article in our Impossible Tooltips challenge, if you have arrived here by accident, have a read of the precursor articles before going further.

1. Tooltips Challenge
2. Tooltips Solution Part 1
3. Tooltips Solution Part 2 (You are here)

The solution below has been freely available on the Impossible Siebel group for over a month now, and has been available to hundreds of people.

If you havnt already joined, or dont have a friend who is in the group to give you the inside information on our Siebel challenges, join now! There is no non disclosure agreement, take the information and share it.

Originally, I posted this tooltip challenge 6 months ago, but the seed for these articles started over a year ago, does any one remember the first Impossible Siebel poll? Interestingly the tooltip solution finished last on the results.


To quickly refresh your memory, in the last article, we injected artificial browser events into the label caption and used to HTML to display our Tooltips, but that solution had two drawbacks.

1) Unlimited text
2) Dynamic text

The more "important" issue here is the text length, but both these problems can be killed with one stone.

[Scriptless Solution]

The usefulness of the label caption is limited by its text length, but we can cheat by using a calculated field and put it in the position of the label, to act as the 'label' on the form applet.

This can be a little tricky, so we'll start with a basic example on how to implement this.


"<p onmouseover='alert(""Disco Forever"")'>Disco</p>"

Notice that with calculated fields, we need to enclose the expression with double quotes, and also escape any double quotes to become a pair of double quotes. There is no way to quickly simulate calculated fields, so an incorrect attempt at this expression may suggest that the idea dosnt work.

So here is our calculated field expression, with escaped quotes.

"<p onmouseover='var d=document.createElement(""div"");d.id=""t"";d.innerHTML=""Hey"";this.appendChild(d);' onmouseout='var d=document.getElementById(""t"");d.parentNode.removeChild(d);'>Disco</p>"

Create a field control, ensure that the control is set to dontencodedata and HTML Type is set to Plain Text. Map this control to your applet mode, compile these changes, and you'll notice that the real label and the calculated field behaves the same on surface value.

By using calculated fields, we can concatenate several other calculated fields together to get around the character limit, and by the nature of calculated fields, we can also take advantage of the fact that we can pull data dynamically through them. For example, we can retrieve other field values, get profile attributes, and even call business services.

However using calculated fields in this way will become incredibly complicated, especially if you have more than one field. Every field might have multiple concatenations, and the logic for creating and display the tooltips could be duplicated hundreds of times. Imagine having to change the style of the tooltip across the application, this will be quickly become unmaintainable.

This concept is only provided to illustrate that it can be done without scripting, but for practicality writing script in this case is much more sensible.

[Scripting Solution]

We will create two custom global browser script functions called showDiv() and hideDiv(), which will be fired by our artificial onmouseover and onmouseout events. This will offload the creation, as well as the styling of our tooltips, to a central place. Then all we need to do, is pass parameters to these functions, to display the tooltip.

The following example creates a really simple tooltip, but what you can do with it is only limited to your HTML skills.

Eg. you can make it float rather than append, you can add pictures, titles bars, rounded corners, play a sound etc.

Modify the calculated field, or Label to look like this:

"<p onmouseout=top.hideDiv(this) onmouseover=top.showDiv(this,'Hey')>Disco</p>"

In your Application browser script or business service, attach the following functions to your "top" object.

top.showDiv=function(that,m) {
var d=that.document.createElement("div");
d.id="Disco";
d.innerHTML=m;
that.appendChild(d);
}

top.hideDiv=function(that){
var d = that.document.getElementById("Disco");
if (d!=null) d.parentNode.removeChild(d);
}


The "expresssion" in this label caption uses about 80 characters, and still leaves a lot of room to display a useful tooltip without using multiple calculated fields, and if you dont require dynamic text, stick to using the label caption, otherwise the calculated field offers a bit more flexibility at the expense of maintenance.

You still can build some logic in the global showDiv() and hideDiv() functions to enable the label method to be a little dynamic, but it depends on how contexual you want your dynamic labels to be.

If you are one of those control freaks, then you also might want to offload the management of the tooltips text to a central location, rather than hardcoding the text as a parameter, we can hard code a reference to the label and perform a lookup.

A modified solution would look like this, create your calculated field as follows

"<p onmouseout=top.hideDiv(this) onmouseover=top.showDiv(this,'MyApplet.MyLabel')>Disco</p>"

In your Application browser script, change your showDiv function as so

top.showDiv=function(that,lov) {
var m = lookupValue("MY_LABEL_LOV_TYPE",lov);//lookupValue is a custom function that retrieves LOV values from the database.
var d=that.document.createElement("div");
d.id="Disco";
d.innerHTML=m;
that.appendChild(d);
}

This way BAU can change the labels without re-compiling the SRF, and provides clients in regulatory situations to quick adapt to changing needs.

[Floating, Appending, Positioning the tooltip]

The solution that i've provided above, appends the tooltip and positions it underneath the label, the position is always relative to the label. Some readers who i gave out the solution to, modified the solution to use absolute X,Y co-ordinates. I've also seen variations of my solution that have been modified to use <span> tags.

I've found that mouseovers dont work correctly on span tags in Siebel, so if you have problems with the mouseover not triggerring, try changing it to a <p> (paragragh tag).

Should you float or append? For short tooltips, appending is easier, because the solution is a lot less complex. When your text or styling makes the tooltip too big, it will start to push your controls out of alignment. To overcome this issue, you need to implement a floating tooltip, as seen on my screenshots on the original challenge.


[Dealing with the ActiveX]

The floating tooltip will not be effective, unless you deal with the ActiveX problem. Web professionals will know that elements on a web page can be layered, and each control can be set with a layer order to make it appear in front or behind another object.

ActiveX controls are a little different, because you cannot set the layer order on these type of controls, they just appear on top of everything else on the webpage. So if you try to implement a floating tooltip that lies in the path of a dropdown box or any other Siebel ActiveX control, your tooltip will be hidden by the control.

To get around this, we have to use a really obscure web developer trick, the "iframe technique".

var if=that.document.createElement("iframe");
if.id="iFrameDisco";
if.style.width = your tooltip width
if.style.height = your tooltip height
if.style.top = your tooltip Y position
if.style.left = your tooltip X position
if.style.zIndex='998';
if.style.filter='progid:DXImageTransform.Microsoft.Alpha(opacity=0)';

The above code creates an iframe of the same size as our tooltip, the next step is to create our tooltip to sit above this iframe (it is important that both the iframe and the tooltip are the same size).

This little trick allows our tooltip to float above the ActiveX controls in Siebel and is the same technique, that i've used in the ImposSiebel toolbar to float the AboutView dialog on top of the Siebel ActiveX elements.

[Conclusion]

This solution is unconventional, even if you consider the scriptless option, and depending on what kind of effect you are after, it can become very complex, but when used strategically, your users will be happier than any other siebel user in the world.

Keeping your users happy is very critical, and will be the subject of a series of future articles, but for now, the Siebel community can say that our million dollar system can do Tooltips!

Our regular readers probably saw this coming, but this is where we introduce a disco tune to the audience.



I cant think of a better disco tune than "One way ticket" to compliment this article, wether you like Neil Sedaka, Eruption or Boney M, this is a killer disco track.

Solution - Mouseover Tooltips (Scriptless) Part 1

I've been receiving a lot of requests from Siebel professionals to provide the solution to the tooltips challenge, and though i've provided the solution privately to needing customers, i've realised that implementing it can be tricky, so in this article so i'll provide a walkthrough of the fundamental configuration needed to achieve a basic solution.

[Background]

To provide some perspective on this problem, lets have a look at a real life scenario from a customer on the Oracle forums.

"We have been struggling with a user request:

The users have requested that we change default Siebel Tooltip behavior so that if we hover the mouse over some select fields(In this case a credit code, among others) that the tooltip contain information that can help the user to understand the value. Whether this is the definition of the actual value or a short list of actual values is still up for debate. Alternate approaches like populating the status bar with a value, theoretically the definition of the current value, and providing a help icon with a tooltip or message that contains reference info for the column below, have been discussed, but these are not preferred.

So has anyone ever tried to highjack the tooltip functionality? I'm not going to say that the existing functionality (Displaying the full value of the current field) isn't useful in many cases, but that functionality is useful for the codes that we are looking at(WHich are typically smaller then the existing field) and this would be a far better use of the functionality.
"

source: http://forums.oracle.com/forums/thread.jspa?threadID=577955&tstart=525

[Million dollar system]

The Siebel UI can be quite overwhelming, so its understandable that business want to implement tooltips, to provide its users with visual clues and help the user perform their duties. This is the one requirement that every BA has asked once in their Siebel career.

But when the business ask for a simple feature such as floating tooltips, and we say its not possible. It becomes a little embarasing, when they ask why a system, they've spent millions of dollars on, cant offer tooltips, which have been around since the beginning of the web.

[Workaround]

A primitive technical solution to this, is to utilise the caption override on the label, and hard code text into the alt or title attributes.
<span alt='Disco Forever'>Disco</a>

This dosnt meet the requirement of the impossible challenge, but it also has an annoying side effect, in that the tooltip vanishes too soon. So if you want to provide a few lines of text for the user to read, they'll have roughly 5 seconds to read it all, before it disappears.

Some readers have reasonably guessed that we need to use the onmouseover and onmouseout events in browser script control events to deliver this solution, as it is the most obvious mechanism to create a floating dialog, however the only problem is, these browser events are not available in HI environments, and it also involves scripting.

But read on, and i'll show you how to bypass these obstacles.

[Solution]

To get around the HI browser events limitation, we can inject custom onmouseover and onmouseout events on the label caption as so.
<p onmouseover='<Show our tooltip>' onmouseout='<Hide our tooltip>'>Disco</p>

This lays the foundation for the rest of the challenge, and offers us the launchpad to use some HTML magic to display our tooltips.

Here is the caption override that is needed to display a tooltip.
<p onmouseover='var d=document.createElement("div");d.id="t";d.innerHTML="yeah";this.appendChild(d);' onmouseout='var d = document.getElementById("t");d.parentNode.removeChild(d);'>Disco</p>

What the above syntax does, is creates a DIV element on the fly and injects it underneath the current object, which in this case is our field label object.

Our label now has two custom events that will fire off code to display and hide the tooltip accordingly. The tooltip will hang around as long as the mouse cursor is hovered over the label, and disappear swiftly when the mouse moves away.

But lets not celebrate so soon, because this solution has the following draw backs, the tooltip text is limited by the repository length of the caption field, our creativity with the tooltips is also severely limited by the caption length, and hard coding the text here would make it difficult to maintain.

We can dress it up by adding a little style
<p onmouseover='var d=document.createElement("div");d.id="t";d.innerHTML="yeah";d.style.backgroundColor="red";d.style.borderColor="black";this.appendChild(d);' onmouseout='var d=document.getElementById("t");d.parentNode.removeChild(d);'>Disco</p>

This looks a little better, but uses it up every (255) valuable character, and leaves no room for a useful tooltip.

This is the most "vanilla" result, and is not very useful, but it does provide the basic framework for others wishing to get further with this challenge.

[Until next week]

The most important hurdles have been taken away

1) Mechanism to Display/hide a persistent floating tooltip
2) Achieved by using a caption "expression" and hence Scriptless

But the following aspects of the challenge remain un-met

3) Unlimited text
4) Dynamic text

In the next article, i'll provide the full solution and bust the myth that Siebel cant do tooltips.

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