Using CSS to affect div style inside iframe - css

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

Related

iframe cross-domain access with JavaScript

I have a simple HTML page with an iframe. I set its src to another HTML
file and I can change the style of any chosen element at will using code
like this (a basic example):
function elementStyle()
{
var iFrame = document.getElementById( "iFrame" );
var element = iFrame.contentWindow.document.getElementsByTagName(
"table" )[0];
element.style.color = "#ff0000";
}
However the src of the iframe must be an external URL and cross-domain
restriction prevents me from accessing its elements. I have no control
over its content so I can't use postMessage() because I can't receive
any message posted.
Any ideas of a way to get round this?
Note: it must work for anyone with any browser so musn't use any special
methods (like jQuery, CORS etc).
Thanks

How to refresh an iframe not using javascript?

I have an iframe which I would like to refresh every fifteen seconds, but I'm not sure how to do this or if it is even possible. If it is, how would I go about doing this without the use of JavaScript. If JavaScript is necessary then please post how I would do it in JavaScript. Thank you.
You might be able to achieve this using a meta tag, inside the HEAD element of the HTML file being included inside the iframe:
<meta http-equiv="refresh" content="5" />
This will refresh the page every 5 seconds. See the Wikipedia entry.
However, using JavaScript, this is the way to go:
function reloadIframe() {
var iframe = document.getElementById('my-iframe');
iframe.src = "http://some/url/";
setTimeout("reloadIframe()", 5000);
}
window.onload = reloadIframe;
This will reload the iframe with ID my-iframe every five seconds, by pointing it to http://some/url.

How to change img src on document ready before browser downloads images?

On my page I have some images on thisdomain.com/images. on document.ready(), I change the src attribute of images to thatdomain.com/images. Firebug's Net tab shows me that images are downloaded from both thisdomain.com and thatdomain.com. How can I prevent the browser from downloading images from thisdomain.com?
$(document).ready(function(){
$("img").each(function() {
var $img = $(this);
var src = $img.attr("src");
$img.attr("src", src.replace(/thisdomain.com.com\/images/i, "thatdomain.com\/images"));
});
});
EDIT: ASP.NET server-side override of Render() using code "in front" i.e., <script runat="server"> I just added this to the aspx page without recompiling code-behind. It's a bit hack-ish but it works.
<script runat="server">
static Regex rgx = new Regex(#"thisdomain.com/images", RegexOptions.Compiled | RegexOptions.IgnoreCase);
protected override void Render(System.Web.UI.HtmlTextWriter writer)
{
using (HtmlTextWriter htmlwriter = new HtmlTextWriter(new System.IO.StringWriter()))
{
base.Render(htmlwriter);
string html = htmlwriter.InnerWriter.ToString();
string newHtml = rgx.Replace(html, "thatdomain.com/images");
writer.Write(newHtml.Trim());
}
}
</script>
This sounds like something that is impossible to achieve reliably, because images will start to load asynchronously as soon as a src has been specified.
I can't think of a workaround. The <base> tag would allow for some kind of "mass redirection" but the URIs would have to be relative ones for that to work.
I'm sure you have your reasons for outputting thisdomain.com in the first place, but I'm pretty sure you'll have to change your code so thatdomain.com gets output instead (or no src gets specified at all so you can add them using jQuery) if you want a 100% watertight solution.
This ain't going to work in the client side. Your best bet is a server side solution. Have the server side script (PHP? JSP? ASP? etc) to read the to-be-included HTML source and replace the src's accordingly with help of a decent DOM parser before it get emitted to the client side.
I don't that is possible at all. To use jQuery functions, the jQuery library needs to be downloaded, which probably means the browser already started downloading other assets, such as images.
You can't be completely sure to prevent downloading by changing the URL after the element has been parsed. The closest possible that you can get is by changing it immediately after the element:
<img id="something" src="http://www.thisdomain.com/images/hello.gif" />
<script type="text/javascript">
var $img = $('#something');
$img.attr("src", $img.attr("src").replace(/thisdomain.com\/images/i, "thatdomain.com\/images"));
</script>
I don't think there is a way to halt GET requests from img elements once the page has loaded. It's difficult to suggest an alternative since I'm not sure what you're trying to achieve.
Can you be more specific?

jQuery and asp.net not playing nice together

Please refer to this page for reference: http://loadedgranola.valitics.com/_product_83484/blackberry_lime
I have a jQuery script that runs to replace the h1 tags with a background image. It works great when the document loads but when I click "add to cart", after the javascript alert the jQuery styling breaks. Due to CMS restrictions I have no direct access to their javascript or any of the ASP files but I assume there has to be an easy fix to this.
The code I'm using:
jQuery(document).ready(function(){
var textReplacer = document.title.replace(/ /g,'');
jQuery("h1").addClass('replaced').css("background","url(../images/h1/" + textReplacer + ".png) no-repeat 0 0");
});
I have also tried using the function pageLoad(sender, args) { magic but no luck.
Here you go ..
jQuery(document).ready( function() {
jQuery('<style type="text/css" media="screen">h1{text-indent:-9999px!important;background:url(../images/h1/'+document.title.replace(/ /g,'') +'.png) no-repeat 0 0!important;}</style>').appendTo('head');
});
what it does is add a new css rule that pushes the text way out of the box and adds the background image
Here is what is happening:
When you submit the shopping cart it's doing an AJAX call. The result of that call replaces most of the HTML on the page. Any changes you made before that get replaced.
Possible Solution
You would have to run that replace script again after the AJAX call is complete.
Questions
Why are you replacing the H1 tags on load? What problem are you trying to solve? You might be able to find a better CSS solution.

Auto ajax selectors with Jquery

I'm trying to make a proof of concept website, but I want perfect degradation. As such I'm going to code the website in plain XHTML first and then add classes & ids to hook them in jQuery.
One thing I want to do is eventually enable Ajax xmlhttprequest for all my links, so they display in a viewport div. I want this viewport to be a "universal" dump for any xmlhttprequest from multiple external pages.
I was wondering if I'm able to hardcode something like:
<a href="blah.html" class="ajax">, <a href="bleat.html" class="ajax">
etc. So as you can see, I give all link tags that I want to call Ajax requests from with the class ajax. In my JS based on jQuery, I want to be able to code it such that all positive ${"a").filter(".ajax") will automatically load their respective hrefs [variable] as a ajax request.
Please help. I'm a n00b.
With your example, you should be able to do:
$('.ajax').click(function () {
// Your code here. You should be able to get the href variable and
// do your ajax request based on it. Something like:
var url = $(this).attr('href');
$.ajax({
type: "GET",
url: url
});
return false; // You need to return false so the link
// doesn't actually fire.
});
I would suggest using a class different from "ajax" because it makes the code a little strange to read, because $('.ajax') could be misread as $.ajax().
The $('.ajax').click() part registers an onClick event handler for every element on the page with the class "ajax" which is exactly what you want. Then you use $(this).attr('href') to get the href of the particular link clicked and then do whatever you need!
Something like:
function callback(responseText){
//load the returned html into a dom object and get the contents of #content
var html = $('#content',responseText)[0].innerHTML;
//assign it to the #content div
$('#content').html(html);
}
$('a.ajax').click(function(){
$.get(this.href, callback);
return false;
});
You need to parse out everything that is outside of the #content div so that the navigation isn't displayed more than once. I was thinking about a regexp but probable easier to use jQuery to do it so I updated the example.

Resources