0

I have searched the web, youtube, and communities but no solution to this question. I have an app that I am developing using Phonegap Build. I have included the InAppBrowser plugin in my config.xml and works fine with links in the app. The solution or direction I am looking for is a way to include links that are on an external website to open using the InAppBrowser. The links on the external page are dynamic but I am able to add the onClick event. This is what my dynamic link looks like.

<a href="#" onclick="openInAppBrowserBlank(\'' . get_permalink($post->ID) . '\');>Read More</a>

This is one link that I see when I use Firebug to view the html it is generating.

<a onclick="openInAppBrowserBlank('http://website.com/uncategorized/post-one/');" href="#">Read More »</a>

This is the script that I use to load the external page in my app.

<script type="text/javascript">
 function expage() {
   $("#display").html('<object data="http://website.com" style="position: relative; right:0; top:30px; width:100%; height:100%; overflow:auto; overflow-y:hidden; padding:0px;" />');
} 
</script>

This is the DIV that displays the external page.

<div id="display" class="card1" style="position:fixed; top:15px; left:0px; width:100%; height:93%;"></div>

These are scripts attached to my page. Phonegap builds "phonegap.js" into my app.

<script type="text/javascript" src="phonegap.js"></script>
<script type="text/javascript" src="js/index2.js"></script>
<script type="text/javascript">
  app.initialize();
</script>

This is "index2.js"

var ref = null;
function openInAppBrowserBlank(url)
{
    try {
ref = window.open(url,'_blank','location=no'); //encode is needed if you want to send a variable with your link if not you can use ref = window.open(url,'_blank','location=no');
     ref.addEventListener('loadstop', LoadStop);
     ref.addEventListener('exit', Close);
}
catch (err)    
{
    alert(err);
    }
}
function LoadStop(event) {
     if(event.url == "http://website.com/x.php"){
        // alert("fun load stop runs");
         ref.close();
     }    
}
 function Close(event) {
     ref.removeEventListener('loadstop', LoadStop);
     ref.removeEventListener('exit', Close);
}

Has anyone done something like this or can give me direction?

Rob
  • 15
  • 9

2 Answers2

0

I think the problem is that you are loading the external page using an object tag. This has a different browsing context than your current page therefore your openInAppBrowserBlank function and other scripts doesn't exist there.

This is the definition of the object tag

The HTML Embedded Object Element () represents an external resource, which can be treated as an image, a nested browsing context, or a resource to be handled by a plugin.

Read here about browsing context. A different browsing context is used also for iframes and frames inside a frameset.

So the easiest solution is to use an iframe with a seamless attribute like this

<iframe seamless="seamless">

This Boolean attribute indicates that the browser should render the inline frame in a way that makes it appear to be part of the containing document, for example by applying CSS styles that apply to the to the contained document before styles specified in that document, and by opening links in the contained documents in the parent browsing context (unless another setting prevents this).

That way the browsing context of the page inside the iframe will be the same that of your page and your script most likely work.

I use "most likely" on purpose because you need to remember that the nested page was designed assuming it will execute in his own browsing context and you will be running it on another so unexpected behaviour might ocurr.

There are other solutions like making an ajax call and fill the content of any tag, eg a container div with the content retrieved or use an iframe withouth the seamless attribute to load the page and inject your script in it but this are more tricky and will have side effects too so be aware.

In all the solutions you might have colliding styles or scripts so if that's the case go for the iframe without the seamless and inject only the desired functionality.

{Edit}

Doing some research I found an article and some SO post containig examples of how to inject scripts in iframes. These are the links

http://jaspreetchahal.org/how-to-inject-javascript-into-an-iframe/

inject a javascript function into an Iframe

Injecting Javascript to Iframe

These examples work very well when the iframe is referencing a page that does not have CORS restrictions, that is, a request from a different domain. When this is the case you have to use window.postMessage to comunicate between your page and the external page inside the iframe because the api gives very limited access to the window and location objects (imagine the security hazards there).

Check the mozilla docs in the section Cross-origin script API access to see wich functionality is left for you to use.

Community
  • 1
  • 1
devconcept
  • 3,665
  • 1
  • 26
  • 40
  • This makes total sense. I've researched over the weekend and read some articles that cover what you are recommending. This is good to know. I tried using this in a function... console.log(document.getElementById('wp').contentWindow.document.getElementById('my-app').onclick = function() {alert ("Hello World!");}); ...to inject the code into an element inside and iframe. Works great for the parent page but no response in the iframe. Do you think this has to do with the access origin policy? The parent page is native and the page that is loaded into my iframe is hosted on my server. – Rob May 18 '15 at 17:10
  • Are you using ripple to test your app? Request being blocked by cors are easy to spot in chrome, just look in your network tab if your browser is making request to your page using an OPTIONS verb instead a GET is very likely that you are using cors and right there you can look at the response code sent from the server. If not you can use a tool like Fiddler to intercep calls. As for the injecting of code i will edit my answer to suggest some examples of how you do it. – devconcept May 18 '15 at 17:27
  • I didn't think about using Ripple. Mostly I have been building my app using Phonegap Build and testing it on my mobile device to see if anything is happening. However, I see that using Ripple and Chrome to see if my browser is making requests to my page makes much more sense. Thanks for the edited info. Much appreciated. – Rob May 18 '15 at 17:59
  • If you are working directly on a device you can use weinre to print debug information and do some testing http://people.apache.org/~pmuellr/weinre/docs/latest/ . Remember to mark the answer as accepted if it was helpful. – devconcept May 18 '15 at 18:08
0

I learned that the "access origin policy" is the issue. Since the page I am loading is not native and is hosted on a server the phonegap "inappbrower" plugin script can not be injected. Regardless if I use the getElementById method. I've read that there is away around this but unfortunately this is outside of my scope for the time being.

I was able to create another solution by loading in data through an array and styling the elements. I did this by hosting the JS with the arrays on my server and added the "onclick=inappbrowserblank" method to the links.

This worked like a charm but unfortunately is a manual process for now.

Hopefully this helps someone.

Rob
  • 15
  • 9