I'm using ionic framework to develop native app. Here, I'm having default header in all the pages. When switching over to second page, I need in-app browser to view the external content.
So, I used window.open
Click Here to view inapp browser
But, I need the header to be constant when I am viewing the content in in-app browser.
Is it possible in ionic framework?
I don't need iframe for this. It is heavy weighted in html.
Updated:
I m having a html file which I m injecting to iframe. like
<div id="header"></div>
<iframe src="serveraddress/index.html"></iframe>
Instead of iframe, is there anything which remains the header constant? If I use in-app browser, my header was invisible.
EDIT
I had disregarded the in-app browser element in your question. Here is an update, specifically for in-app browser.
DISCLAIMER: none of the code provided below has been tested; however, this answer gives you guidelines to implement your solution.
Instead of iframe, is there anything which remains the header constant? If I use in-app browser, my header was invisible.(...)Header needs to be constant when I'm viewing external website content.
When you use in-app browser:
Click Here to view inapp browser
it opens a popup which displays the requested URL.
You would like to have your own header displayed in the in-app browser window. I see two ways to do this:
A) You could customise the webpage you want to display in your in-app browser beforehand, and store it on your server.
The customised webpage could have included some third party HTML, using one of the 4 techniques mentioned below. See techniques 1, 2a, 2b and 2c.
Say you store a customised webpage on your server which is like so:
<div id="header"></div>
<div id="main"></div>
The page is stored on your own server, at url: www.myserver.com
If you make your in-call like: window.open('http://www.myserver.com',...) you would display your customised page, with your own headers.
B) You could fetch the third party webpage with in-app browser, keep it hidden, modify it, then display it
Please read this Cordova doc page.
To open a window and keep it hidden:
var ref = window.open(url, target,'hidden=yes');
To execute a script when the hidden in-app window is ready:
var iabRef = null;
function insertMyHeader() {
iabRef.executeScript({
code: "var b=document.querySelector('body'); var a=document.createElement('div');document.createTextNode('my own header!'); a.appendChild(newContent);b.parentNode.insertBefore(a,b);"
}, function() {
alert("header successfully added");
});
}
function iabClose(event) {
iabRef.removeEventListener('loadstop', replaceHeaderImage);
iabRef.removeEventListener('exit', iabClose);
}
function onDeviceReady() {
iabRef = window.open('http://apache.org', '_blank', 'location=yes');
iabRef.addEventListener('loadstop', insertMyHeader);
iabRef.addEventListener('exit', iabClose);
}
Now you can show the in-app window: ref.show();
APPENDIX: 4 techniques to use third-party content in your apps:
If the third-party website provides an API (complex solution, but entirable configurable)
e.g. Bing Search API
Some websites provide an API, which responds with bare information, usually returned in the form of a JSON string.
You can use a JavaScript templator like Mustache to create your HTML from the JSON response you got, either server-side or client side. Then you open your popup:
<div id="header"></div>
<div id="myTemplatedHTML"></div>
If you go for the client-side option, I suggest you read open window in javascript with html inserted
2a. If the third-party website does not provide an API: cross-site javascript call
Please read this thread: Loading cross domain html page with jQuery AJAX
You would have in your HTML:
<div id="header"></div>
<div id="myLoadedHTML"></div>
And the myLoadedHTML would be filled with HTML fetched from the third-party website.
I recommend to use a tool like YQL to fetch the HTML. YQL will let you make complex queries to fetch just the bits of HTML you need.
2b. If the third-party website does not provide an API: embed
Please check this thread: alternatives to iframes with html5
It reads that: if you want to display cross domain HTML contents (styled with CSS and made interactive with javascript) iframe stays as a good way to do
It also mentions the embed tag:
<embed src="http://www.somesite.com" width=200 height=200 /></embed>
In your case, you could probably achieve your goal with something like:
<div id="header"></div>
<embed src="http://www.somesite.com" width=200 height=200 /></embed>
2c. If the third-party website does not provide an API: iframe
Alternatively, should you want to display a third-party website in an iframe, and then modify the display with your own content, I suggest you check this StackOverflow thread: Cannot modify content of iframe, what is wrong?
In your particular case, say you named your iframe myIframe:
<iframe src="serveraddress/index.html" id="myIframe"></iframe>
You could then achieve your goal with something like this:
$(document).ready(function(){
$('#myIframe').ready(function(){
$(this).contents().find('body').before('<div id="header"></div>');
});
});
I'm afraid the inAppBrowser Plugin does not support such behavior. It's not listed on their docs here
https://github.com/apache/cordova-plugin-inappbrowser
You can edit the plugin native code for iOS and Android, if have such knowledge.
If you don't want to get into native development (probably), then iframe is the way to go. But you won't be able to edit the contents of the iframe because it will be in a different domain from your application. All you can do is position and size the iframe so that it fills the page right below you application header.
I know it's been a while – just in case somebody is struggling with the same issues: There's a themeable version of cordova's InAppBrowser which is working like a charm, we used it recently in a project.
https://github.com/initialxy/cordova-plugin-themeablebrowser
Related
Ive tried using the js load function but as the external site does not allow CORS requests, my original GET request gets blocked.
<div id="test"></div>
<script>
$(document).ready(function () {
$("#test").load("https://mywebsite.com");
});
</script>
So it seems that my only approach is to use iframes?! Is there a way to only crawl a specific div with iframes? I dont want to display the whole website.
EDIT: Since I am using Django I was able to crawl the website with python in a view and then push the crawled and cleaned up code snippet in the html template. Nevertheless to answer my question -> There is no correct way of doing it as long as the website you are trying to access is blocking the content.
Work with the owner of the site you want to take content from.
They can set you up with an API. That avoids having to use hackey methods or risking copyright-related legal trouble.
Scenario:
I've an application made in angularJS and ionic for cordova 3.5
This application loads trough an iframe a web to make some things with a step by step form. This web is on other site.
The code for the html is:
<div id="IframeContainer">
<iframe src="URL" style="width:100%;height:90%" onLoad="checkforclose(this);"></iframe>
</div>
This step-by-step form returns a result that the cordova application needs to know what happens in the form. It can return a json, a text/plain or even an HTML that auto-post to another site (This is linked with this non-answered question: Post and redirect FROM Web Api)
Said this, in my cordova application I've a javascript function in order to close the iframe and take over again the control of my application, detecting if the url contains the word "close". This is the code:
<script type="text/javascript">
function checkforclose(pageURL) {
var urlFrame = pageURL.contentWindow.location;
if (urlFrame.href.indexOf('close') > -1) {
window.location = "#/employees/";
}
}
</script>
Question:
Trying avoid CORS (So I think I can't read the iframe content on load, or I'm wrong?),
without using jQuery (AngularJS is welcome, plain javascript even more)
Taking over the control again to the application
How can I get the data returned by the step-by-step external form?
UPDATE 1:
I tried coding a "onload" reading (CORS errors), and posting to a cordova-html page, but without any respectable result.
A possible solution is Web messaging or cross-document messaging. Here's a blog post where someone used this method to gain access to a mobile device's camera from an external page loaded in an iframe. Although this person had the opposite goal (get data from Cordova to page loaded in iframe), they were able to accomplish cross domain communication between a page in an iframe and Cordova; which is what I believe you are trying to do.
I have the following HTML markup (don't ask....)
- document //main site
- <iframe> //my site
- <iframe> //site within my site
- <frame>
- <a onclick="JavaScript:parent.parent.location.href='http://bla.com;return false;'">
Basically, main site is calling my site in an iframe. I, in turn, also have an iframe on my site where I'm calling 3rd site. The third site has a frameset with a frame in it that has a link. When clicking on this link, it has to change the url of my site. My site and my child site are on the same domain. When I'm running my site as "stand-alone" (not in iframe) the above code works fine in all browsers.
Once I open my site in an iframe of the main site, it looks like the above code is trying to change the source of the main site. In FireFox I get a console message "Access to property denied". In IE it opens up a new window with my site not in the main site anymore.
What is the correct JavaScript to change the #src attribute on my site when I'm within an iframe?
You are banging your head against the wall that is the same origin policy here. This is XSS country and strictly forbidden, no way around it, unless both domains agree to talk together.
You can read more about cross domain communication using iframes, but again, unless the different domain agree to talk together, you are out of luck.
Although this might seem frustrating, be glad of this rule next time you use homebanking ;)
Can you try something like this
<document> //main site
<iframe id="my_iframe"> //your site
<iframe> //site within your site
<frame>
<a onclick="JavaScript:Top.document.getElementById('my_iframe').location.href='http://bla.com;return false;'">
Top refers to the main window, and then getElementById('my_iframe') will give you your iframe element.
I believe that you're trying to do communication between different pages.
You may take a look this API: HTML5 Cross Document Messaging
Basically, if you want to tell the parent iframe to navigate to a certain url, you can do this:
In the site within my site html:
// onclick of your anchor, post message (an event) with an expected origin
window.postMessage("http://bla.com", "www.sitewithinmysite.com");
In my site html:
// listen to the event "message"
window.addEventListener("message", messageHandler, true);
function messageHandler(e) {
// only recognize message from this origin
if (e.origin === "www.sitewithinmysite.com") {
// then you can navigate your page with the link passed in
window.location = e.data;
}
}
You might want to have the pages communicate using AJAX. Have the site that needs to change its URL listen by long polling to to a node.js server.
I am trying to integrate with the FireShot API to given a URL, grab HTML of another web page into a div then take a screenshot of it.
Some things I will need to do after getting the HTML
grab <link> & <script> from <head>
grab <body> into <div>
But 1st, it seems when I try to do a
$.get("http://google.com", function(data) { ... });
I get a 200 in firebug colored red. I think it has to do with sites not allowing you to grab their page with JS? Then is opening a window the best I can do? But how might I control the other page with jQuery or call fsapi on that page?
UPDATE
I tried to do something like below to do something when the new window is ready, but FireBug says "Permission denied to access property 'document'"
w = window.open($url.val());
setTimeout(function() { // if I dont do this, I always get about:blank, is there a better way around this?
$(w.document).ready(function() {
console.log(w.document.body);
});
}, 1000);
I believe the cross-site security setup within Javascript is basically blocking this. You'd likely have to proxy the content through your own domain.
There are a couple other options I think for break the cross-site security constraints, but I'm not sure I'd promote them.
If the "another page" locates within the same domain of your hosting page, yes, you can. Please refer to jQuery's $().load() API.
Otherwise, you're disallowed to do so by the browser's Cross-Site Security Policy. At this moment, you can choose to use iFrame instead of DIV.
Some jQuery plugins, e.g. thickbox provides ability to load pages to appropriate container automatically.
Unless I am correct, I do not believe you can AJAX a page cross domain (e.g. from domain1.com to domain2.com). To get around this, you can have a PHP "proxy" script that does the "getting" of the page and then pass it to JS.
For example, in JS you would get() http://mydomain.com/get/?domain=http://google.com and then do what you need to do!
I have a html page on my localhost - get_description.html.
The snippet below is part of the code:
<input type="text" id="url"/>
<button id="get_description_button">Get description</button>
<iframe id="description_container" src="#"/>
When the button is clicked the src of the iframe is set to the url entered in the textbox. The pages fetched this way are very big with lots of linked files. What I am interested in the page is a block of text contained in a <div id="description"> element.
Is there a way to mitigate downloading of resources linked in the page that loads into the iframe?
I don't want to use curl because the data is only available to logged in users and the steps to take with curl to get the content is too complicated. The iframe is simple as I use this on a box which sends the right cookies to identify the request as coming from a logged in user, but the problem is that it is very wasteful to get nearly 1 MB of data to keep 1 KB of it and throw out the rest.
Edit
If the proposed method just works in Firefox it is fine, so I added Firefox tag. Also, it is possible that the answer actually is from the realm of Firefox add-on techniques, so I added that tag as well.
The problem is not that I cannot get at what I'm looking for, rather, the problem is the easy iframe method is wasteful.
I know that Firefox does allow loading only the text of a page. If you open a page and press Ctrl+U you are taken to 'view page source' window, There links behave as normal and are clickable, if you click on a link in source view, the source of the new page is loaded into the view source window, without the linked resources being downloaded, exactly what I'm trying to get. But I don't know how to access this behaviour.
Another example is the Adblock add-on. It somehow kills elements before they get loaded. With plain Javascript this is not possible. Because it only is triggered too late to intervene in good time.
The Same Origin Policy forbids any web page to access contents of any other web page in a different domain so basically you cannot do that.
However it seems that with some browsers it is allowed to access web pages content if you are trying to access it from a local web page which seems to be your case.
Safari, IE 6/7/8 are browser that allow a local web page to do so via XMLHttpRequest (source: Google Browser Security Handbook) so you may want to choose to use one of those browsers to do what you need (note that future versions of those browsers may not allow to do so anymore).
A part from this solution I only see two possibities:
If the web pages you need to fetch content from are somehow controlled by you, you can create a simpler interface to let other web pages to get the content you need (for example allowing JSONP requests).
If the web pages you need to fetch content from are not controlled by you the only solution I see is to fetch content server side logging in from the server directly (I know that you don't want to do so, but I don't see any other possibility if the previous I mentioned are not practicable)
Hope it helps.
Actually I've seen Cross Domain jQuery .load request before, here: http://james.padolsey.com/javascript/cross-domain-requests-with-jquery/
The author claims that codes like these found on that page
$('#container').load('http://google.com'); // SERIOUSLY!
$.ajax({
url: 'http://news.bbc.co.uk',
type: 'GET',
success: function(res) {
var headline = $(res.responseText).find('a.tsh').text();
alert(headline);
}
});
// Works with $.get too!
would work. (The BBC code might not work because of the recent redesign, but you get the idea)
Apparently it is using YQL wrapped into a jQuery plugin to do the trick. Now I cannot say I fully understand what he is doing there but it appears to work, and fits the bill. Once you load the data I suppose it is a simple matter of filtering out the data that you need.
If you prefer something that works at the browser level, may I suggest Mozilla's Jetpack framework for lightweight extensions. I've not yet read the documentations in its entirety but it should contain the APIs needed for this to work.
There are various ways to go about this in AJAX, I'm going to show the jQuery way for brevity as one option, though you could do this in vanilla JavaScript as well.
Instead of an <iframe> you can just use a container, let's say a <div> like this:
<div id="description_container"></div>
Then to load it:
$(function() {
$("#get_description_button").click(function() {
$("#description_container").load($("input").val() + " #description");
});
});
This uses the .load() method which takes a string in this format: .load("url selector"), then takes that element in the page and places it's content inside the container you're loading, in this case #description_container.
This is just the jQuery route, mainly to illustrate that yes, you can do what you want, but you don't have to do it exactly like this, just showing the concept is getting what you want from an AJAX request, rather than in an <iframe>.
Your description sounds like you are fetching pages from the same domain (you said that you need to be logged in and have session credentials) so have you tried to use async request via XMLHttpRequest? It might complain if the html on a page is particularly messed up but you chould still be able to get raw text via .responseText and extract what you need with a regex.