ADF Mobile Custom Javasciprt – iFrame Injection

6
15 Flares 15 Flares ×

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.

  • Post Filed Under
Post comment as twitter logo facebook logo
Sort: Newest | Oldest
rohantan 5 pts

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

John Brunswick 8 pts 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!

rohantan 5 pts

 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 8 pts 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

sanjpradhan 5 pts

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

John Brunswick 8 pts 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