Open UI: Close Popups on Escape Key

The ESC key in many traditional applications, provides a convenience shortcut to stop, undo, or go back in the application. It enhances the usability of an application by allowing the user to navigate backwards quickly or work more effectively work with two hands.

This feature is also built into major modern browsers, with the ESC key allowing users to dismiss dialog boxes. This feature works on native browser dialogs such as the alert, confirm and prompt dialogs, as well as artificial dialogs, such as the new notification pane seen in Open UI.



Right click on the Notification Pane, and inspect the source code behind this UI element. It will look something like this:



The class attribute of the container gives it away as a jQuery dialog.

You may not know it, but you will be interacting with jQuery dialog boxes throughout Siebel Open UI. Just inspect the browser source for any MVG, Pick or any Popup applet in Open UI, and it will reveal the same class attributes as the Notification Pane. This tells us they are constructed using the same plugin, except these other 'dialogs' cannot be dismissed with the ESC key.

Lets see if we can imbue these other applets, with the ability for us to dismiss them using the ESC key.

This behaviour is controlled by the following code snippet

$("[name=popup]").dialog({
    position : "center",
    modal : true,
    autoOpen : false,
   //This line disables the ability to dismiss dialogs using ESC             
   closeOnEscape : false
});



Log onto the Application, and select “Help > About View”, open the Query Assistant Applet, or choose any other popup applet, this will initialise the jQuery dialog. Press the ESC button, and at the moment, nothing will happen.

Press F12 on your browser to bring up the built-in debugger, and paste the code below.

        $("[name=popup]").dialog( "option", "closeOnEscape", true );


Now with that same popup applet still open, press ESC, and watch that applet disappear. Any popup applet that is opened in the Application at this point also inherits this behaviour.

The above code will act the basis of our solution, but it only works if a popup has already been opened, so the most appropriate event is the first time a popup applet is displayed. This makes ShowUI a good candidate, as we can detect when a popup is open, and set the dialog option.

For testing purposes you can put the following code the ShowUI handler of any popup renderer.

if (!$( "[name=popup]" ).dialog( "option", "closeOnEscape" ) ){
    $("[name=popup]").dialog( "option", "closeOnEscape", true );
}


The above code detects if the closeOnEscape option of the jQuery dialog is disabled, and proceeds to enable it. It works even if the first popup applet is opened, and has been initialised to false.

The above code only works for a particular applet, and any subsequent popup applets opened from that point onwards, so a better approach is to put the code under the global ShowUI handler, which will enable the feature for any popup that is opened, however we only want to run it once.

To achieve this, we can use the technique below, which re-writes the logic to cut out the if statement after the first time the dialog option is set.

Note: This code is provided for educational purposes only, and should not be used in production environments.
function Global_PreShowUI(){
    //Call the usual ShowUI function
    Global_PreShowUI_Rewrite();

    //Perform popup dialog check
    if (!$( "[name=popup]" ).dialog( "option", "closeOnEscape" ) ){
        $("[name=popup]").dialog( "option", "closeOnEscape", true );
        //Rewrite the current function after the first popup has been detected
        Global_PreShowUI=Global_PreShowUI_Rewrite;
    }
}


function Global_PreShowUI_Rewrite(){
    //Show UI code goes here
}


The line below shows where the application logic is being re-written.

    Global_PreShowUI=Global_PreShowUI_Rewrite;


The subsequent time Global_PreShowUI is fired, it will go straight to the real Global_PreShowUI_Real handler, which means our conditional test is only evaluated once. Neat!

Usability has always been thrown in the too hard basket, and although browser script techniques have been available to improve usability in Siebel HI, it has only been attempted by the brave.

The ESC key is already used in Siebel to undo query, undo record, and dismiss dialogs. Open UI now provides the option for customers to extend this feature to all Siebel popup applets.

Open UI: SiebelJS.Log & The Stack

Introduction

SiebelJS.Log allows the developer to debug the application by writing to the browser console. This has been provided since 8.1.1.9.

Most modern browsers have console.log which performs the same function, except console.log causes an error in IE if the developer toolbar has not already been opened. SiebelJS.Log avoids this problem by first checking if the console object is available, before calling the log method.

SiebelJS.Log is better for this reason.

SiebelJS.Log in 8.1.1.11

In 8.1.1.11 Oracle changed the way SiebelJS.Log works.

SiebelJS.Log no longer supports a string argument, but rather an Error object. This also means all previous log statements from 8.1.1.10 will be ignored silently.

Update: The above behaviour affects the only the 8.1.1.11 sample application. SiebelJS.Log has been redefined in 8.1.1.11 to support an Error object, but passing in a String will still log to the console. Usage
TestPRList.prototype.ShowUI = function(){
    hello_a();
};

function hello_a(){
    hello_b()
};
function hello_b(){
    hello_c()
};
function hello_c(){
    SiebelJS.Log( new Error('Error occurred here')) ;
};


Result


Notice that it produces an error message with a stack trace.

If you don't like the stack trace produced by SiebelJS.Log, you can call SiebelJS.Trace or console.trace directly to produce a stack trace without the error message.

Just substitute SiebeJS.Log with console.trace in the above example. This results in a much cleaner output as can be seen below.



console.trace is supported in Chrome, Firefox, and Opera.

Conclusion

Although there has been no official documentation page on the SiebelJS class and its available methods, it has been used in Oracle Bookshelf alongside usage examples of other methods, and as such, can be considered to be implicitly documented.

For better or for worse SiebelJS.Log has been redefined to be used as an error logger. Open UI customers that need a method for logging, are better off creating a wrapper around console.log, and put it in a client side library (if you haven't already done so).

8.1.1.11 brings many changes, including unspecified changes to the browser API. Customers that are upgrading from 8.1.1.10, will find that customizations don't port over without some rework.

The temptation to use undocumented methods is ever present, because the source code is more readable than the documentation. This serves as a good reminder for us to avoid using undocumented methods, or at least have a good mitigation strategy if you do use them.