Welcome Salesforce Community

View Latest Videos on YouTube Follow on Twitter

ADF Mobile Custom Javasciprt – iFrame Injection

ADF Mobile Custom Javasciprt – iFrame Injection

The ADF Mobile Framework (ADFMF) provides a range of out of the box components to add within your AMX pages. When the occasion arises when an out of the box component does not directly fulfill your development need – what options are available to extend your application interface?

Recently I was experimenting with ADF Mobile and using it to create a ADF Mobile WebCenter Content iPhone / Android application. I needed a way to show HTML content from an external source based on an attribute in a result set that contained a desired content item ID.

It is possible to include Remote URLs in an ADFMF application, but I wanted to stay within the visual context of my existing application and have a pattern to potentially incorporate external content in a region of a page. I explored and tested a long series of options and settled on refining the following approaches

  1. Backing bean to leverage the CVM JVM within the ADFMF to request the remote HTML and then bind it to a control in my AMX
  2. Using some custom Javascript to extend the AMX interface for what I needed

Since some of the WC Content files could be rather large, I opted for the 2nd to see if a simple iFrame could be added within the AMX – keeping the context of the user interface and rendering the content item within.

Please keep in mind this is my own approach / experience and because ADFMF leverages PhoneGap (a container to allow “hybrid” application development), the end result allowed me to easily add the iFrame into the Document Object Model (DOM). As a general rule, it only makes sense to fall back on manipulating the DOM when native options have been exhausted.

Adding Custom Javascript – invokeContainerJavaScriptFunction
The process is actually fairly straightforward, once the understanding of the abstraction layers between your components and Javascript function are clear. The following diagram shows how the various elements involved in including external Javascript in an ADF Mobile application.

The complete steps for this process are described in Defining the Content Types for an Application Feature.

So… now that we have the ability to add custom Javascript, how do we get our iFrame?

Rendering the iFrame
ADF Mobile applications render various components on a page into HTML markup in which the ID defined in JDeveloper for the given component ends up being the ID rendered. This means that the panelPage component in the following code block will receive an ID of pp1 when rendered for deployment. To be clear, this is subject to change, as developers we cannot control the render engine directly.

Sample AMX Page Code
This AMX code contains the panelPage component, as well as a commandButton that when clicked will invoke a callFramedDocumentJS in a managed bean associated with our application.

  <amx:panelPage id="pp1" inlineStyle="background-color:White;">
    <amx:facet name="header">
      <amx:outputText value="#{pageFlowScope.DemoBean.docName}" id="ot1"/>
    </amx:facet>
    <amx:facet name="primary">
      <amx:commandButton id="cb1" text="Back" action="__back"/>
    </amx:facet>
    <amx:facet name="secondary">
    </amx:facet>
    <amx:commandButton text="View Content" id="cb2"
                       actionListener="#{pageFlowScope.DemoBean.callFramedDocumentJS}"/>
 
    <amx:verbatim id="vb1"/>
  </amx:panelPage>

Method in Managed Bean to Associate with commandButton
This method is contained in a managed bean associated with the mobile application. In our example we have scoped the bean to the pageFlow. Additionally, notice the docURL – that is a variable that is being passed into our custom Javascript function. It is possible to pass a series of parameters in as an array.

    // Call custom Javascript to inject an iFrame
    public void callFramedDocumentJS(ActionEvent actionEvent) {
        AdfmfContainerUtilities.invokeContainerJavaScriptFunction("DocB", "showFramedDocument",
                                                                  new Object[] { "" + docURL + "" });
    }

Javascript Function to Inject iFrame into DOM
The following method will get triggered when the code in the managed bean is invoked by a button click that is using an actionListener referencing callFramedDocumentJS. Notice that we are receiving parameters from the Managed Bean in the form of a variable called “args”, we then grab the first parameter with “args[0]” later in our code to get the docURL in our sample.

(function () {
    if (!window.application)
        window.application = {
        };

    // Custom JS that will add an iFrame into the DOM
    showFramedDocument = function () {
        // Get array of arguments that are passed in from DocBean.java
        var args = arguments;

        // ID of the amx:panelPage
        var target = document.getElementById("pp1");

        // Uncomment the following to see what URL will attempt to be opened
        // alert("Opening : " + args[0] + " ");
        
        // Build iframe object to add into DOM 
        ifrm = document.createElement("IFRAME");
        ifrm.setAttribute("src", args[0]);
        ifrm.setAttribute("background-color", "#ffffff");
        ifrm.style.width = "100%";
        target.appendChild(ifrm);

        return "application.testFunction - passed";
    };
})();

Closing thoughts
You may want to include a second Javascript function to clean up the DOM when someone leaves the current view. Additionally, be aware of the whitelisting of external resources that can be called by your application. Hopefully this approach can help others as needed when special cases arise.

16 comments
slokam
slokam

Hi John

It is a nice article, we tried to do the same steps but when we are opening this in iOS simulator , iframe is opening in a separate safari web browser rather than within our application.

Can you please help us...


Thanks

slokam

Bhummiwat Manphadung
Bhummiwat Manphadung

Hi,

This tutorial is totally useful for me, btw I have some approach to using with this one

Is it possible to showing iframe when AMX page loaded ? as have to have some action with button before

rohantan
rohantan

Hi John,

 

Nice post ! very helpful.

I was trying to navigate to some amx page from javascript but it did not work.

 

what I'm trying to do:

From one amx page I am calling an action, in that action I'm performing some operations and calling the javascript.

From that javascript I want to call another amx page.

 

I tried this way(in javascript):

window.location='menupg.amx';

 

It works fine if I use html page instead of amx. I mean, the javascript navigates to html page but not amx.

Could you please help me in navigating to an amx page from javascript?

 

Regards,

Rohan

sanjpradhan
sanjpradhan

Hi John,

 

Great article as always.If a customer has Oracle WebCenter  could they optionally use Pagelet Producer to inject HTML into the mobile device in a lightweight manner  ?

 

Sanjay

HarshaRamesh
HarshaRamesh

@slokam Make sure that the URL that you are opening has been added to the whitelist in the adfmf-application.xml file

John Brunswick
John Brunswick moderator

Hey Harsha,

Great writeup.  Definitely a good resource for people looking at getting the most from the ADF stack.  Thanks for sharing!

Cheers,
John

John Brunswick
John Brunswick moderator

 @rohantan Apologies for the delay - the holiday distracted me from email for a bit :-)

 

With regard to the AMX page, I have not attempted anything like that, as the AMX page contains functionality that will not be able to be directly used, like HTML, due to the tags that are provided within the framework - http://docs.oracle.com/cd/E35521_01/doc.111230/e24475/amxcontent.htm.

 

To navigate to an AMX page would suggest using the flows within the page navigation - http://docs.oracle.com/cd/E35521_01/doc.111230/e24475/amxcontent.htm#CIHCIJBG.

 

Hope that helps!

John Brunswick
John Brunswick moderator

 @sanjpradhan Thanks Sanjay!

 

Funny that you mention that - I was actually starting to look at Gadgets / Pagelet Producer as additional options.  ADF Mobile allows custom HTML pages to be used in the application as well, so unlike the AMX page which need amx tags, the HTML page could simply use the markup for the Pagelet Product / Gadgets.  Will definitely have to test - would be great for reuse.

 

Cheers,

John

slokam
slokam

Hi harsha

Thank you for your quick reply.

Our URL is dynamic. How can we add dynamic url to admf-application.xml?

Please help.

Thanks

Slokam.

rohantan
rohantan

 @John Brunswick Thanks for the reply John :) and a very happy new year to you !

My application is running using normal taskflow(without using javascript) which you have mentioned.

But what I'm trying to achieve is:

I want to open an AMX page from javascript(js file).

How to do it? Or is there any workaround for this?

 

Regards,

Rohan

John Brunswick
John Brunswick moderator

@slokam What if you tried a global whitelist for testing and work backward from there?  That would help to quickly rule that out as being an issue.

@HarshaRamesh Thanks for jumping in to help as well - much appreciated.

I have not attempted any of the above with the latest release (iOS or ADF Mobile), so it may require adjustment.

Cheers,
John

slokam
slokam

Harsha

I tried adding "http://www.yahoo.com" to whitelist. After adding this to whitelist, safari browser is not opening but iframe does not showing anything. Am I missing anything else?


Thank you

slokam

HarshaRamesh
HarshaRamesh

@slokam That unfortunately cannot be circumvented. Unless you can find a hack in the PhoneGap code.

John Brunswick
John Brunswick moderator

 @rohantan Hey Rohan,

 

I have not personally tried that yet, but it is definitely possible, as the native UI must use JS to navigate within itself (e.g. http://jdevadf.oracle.com/amx/bootstrap.html?file=Gallery/task-flow.xml%23task-flow&featureRoot=./).  Not sure what would happen in the hybrid container on device though.

 

With that being said - the client side JS can call into a "bean", there are a series of methods to work within the bean to manage the navigation, etc.  Have you looked at

http://docs.oracle.com/cd/E35521_01/doc.111230/e24475/phgapfeatures.htm?

 

Hope that helps!

 

Cheers,

John

Trackbacks

  1. [...] For complete details of our custom Javascript that opens the iframe to our content check out our prior post ADF Mobile Custom Javascript – iFrame Injection. [...]