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 =).


Reactions:

19 comments:

  1. Thanks so much for Jason's efforts to create this fantastic blog. Such blog has taken a lot of time but also stored so many priceless Siebel experience.

    As his loyal follower, it is my great pleasure to provide more solutions to "impossible siebel problems" in the future.

    Michael Feng

    ReplyDelete
  2. Hi,

    I need something much more simple, but I can't find any description how to do it. I want the popup applet to close when "OK" is pressed and the method invoked finishes running.

    This is not happening for me right now, with Method Invoked set to a custom method for the "OK" button.

    Thank you in advance,
    Yossi.

    ReplyDelete
    Replies
    1. Hi,
      You can use the CloseApplet method to close the popup applet

      Delete
  3. @Michael, Its good to have experts like you do all the hard work for me =)

    @Yossi, You can invoke "CloseApplet" after your custom method to close the applet.

    ReplyDelete
  4. Hi, I got this to work for showing an alert, but I need more. I need to call a business service. I can't get that to work, and it is also unclear to me whether I should use App.GetService() or theApplication.GetService()?

    Thanks

    ReplyDelete
  5. Hi Wannes

    Use theApplication.GetService() as it is the official interface.

    From a popup, you might need to make the call as follows.

    opener.top.theApplication.GetService()

    > opener.top.
    This opener 'prefix' is needed, because you are on popup applet. the 'top' refers to the top level window, where that API should be available.

    ReplyDelete
  6. Hi All , can anybody advice how to trigger CloseApplet ? I tried opener.top, top, this.InvokeMethod('CloseApplet',ps) but was not successfull on Columns Displayed Popup Applet (SWE).

    ReplyDelete
  7. Hi Martin,

    the opener.top, top references aren't relevant when you are invoking methods on the current applet browser object context.

    Can you elaborate on your requirement, and post more code, so we can see the context?

    ReplyDelete
  8. Setting DisableShortCuts Applet user property to TRUE disables the X button on the applet.

    ReplyDelete
    Replies
    1. I confirm this is the simpliest workaround!

      Delete
  9. Hi Jason, thanks a lof for your reply and birliant idea. The whole story short : We will temporally use Siebel HI 8.1.1.11 with IE10 in Compatibility mode. With our PoC which was donw ith the Siebel 8.1.1.10 no side effect were detected. Currently in the Siebel 8.1.1.11 Patchset 7 the x button for all popups works only once. After first invocation it does not close Popup Applet. To workaround this issue I am injecting into Popup webtemapltes e.g. CCAppletItemsDisplayed.swt this code :

    window.onresize=Trigger;
    function Trigger()
    {
    if(document.body.clientHeight<100&&document.body.clientWidth<300&&!Top().SWEPopupGainFocus()){
    var ps = top.theApplication.NewPropertySet();
    top.InvokeMethod("CloseApplet",ps);
    }
    }

    I can see the event is triggered, but I do not succeed to invoke CloseApplet method to ensure the popup gets always closed with this method. Thanks for your opinion. We do know that Siebel 8.1.1.1 High Interactivity with IE10 in Compatibility Mode is not recommended and supported but for some interim time we should live with it. After of course Open UI will be introduced to users.

    ReplyDelete
  10. Yes, I was bit concerned when you mentioned IE10 and HI together, but you seem to have your reasons.

    The reason why your code isn't working, is because it doesn't have scope of the applet browser instance, and generally if you cannot close the window physically, a programmatic solution won't work, but you could try these methods

    1. Use window.close(), instead of the Siebel API.

    2. In browser applet load, add the following line
    top.thisApplet ={ctx:this,ps:theApplication().NewPropertySet()}

    then replace this line
    top.InvokeMethod("CloseApplet",ps);

    with this line
    top.thisApplet.ctx.InvokeMethod("CloseApplet",top.thisApplet.ps);

    3. Put a button on the popup applet, and define it the CloseApplet invokemethod

    ReplyDelete
  11. Martin,
    Your issue with "X" in HI IE11, is that resolved now?

    We are also facing similar issue and challenge is same. We have to support HI IE11 till Open UI is fully functional.
    In addition we are also facing another issue in HI IE11. PopUp window of Browser "Confirm' and 'Alert' are either opening behind the Siebel window(Not visible to users) or unresponse if they open in Front. In both cases workaround is that users have to minimize the Siebel Application window. Then they can click on Ok/cancel buttons on PopUp.

    ReplyDelete
    Replies
    1. we are also facing another issue in HI IE11. PopUp window of Browser "Confirm' and 'Alert' are either opening behind the Siebel window(Not visible to users) or unresponse if they open in Front. In both cases workaround is that users have to minimize the Siebel Application window. Then they can click on Ok/cancel buttons on PopUp.

      Any solution on this please?

      Delete
  12. Hi Guys, I cannot reproduce the pop under behaviour in IE11, using the alert,confirm dialog in IP2014 or IP2015.

    A possible consideration for further research, is to try rolling your own prompt,alert implementation, as floating div's in the Siebel window. Remember to put it in a global library, so you can switch the implementation easily if needed.

    Watch out for the activeX zOrder, as described in this article
    http://www.impossiblesiebel.com/2010/11/solution-mouseover-tooltips-scriptless_09.html

    ReplyDelete
  13. I am curious how this behavior differs in Open UI (w/ IP2014 or IP2015) instead of HI? Also when using Chrome & Firefox versus IE?

    ReplyDelete
  14. Hi I am having a small that became very annoying for the users. I am using Siebel 8.2.2.2 with Internet Explorer 9. The problem is that when I am using a MVG applet to create a register (address for example) and I save it with a data problem (fields missing, etc) the pop-up window with the error is raised behind the MVG Applet (Beetween the Siebel Window and the MVG applet) so the users cant see it so they think that Siebel is having problems because it doesnt respond. Is there a way to solve this? Maybe with browser scripts to bring that error pop-up to the front???

    ReplyDelete
  15. Hi Jason, I am having this problem with Siebel 8.2.2.2 on IE9. I am creating a new record (address) in a MVG applet the pop-up message when I missed a field is raised beetween the MVG Applet and the Siebel window. So the users cant see it so they report problems with the application. Do you know a way so I can "bring to front" this pop-up? Maybe with a browser script or something like that.

    ReplyDelete
  16. Hi Sebastian,

    I have seen this behaviour when the message dialog has been implemented as a floating div. In this case you can make it appear on top, by changing the zOrder of the container of the message dialog.

    ReplyDelete

Comments are open to all, please make it constructive.