I'm making a Chrome extension that inserts an iframe into the page and applies my own styling to it:
const iframe = document.createElement('iframe');
iframe.style.background = 'white';
iframe.style.position = 'fixed';
iframe.style.width = '300px;
iframe.style.height = '50%';
iframe.style.top = '0';
iframe.style.zIndex = '999';
iframe.frameBorder = 'none';
document.documentElement.appendChild(iframe);
Most of the time this works fine but there are some sites which target iframes with JavaScript and apply some inline CSS which messes up the Layout. https://exchange.adobe.com/creativecloud.html?zpluginId=12557&mv=product&mv2=accc does this when you resize the browser.
Is there any way around this? I tried setting the inline styles as !important but it has on affect.
1. Solution
You could make use of the css property all
In your case it would look like this:
const iframe = document.createElement('iframe');
iframe.style.all = 'unset'; // maybe also add `! important`
// ...
document.documentElement.appendChild(iframe);
2. Solution
If you want to ensure that your style attribute does not get changed. You could get it done with a MutationObserver
const iframe = document.createElement('iframe');
iframe.style.all = 'unset'; // maybe also add `! important`
// ...
document.documentElement.appendChild(iframe);
const observer = new MutationObserver((event) => {
// check if styles differ from your initial ones
// fix them if necessary
});
observer.observe(iframe, {
attributes: true,
attributeFilter: ['style'],
childList: false,
characterData: false
});
It's kind of brute force. But will work for sure.
Have you looked at the sandbox attribute of the iframe? If you set allow-same-origin to false. Then it will cause the iframe to appear like a cross-origin iframe and block the parent page from accessing it.
Related
I have an issue with the div:
<div id="root-hammerhead-shadow-ui" contenteditable="false" class="root-hammerhead-shadow-ui"></div>
which is injected by testcafe into an iframe that I'd like to test.
The iframe contains an input field and some styles which make the hammerhead div cover the iframe and input completely (width/height set to 100%) so I'm unable to use typeText with it (expect visible passes correctly).
I can fix the issue during debugging by setting the width/height of the hammerhead div to defaults, can I somehow do the same thing in code?
You can use the ClientFunction API to manipulate DOM elements on a client. Please take a look at the following example:
import { Selector, ClientFunction } from 'testcafe';
fixture `New Fixture`
.page `https://example.com`;
test('New Test', async t => {
const changeHammerheadDiv = ClientFunction(() => {
const hammerHeadDiv = document.getElementById('root-hammerhead-shadow-ui');
hammerHeadDiv.style.width = '0';
hammerHeadDiv.style.height = '0';
});
await t.switchToIframe(Selector('iframe'));
await changeHammerheadDiv();
await t.typeText(Selector('body').find('input'), 'qwerty');
});
I have a rather simple question about React, but I wanna see what the best practice is for this kind of situation.
How do you change the body background color, according to the page you are in? Do you set a CSS rule for the body background color in a CSS file for each page and import it in the component? Will the above work or do I need to add a CSS class to the body tag using componentDidMount, and remove it in componentWillUnmout?
Which one is the preferred way? I noticed that if you imported some CSS in one page, it will remain active even after you navigate to a new url. So, maybe I need to use componentDidMount/componentWillUnMount, is that correct?
Yes,we can change the background-color of body based on the route change.Determine the page you are in by using componentWillReceiveProps or componentDidUpdate lifecycle method and get the route name using props.location.pathname provided by react-router-dom.If your route composes of params,then just replace the props.location.pathname by props.match.params.customparam
componentDidMount(){
document.body.style.background = "red";
}
componentWillReceiveProps(nextProps){
if(this.props.location.pathname !== nextProps.location.pathname){
const currentRoute = nextProps.location.pathname;
switch(currentRoute){
case "\a": document.body.style.background = "blue";
break;
case "\b": document.body.style.background = "green";
break;
default : document.body.style.background = "red";
}
}
}
I am using my own .css stylesheet to overwrite some Bootstrap CSS rules, in this particular case I want the navbar-brand image display as 'inline-block', not as 'block', like specifies bootstrap.css.
No problem with that, I have my navbar-brand image handled by my 'custom.css', with 'display: inline-block', until an event that changes the 'src' attribute is fired:
var logoChanged = false;
$(window).on("resize",function(){
var screen = $(window).width();
if(screen<390 && !logoChanged){
$("navbar-brand img").attr("src","img/logo-aure2.png");
logoChanged=true;
});
}else if(screen>390 && logoChanged){
$("navbar-brand img").attr("src","img/logo-aurestudio.png");
logoChanged=false;
});
}
});
The function works fine and the 'src' attribute changes correctly when resizing the screen, but after that, navbar-brand returns to be handled by bootstrap.css and not by my custom.css, displaying the image as a 'block' again.
Anyone know why this happens?
Thanks a lot
I'm looking to set the background-image (or even render an image via the pseudo elements :after or :before) to the value, which will be a URL, of a rel attribute, but only in certain cases (this is a cloud file listing). For example:
HTML:
<div class="icon ${fileExtension}" rel="${fileURL}"></div>
It would be great if I could do something like this:
CSS:
.icon.png,
.icon.jpg,
.icon.jpeg,
.icon.bmp,
.icon.gif { background-image: attr(rel,url); }
... but obviously that doesn't work as, if I'm not mistaken, the attr() CSS function only works inside pseudo element blocks.
I know there are ways of doing this using conditional JSP or even jQuery logic, but I'd like to figure out a neat way of doing it via CSS3, since I'm only concerned with modern browsers at the moment anyway.
Also, I don't want to explicitly set the background image to the URL or create an <img> element, because by default if the file is not a supported image, I'd rather display a predetermined set of icons.
Using
.icon:after{ content: ""attr(rel)""; }
displays the rel value as text.
A jQuery solution is to add the background-image (taken from the rel value) as inline CSS:
jQuery(function($) {
$('.icon').each(function() {
var $this = $(this);
$this.css('background-image', 'url(' + $this.attr('rel') + ')');
});
});
I've tried to do something using jQuery but i don't exactly understand what you want so i can't go on with my code. So far i've done only this.
EDITED I hope it's exactly what you need
$(function(){
var terms = new Array('png','jpg','jpeg','bmp','gif');
$('.icon').each(function(){
var t = $(this),
rel = t.attr('rel'),
cls = t.attr('class');
cls = cls.split(' ');
for (var i=0; i < terms.length; i++) {
if (terms[i] == cls[1]) {
t.css('background-image','url('+rel+')');
}
}
});
});
if you can give me a better example, to undestand exactly what you want, i hope somebody from here will be able to solve your problem.
Regards,
Stefan
I've decided to go the jQuery route, and used a combination of #ryanve and #stefanz answers. Thanks guys
$(document).ready(function() {
$(".png,.jpg,.jpeg,.bmp,.gif,.tiff").each(function(n) {
var bg = 'url(' + $(this).attr("rel") + ')';
$(this).css('background-image', bg);
});
});
I think this is relatively neat/concise and works well for my needs. Feel free to comment on efficiency, methodology, etc.
I am using SimpleModal and i am opening an Iframe (using ff)
it seems to work ok in ie9 but in ff it is calling the iframe src twice
Thanks for any help
the code i am calling looks like
function addNew(){
var src = "/php/ftp/parsehome.php?dir="+userDir+"&idx=new";
$.modal('<iframe src="' + src + '" height="445" width="800" style="border:0">', {
containerCss:{
backgroundColor:"#E1EFF7",
borderColor:"#00A99D",
height:450,
padding:0,
width:840
},
modal: true
});
}
I ran into the same problem. Looking at the plugin code...
// add styling and attributes to the data
// append to body to get correct dimensions, then move to wrap
s.d.data = data
.attr('id', data.attr('id') || s.o.dataId)
.addClass('simplemodal-data')
.css($.extend(s.o.dataCss, {
display: 'none'
}))
.appendTo('body');
data = null;
You can see the data is added to the page body with the line .appendTo('body'); to calculate the correct dimensions for the modal. If you comment out this line, it will prevent the iframe being called twice.
// add styling and attributes to the data
// append to body to get correct dimensions, then move to wrap
s.d.data = data
.attr('id', data.attr('id') || s.o.dataId)
.addClass('simplemodal-data')
.css($.extend(s.o.dataCss, {
display: 'none'
}));
data = null;
Not sure if this modification will cause your modal size to have the wrong dimensions, but my iframe was set to width=100% and height=100% so didn't affect me.