I'm looking for a light weight method for client-side includes of HTML files. In particular, I want to enable client-side includes of publication pages of researchr.org, on third party web pages. For example, I'd like to export a page like
http://researchr.org/profile/eelcovisser/publications
(probably just the publications box of that page.)
Using an iframe it is possible to include HTML pages:
<iframe class="foo" style="height: 50em;" width="100%" frameborder="0"
src="http://researchr.org/profile/eelcovisser/publications">
</iframe>
However, iframes require specification of a fixed height, while the pages I'm exporting don't have a fixed height. The result has an ugly scrollbar:
http://swerl.tudelft.nl/bin/view/EelcoVisser/PublicationsResearchr
I found one reference to a method that appears to be appealing
http://www.webdeveloper.com/forum/archive/index.php/t-26436.html
It uses an iframe to import the html, and then a javascript call from the included document to a function defined in the including document, which places the contents of the body of the included file in a div of the including file. This does not work in my scenario, probably due to the same origin policy for javascript, i.e. the including and included page are not from the same domain (which is the whole point).
Any ideas for solving this? Which could be either:
a CSS trick to make the height of the iframe flexible
a javascript technique to lift the contents of the iframe to a div in the including page
some other approach I've overlooked
Requirement: the code to include on should be minimal.
No. The same-origin policy prevents you from doing any of that stuff (and rightly). You will have to go server-side, have a script on your server access that page and copy its contents into your own page (prefeably at build-time/in the background; you could do it at access-time or via AJAX but that would involve a lot of scraping traffic between your server and theirs, which may not be appreciated.
Or just put up with the scrollbar or make the iframe very tall.
As far as I know there is no CSS trick, the only way is to query the iFrame's document.documentElement.offsetHeight or scrollHeight, depending on which is higher, take that value and apply it on the iframe's css height ( add the + 'px' ).
try this ajax with cross domain capability
Why don't you use AJAX?
Try this:
<div id="content"></div>
<script type="text/javascript">
function AJAXObj () {
var obj = null;
if (window.XMLHttpRequest) {
obj = new XMLHttpRequest();
} else if (window.ActiveXObject) {
obj = new ActiveXObject("Microsoft.XMLHTTP");
}
return obj;
}
var retriever = new AJAXObj();
function getContent(url)
{
if (retriever != null) {
retriever.open('GET', url, true);
retriever.onreadystatechange = function() {
if (retriever.readyState == 4) {
document.getElementsById('content').innerHTML(retriever.responseText);
}
}
retriever.send(null);
}
}
getContent('http://researchr.org/profile/eelcovisser/publications');
</script>
And then, you can parse the received page content with JS with regular expressions, extracting whatever content you want from that page.
Edit:
Sorry, I guess I missed the fact that it's a different domain. But as ceejayoz said, you could use a proxy for that.
If you're using jQuery, you can use the load method to retrieve a page via AJAX, optionally scrape content from it, and inject it into an existing element. The only problem is that it requires JavaScript.
Related
Is it possible to change styles of a div that resides inside an iframe on the page using CSS only?
You need JavaScript. It is the same as doing it in the parent page, except you must prefix your JavaScript command with the name of the iframe.
Remember, the same origin policy applies, so you can only do this to an iframe element which is coming from your own server.
I use the Prototype framework to make it easier:
frame1.$('mydiv').style.border = '1px solid #000000'
or
frame1.$('mydiv').addClassName('withborder')
In short no.
You can not apply CSS to HTML that is loaded in an iframe, unless you have control over the page loaded in the iframe due to cross-domain resource restrictions.
Yes. Take a look at this other thread for details:
How to apply CSS to iframe?
const cssLink = document.createElement("link");
cssLink.href = "style.css";
cssLink.rel = "stylesheet";
cssLink.type = "text/css";
frames['frame1'].contentWindow.document.body.appendChild(cssLink);
// ^frame1 is the #id of the iframe: <iframe id="frame1">
You can retrieve the contents of an iframe first and then use jQuery selectors against them as usual.
$("#iframe-id").contents().find("img").attr("style","width:100%;height:100%")
$("#iframe-id").contents().find("img").addClass("fancy-zoom")
$("#iframe-id").contents().find("img").onclick(function(){ zoomit($(this)); });
Good Luck!
The quick answer is: No, sorry.
It's not possible using just CSS. You basically need to have control over the iframe content in order to style it. There are methods using javascript or your web language of choice (which I've read a little about, but am not to familiar with myself) to insert some needed styles dynamically, but you would need direct control over the iframe content, which it sounds like you do not have.
Use Jquery and wait till the source is loaded,
This is how I have achieved(Used angular interval, you can use javascript setInterval method):
var addCssToIframe = function() {
if ($('#myIframe').contents().find("head") != undefined) {
$('#myIframe')
.contents()
.find("head")
.append(
'<link rel="stylesheet" href="app/css/iframe.css" type="text/css" />');
$interval.cancel(addCssInterval);
}
};
var addCssInterval = $interval(addCssToIframe, 500, 0, false);
Combining the different solutions, this is what worked for me.
$(document).ready(function () {
$('iframe').on('load', function() {
$("iframe").contents().find("#back-link").css("display", "none");
});
});
Apparently it can be done via jQuery:
$('iframe').load( function() {
$('iframe').contents().find("head")
.append($("<style type='text/css'> .my-class{display:none;} </style>"));
});
https://stackoverflow.com/a/13959836/1625795
probably not the way you are thinking. the iframe would have to <link> in the css file too. AND you can't do it even with javascript if it's on a different domain.
Not possible from client side . A javascript error will be raised "Error: Permission denied to access property "document"" since the Iframe is not part of your domaine.
The only solution is to fetch the page from the server side code and change the needed CSS.
A sort of hack-ish way of doing things is like Eugene said. I ended up following his code and linking to my custom Css for the page. The problem for me was that, With a twitter timeline you have to do some sidestepping of twitter to override their code a smidgen. Now we have a rolling timeline with our css to it, I.E. Larger font, proper line height and making the scrollbar hidden for heights larger than their limits.
var c = document.createElement('link');
setTimeout(frames[0].document.body.appendChild(c),500); // Mileage varies by connection. Bump 500 a bit higher if necessary
Just add this and all works well:
<meta name="viewport" content="width=device-width, initial-scale=1.0, maximum-scale=1.0, user-scalable=0">
If the iframe comes from another server, you will have CORS ERRORS like:
Uncaught DOMException: Blocked a frame with origin "https://your-site.com" from accessing a cross-origin frame.
Only in the case you have control of both pages, you can use https://developer.mozilla.org/en-US/docs/Web/API/Window/postMessage to safely send messages like this:
On you main site(one that loads the iframe):
const iframe = document.querySelector('#frame-id');
iframe.contentWindow.postMessage(/*any variable or object here*/, 'https://iframe-site.example.com');
on the iframe site:
// Called sometime after postMessage is called
window.addEventListener("message", (event) => {
// Do we trust the sender of this message?
if (event.origin !== "http://your-main-site.com")
return;
...
...
});
Yes, it's possible although cumbersome. You would need to print/echo the HTML of the page into the body of your page then apply a CSS rule change function. Using the same examples given above, you would essentially be using a parsing method of finding the divs in the page, and then applying the CSS to it and then reprinting/echoing it out to the end user. I don't need this so I don't want to code that function into every item in the CSS of another webpage just to aphtply.
References:
Printing content of IFRAME
Accessing and printing HTML source code using PHP or JavaScript
http://www.w3schools.com/js/js_htmldom_html.asp
http://www.w3schools.com/js/js_htmldom_css.asp
I'm working on an application which supports both client and server-side rendering using Facebook's React JS framework.
I need to render an iframe, which has some html inside of it. The HTML is created using a script that I have access to.
However, I want the inner content to be rendered on the server, so that the HTML shows up in search engines. The problem is that for the inner content to be created, it normally needs to wait for the iframe to 'load', which does not happen on the server.
How can I do this?
Here's what I tried, which doesn't work:
render: function() {
return (
<div>
<iframe
ref="myIframe">
</iframe>
</div>
);
},
componentDidMount : function() {
var iFrameNode = this.refs.myIframe,
frameDoc = iFrameNode.contentWindow.document;
frameDoc.write('<html><body style="margin:0px;"><div><script type="text/javascript" src="..."></script></div> ... more html');
}
Note that I'm adding the content on componentDidMount because otherwise it gets 'erased' when the iframe loads.
A good way to do it is to use data URI scheme. It allows inserting html content to an iframe via the src attribute.
Currently supported on all browsers except IE (partial support - no html option) - caniuse.
This will allow google search engine to read the content of the iframe on the server side.
So your code should be -
render: function() {
var frameSrc = browser.ie ? '' : 'data:text/html,<html><body style="margin:0px;">...more html">'
return (
<div>
<iframe
ref="myIframe"
src="{frameSrc}"
</iframe>
</div>
);
},
componentDidMount : function() {
if (browser.ie) { //some browser detection library/code
var iFrameNode = this.refs.myIframe,
frameDoc = iFrameNode.contentWindow.document;
frameDoc.write('<html><body style="margin:0px;"><div><script type="text/javascript" src="..."></script></div> ... more html');
}
}
IFrames are sometimes used to display content on web pages. Content
displayed via iFrames may not be indexed and available to appear in
Google's search results. We recommend that you avoid the use of
iFrames to display content. If you do include iFrames, make sure to
provide additional text-based links to the content they display, so
that Googlebot can crawl and index this content.
- Google Webmaster Guidelines
So from a SEO standpoint, you either need to stop using iframes here or accept that it won't be indexed.
Clever tricks like putting it in the html, and then switching it to an iframe won't help because Googlebot uses JavaScript... unless you do useragent sniffing to send empty JavaScript files, but I don't recommend that.
The direct answer is to use __dangerouslySetInnerHTML if !this.state.x, and in componentDidMount setTimeout(() => this.setState({x: true}), 0), and inject the html into the iframe in componentDidUpdate.
There is a React component to render iframes: https://github.com/svenanders/react-iframe
You can get it with npm install react-iframe, then use it like this in your React code:
import React from 'react';
import Iframe from 'react-iframe';
...
// In your render function:
<Iframe url="whatever.html" />
Unfortunately for me, I would actually prefer to render my server-generated HTML into a <div> rather than an actual <iframe>...
I'm trying to create a login widget in an iframe that can be used on a clients website. This iframe will be using jQuery, but I first wont to be able to check if the parent document has jQuery loaded, if not, load it.
I've tried several different techniques but none seem to wont to work, or decide to load the jQuery library twice.
Any help would be greatly appreciated.
This code block is within the page loaded inside the iframe, which refuses to co-operate.
<script>
var jQOutput = false;
function initjQuery() {
if (typeof(jQuery) == 'undefined'){
if (!jQOutput){
jQOutput = true;
var jScript = document.createElement('script');
jScript.setAttribute("type", "text/javascript");
jScript.setAttribute("src", "js/libs/jquery/jquery-min.js");
}
setTimeout("initjQuery()", 50);
} else {
$(function() {
$("#email").css({"background":"red"});
//visual aid to see if jQuery is loaded.
});
}
}
</script>
I just want to check and see if the parent to the iframe has loaded jQuery, and if not, load it myself, as I'll be using it to perform several tasks needed to complete the login proceedure.
Entented comment:
I dont think what you want to archive is posible because of same origin policy (Cross domain access via JavaScript) - look it op on Google... http://google.com/search?q=same+origin+policy
If you on the other hand dont violate the same origin policy you can archive what you want using something like this:
var parent = window.parent; // This refers to parent's window object
if ( parent && parent.jQuery ) { // Check to see if parent and parent.jQuery is truly
window.jQuery = parent.jQuery;
window.$ = parent.jQuery;
}
else {
// load jQuery here
}
The JavaScript code of your widget has to be divided into two parts. One of them would be loaded on a client's site. It would have permissions to access the DOM of the site: load jQuery if needed, create an iframe, etc. (Be especially careful with global variables there! Try not to use them at all since they can conflict with the code of the site.) Note that this part wouldn't have access to the DOM of the iframe. That's why you need the second part, which would be loaded inside of the iframe. You can use cross-domain techniques for the parts to exchange messages with each other. I'd advise you to check out the easyXDM library.
I have a doubt. I am having an obfuscated html i want to load that in an iframe component. I want to unobfuscate that before loading it in the iframe component. Is it possible? Is there any javascript tool like that?
Any ideas?
Added a link.
http://colddata.com/developers/online_tools/obfuscator.shtml#obfuscator_view
Original Code:
obfuscated Code:
<script type='text/javascript'>
<!--
var s="=iunm?=cpez?=ejw!dmbtt>#b#?=0ejw?=0cpez?=0iunm?";
m=""; for (i=0; i<s.length; i++) { if(s.charCodeAt(i) == 28){ m+= '&';} else if (s.charCodeAt(i) == 23) { m+= '!';} else { m+=String.fromCharCode(s.charCodeAt(i)-1); }}document.write(m);//-->
</script>
So finally i will be having a file like this but when i am about to load in the iframe component i want to see the real code.
The reason why i want use the obfuscated code is because i will be keeping some static html's in an android device and load those html's since i am keeping it in the device i want to obfuscate. Initially i though of encrypting. But this will cause performance impact.
To load HTML in an iframe with jQuery:
var html = '<div>Your HTML</div>';
$("iframe").contents().find("body").html(html);
The iframe's domain and its parent's must match though.
As for the obfuscation thing, don't do that, if you can un-obfuscate it, everybody can as well.
If you are obfuscating just for the purpose of preventing people from searching the OS quickly for the content, e.g. to hide solutions in a simple game, this would be acceptable on modern devices:
var htmlString = 'this is a test', base64EncodedString = '';
base64EncodedString = window.bToA( htmlString );
You then just need to use the following to reverse:
htmlString = window.aToB( base64EncodedString );
You can then just use Pioul's method for placing it in the iframe.
However as people have stated, obfuscation for other reasons - i.e. proper security protection - is rather pointless, as with a bit of knowledge of your app coders could easily reverse whatever you do (especially as everything involved in the obfuscation is working client-side).
I have a page that loads an external HTML page into an iFrame. There are two problems I am facing with this:
The iFrame is always a fixed height, but I want it to expand
vertically depending on the height of the content.
The content inside the iFrame can not inherit the CSS styles
attached to the HTML page that contains it. The HTML inside the
iFrame has to have it's own link or separate style sheet.
I could be wrong about either of those points, so if I am, please let me know and then I will continue to use the iFrame.
Otherwise, is there a simple Javascript call that can load an external HTML file into a DIV?
Just to be clear, since it seems some people have misunderstood me:
I am asking how to replace an iframe with a DIV and Javascript in order to get the functionality I mention above. I am not looking for ways to make iFrames behave differently.
(I thought this would be fairly common, but most of the questions and information I've found in this site and on the web seems to be situation specific and asks for additional functionality that I don't need and complicates the issue. However, if I've missed something and this is a duplicate, I wouldn't be offended if this got closed.)
You can make an ajax call to fetch your html page and add it to the div. For example using JQuery:
$.get('yourPage.html', function(data) {
$('#yourDiv').html(data);
});
Read more at: http://api.jquery.com/jQuery.get/
I actually wrote up an answer to a different question, that seems to apply here: https://stackoverflow.com/a/10012302/166661
You've got a server that will return to you information -- you could place this information in an IFRAME... or you can call a JavaScript function to retrieve that information and display it in a location (DIV) you set aside on your page.
Here is a sample HTML page that will retrieve information from the server using AJAX
<html>
<head>
<script type="text/javascript">
function getAreaInfo(id)
{
var infoBox = document.getElementById("infoBox");
if (infoBox == null) return true;
var xhr = new XMLHttpRequest();
xhr.onreadystatechange = function() {
if (xhr.readyState != 4) return;
if (xhr.status != 200) alert(xhr.status);
infoBox.innerHTML = xhr.responseText;
};
xhr.open("GET", "info.php?id=" + id, true);
xhr.send(null);
return false;
}
</script>
<style type="text/css">
#infoBox {
border:1px solid #777;
height: 400px;
width: 400px;
}
</style>
</head>
<body onload="">
<p>AJAX Test</p>
<p>Click a link...
Area One
Area Two
Area Three
</p>
<p>Here is where the information will go.</p>
<div id="infoBox"> </div>
</body>
</html>
And here is the info.php that returns the information back to the HTML page:
<?php
$id = $_GET["id"];
echo "You asked for information about area #{$id}. A real application would look something up in a database and format that information using XML or JSON.";
?>
Hope this helps!
#mydiv {
all: initial; /* blocking inheritance for all properties */
}
from How To Isolate a div from public CSS styles?
This solution saved my day.
Use a jQuery plugin to resize the iframe dynamically.
You can't restyle content inside a iframe. What are you planning on using the iframe for? There are often better ways to solve things.
I am asking how to replace an iframe with a DIV and Javascript in order to get the functionality I mention above. I am not looking for ways to make iFrames behave differently.
If you want the functionality mentioned you don't have to replace the iframe. The functionality 2 is easier with an iframe. As for functionality 1, you have two choices:
Put your iframe in a DIV and play with css rules like position absolute and relative plus height at 100%
Add a javascript function to handle the resize event of the window object to resize the iframe