Exit a Modal Window iframe in APEX
I use Dan McGhan’s Modal Page Plugin extensively. I think it’s fantastic and I can’t imagine not using it on any new project. The Oracle APEX Team must have also recognized it’s usefulness because the functionality is now baked into APEX 5.
It’s standard functionality of the plugin to close the modal window on processing or perhaps on a button click. I’m not going to outline those techniques here as they have been explained in some blog post and within the plugin’s documentation. However, recently I had the need to exit or escape the modal window (without submitting) and branch to a new page outside the modal window.
My use case is that the modal window displays a lot of read-only information to the user. If you have the rights, most users would not, I add an “Edit” button and let you go to the edit page where changes are made. This page is way more complicated (and less user friendly) than the read-only page we’re on. We need this edit button to redirect the browser, not the modal window, to the edit page.
This behavior requires that you exit the iframe.
Busting the iframe
One technique is known as breaking out of an iframe and it works like this. You branch the modal page to your destination page (easily done with a standard button that redirects or a page branch). Then, the destination page will have javascript code in place that will detect if it has been loaded inside an iframe and if so, break out if it. Here’s a pretty nifty one liner (listed with these other useful options):
// escape the iframe if we are inside the modal window
this.top.location !== this.location && (this.top.location = this.location);
Add this code to your “Execute when Page Loads” section of the page. The code basically says: Is the browser address (top.location) different from the iframe address (location)? If that’s true, the right side of the AND is evaluated/executed — the browser address is switched to be the same as the iframe effectively breaking out of the iframe.
The problem with this approach is that you basically have to load a bunch (or most) of your page before you realize you need to break out. At that point you reload the page again. Here’s a demo of how that may look in a demo app. Drill into a row, then press the “Branch Regular” link at the bottom. You’ll see the Landing page come up for a bit inside the iframe and then load again in the full browser. Sometimes it loads fast enough that you don’t notice it, but there will be a double load.
My Recommended Solution
Add some information to the link to trigger the exit of the iframe. After all, not all redirect buttons need to exit an iframe. I decide to add “EXITFRAME” to my request. Then I used this little snippet of code:
(function(){
// Store a reference to the original redirect method.
var originalRedirect = apex.navigation.redirect;
// Define overriding method.
apex.navigation.redirect = function(){
var pWhere = arguments[0];
if ( pWhere.indexOf("EXITFRAME") > 6 ) {
window.top.location = pWhere;
}
else {
// Execute the original method.
originalRedirect.apply( this, arguments );
}
}
})();
Here’s an app for you to see the effects: demo Drill into a row, then you’ll see 3 buttons and a link at the bottom: 1) Custom HTML Button (Explained bellow), 2) “Branch Regular 1” (to see iframe break behavior), 3) “Branch Regular 2” (branch to a page that will not exist the iframe), and 4) “Branch w/Exit Frame” (which will use the JS code that “overloads” the standard apex.navigation.redirect)
The EXITFRAME in the request is pretty harmless to the rendering of the landing page (unless, of course, you need some special request, but if you do you’ll know how to modify the code).
The manual custom method
Here’s another technique I do NOT recommend. Sure, it seems simple and fast enough, but I avoid it because you are hardcoding the link to the page and if you want the button to match your theme you’ll be hardcoding the required HTML. Then, months from now, when I go back to this application to copy paste this solution into a new application I may not be using the same theme any more.
If you add target=”_top” to an anchor link you will also exit the iframe.
<a target="_top" role="button" id="exitIframBtn" class="uButton uHotButton" href="f?p=&APP_ID.:3:&SESSION.::&DEBUG.:::"><span>Custom HTML Button</span></a>
An then, if you require a checksum for the link you’ll need to use apex_util.prepare_url and it just gets messy.
A word about reports
Links in the Classic or Interactive Reports are able to break out of an iframe a lot easier because those are real link (as opposed to javascript) We get access to a “Link Attributes” field. We often use it to specify a class or other information to be added to the anchor tag. To exit the iframe from this link, all you have to do is specify target=”_top” and the link will exit the iframe.
In case you missed the link above. Here’s the full demo
Works as magic