I have created a bookmarklet that executes the below code, adding css styling to the page. It works on all tried sites in Chrome and Firefox, but fails for some sites on IE. It's always the same sites that fail.
The fourth line fails with "Unexpected call to method or property access" for SOME sites, only on IE.
var head = document.getElementsByTagName('head')[0];
var style = document.createElement('style');
style.type = 'text/css';
style.appendChild(document.createTextNode(""));
head.appendChild(style);
Two sites that fail on IE 10:
http://www.momswhothink.com/cake-recipes/banana-cake-recipe.html
http://www.bakerella.com/
I think your problem is this line:
style.appendChild(document.createTextNode(""));
Here you are inserting a Text Node into a Style element, which according to the HTML specification is not allowed, unless you specify a scoped attribute on the style.
Check the specification of style here (Text Node is flow content).
You can find good ways to create the style element in a crossbrowser way here.
probably because you forgot to add document.ready()
Using jquery
$(document).ready(function(){
var head = document.getElementsByTagName('head')[0];
var style = document.createElement('style');
style.type = 'text/css';
style.appendChild(document.createTextNode(""));
head.appendChild(style);
});
Using javascript
Try wrapping your javascript in an onload function. So first add:
<body onload="load()">
function load() {
var head = document.getElementsByTagName('head')[0];
var style = document.createElement('style');
style.type = 'text/css';
style.appendChild(document.createTextNode(""));
head.appendChild(style);
}
I'm not sure why you're getting that error in IE10... I know in IE<9 an error is thrown if you try to modify the innerHTML of a <style> tag. It's still doable, you just have to do a bit of a workaround. For example (using jQuery):
var customCSS = "body { color: red; }";
var customStyle = $('<style type="text/css" />');
try {
$(customStyle).html(customCSS); // Good browsers
} catch(error) {
$(customStyle)[0].styleSheet.cssText = customCSS; // IE < 9
}
$(customStyle).appendTo('head');
Hope this helps.
Do you really have to dynamically add the style section to the page? What about adding the attribute, itself, on the fly, like this:
$(document).ready( function() {
$('[id="yourObjID"]').css('yourAttribute','itsvalue');
});
Adding the style section dynamically, rather than the attribute, seems like way overkill, to me.
Related
Trying this on Wordpress:
Inside my iframe I have a ._2p3a class I want to change its width to ._2p3a {width: 100% !important;}.
With CSS its not possible to access that class so I am trying with JavaScript:
MY JS CODE:
function hello() {
let myiFrame = document.getElementById("iframe-css");
let doc = myiFrame.contentDocument;
doc.body.innerHTML = doc.body.innerHTML + '<style>._2p3a{width: 100% !important;}</style>';
}
//the iframe id > "iframe-css"
code Source: https://redstapler.co/how-to-apply-css-to-iframe/
The error:
land_page.js?ver=1.0:4 Uncaught TypeError: Cannot read property 'body' of null
at hello (land_page.js?ver=1.0:4)
at HTMLIFrameElement.onload ((index):539)
underlined code:
.body.innerHTML = doc.body.innerHTML + '<style>._2p3a{width: 100% !important;}</style>';
Tried: Using CSS to affect div style inside iframe
(got errors with all examples "None worked").
I am running this function with onload="hello(this)" on my iframe.
Any other suggestions how I can edit that class to make its width 100%??
please try bellow code ... I hope you get result:
let myiFrame = document.getElementById("iframe-css").contentWindow;
let doc = myiFrame.document;
doc.body.innerHTML = doc.body.innerHTML + '<style>._2p3a{width: 100% !important;}</style>';
Adding a <style> element isn't the best way to do this. However, even if it was, you should try to avoid adding elements via innerHTML. It is better to use Document.createElement (document is an instance of Document) and Element.appendChild (all elements are instances of the Element class).
The best way to do this is by directly modifying the style of the elements in the class.
function hello() {
let myiFrame = document.getElementById("iframe-css");
let doc = myiFrame.contentDocument ?? myiFrame.contentWindow?.document ?? new Document();
let elements = doc.getElementsByClassName("2p3a");
for(let i = 0; i < elements.length; ++i) {
elements[i].style.width = "100%";
}
}
Also, the onload attribute sometimes doesn't work on an iFrame. You may have to use the DOM like this:
document.getElementById("iframe-css").onload = hello;
On a side note, you should generally stick to 2 or 4 spaces of indentation in JavaScript, but you chose 3.
Decided to use a different plugin since using the facebook iframe was causing some trouble. With this new plugin everything is working fine so yea.
Thanks to anyone who put effort to answering, I appreciate your help.
I'm trying to create master pages using javascript. I created Javascript objects containing the html code then including the js the html files. The problem is that I cant inject css in the head of the html. the jquery append function is not working..
You don't really need to inject CSS in the head for it to style your page. I think you can just include the <link> tag anywhere in the DOM and it should work.
However, if you must include it in the head, try this:
function addcssfile(cssfile){
var head = document.head || document.getElementsByTagName('head')[0];
var s = document.createElement('link');
s.setAttribute('rel', 'stylesheet');
s.setAttribute('href', cssfile);
head.appendChild(s);
}
If you want to append just the CSS styles and properties, and not an actual CSS file, you can do this:
function addcss(css){
var head = document.head || document.getElementsByTagName('head')[0];
var s = document.createElement('style');
s.setAttribute('type', 'text/css');
if (s.styleSheet) { // IE
s.styleSheet.cssText = css;
} else { // the world
s.appendChild(document.createTextNode(css));
}
head.appendChild(s);
}
I have a script that brings up some things that I don't want (a selector).
The script brings up a div class named "selector", and I don't want that div class to show. (I have no access to the css files)
Here is the script:
<script language="javascript" type="text/javascript">
window.onload = function() {
var script = document.createElement("script");
script.type = "text/javascript";
script.setAttribute("language", "javascript");
script.src = "http://js.sbrfeeds.com/js";
script.id = "widget-main-script";
document.body.appendChild(script);
}
Is there any way to put some code in the above script that will hide the div "selector" when loaded?
Basically, I want what's circled in the picture to not show, and it is in a div class name "selector".
Image here: http://imagizer.imageshack.us/v2/800x600q90/543/f385.png
document.getElementsByClassName('selector')[0].style.display = 'none';
Mind you, before you run that, you need to make sure your script fully loaded. Is there a reason you don't just add the script as a script tag so it will load when the page loads? Then you don't have to worry about all that mumbo jumbo.
Assuming that your Div has an ID (and you are using JQuery), you could do something like this: JSFiddle
$('#selDiv').removeClass('selector');
If you aren't using JQuery, you could do this: JSFiddle
document.getElementById("selDiv").className = "";
This isn't really a legitimate answer, but I ended up just hiding what I needed to be hid using a div class. Just throwing that here in case someone else needs it. You could also use a png file if it's an awkward shape to hide. Mine was just rectangular though.
var css = '.selector { display : none}',
header = document.getElementsByTagName('head')[0],
style = document.createElement('style');
style.type = 'text/css';
if (style.styleSheet){
style.styleSheet.cssText = css;
} else {
style.appendChild(document.createTextNode(css));
}
header.appendChild(style);
This will create a tag at header and then you can hide your element. Additionally you can set other CSS properties. Not sure this will work in your situation.
I want to append element To head of an Iframe (fancybox)
there is a strange problem : when I use Firefox to Breakpoint on line of code that append element to Head it works correctly but when I run site normally without firebug it does not work;
I am using fancybox 1.3.4 and the code run in onComplete event
var cssLink = document.createElement("link")
cssLink.href = "/themes/furniture/css/test.css";
cssLink .rel = "stylesheet";
cssLink .type = "text/css";
var f123= document.getElementById('fancybox-frame');
var d123= f123.contentDocument || f123.contentWindow.document;
d123.head.appendChild(cssLink);
UPDATE
I also try this code
var $head = $("#fancybox-frame").contents().find("head");
$head.append($("<link/>",
{ rel: "stylesheet", href: "/themes/furniture/css/test.css", type: "text/css" } ));
but it does not work either
Tnx
Well, it seems to be a racing condition indeed (as pointed out by olsn in his comment) between loading the iframe and finding elements inside of it, which fails if the second occurs first ;)
As a workaround, you could use the .load() method to wait for the iframe to be completely loaded before trying to append the stylesheet to the <head> section.
This code should do the trick :
$(document).ready(function () {
$(".fancybox").fancybox({
"type": "iframe",
"onComplete": function () {
var $style = '<link rel="stylesheet" href="/themes/furniture/css/test.css" type="text/css" />';
$("#fancybox-frame").load(function () {
$(this).contents().find("head").append($style);
});
}
});
});
Note : this is for fancybox v1.3.4. Fortunately v2.x includes more flexible public methods than v1.3.4 to circumvent this issue, like afterLoad and beforeShow
Also notice that setTimeout() will work too, but it renders oddly.
I'm working with a CMS, which prevents editing HTML source for <head> element.
For example I want to add the following above the <title> tag:
<meta http-equiv="X-UA-Compatible" content="IE=EmulateIE7" />
You can select it and add to it as normal:
$('head').append('<link />');
JavaScript:
document.getElementsByTagName('head')[0].appendChild( ... );
Make DOM element like so:
const link = document.createElement('link');
link.href = 'href';
link.rel = 'rel';
document.getElementsByTagName('head')[0].appendChild(link);
jQuery
$('head').append( ... );
JavaScript:
document.getElementsByTagName('head')[0].appendChild( ... );
You can use innerHTML to just concat the extra field string;
document.head.innerHTML = document.head.innerHTML + '<link rel="stylesheet>...'
However, you can't guarantee that the extra things you add to the head will be recognised by the browser after the first load, and it's possible you will get a FOUC (flash of unstyled content) as the extra stylesheets are loaded.
I haven't looked at the API in years, but you could also use document.write, which is what was designed for this sort of action. However, this would require you to block the page from rendering until your initial AJAX request has completed.
In the latest browsers (IE9+) you can also use document.head:
Example:
var favicon = document.createElement('link');
favicon.id = 'myFavicon';
favicon.rel = 'shortcut icon';
favicon.href = 'http://www.test.com/my-favicon.ico';
document.head.appendChild(favicon);
Create a temporary element (e. g. DIV), assign your HTML code to its innerHTML property, and then append its child nodes to the HEAD element one by one. For example, like this:
var temp = document.createElement('div');
temp.innerHTML = '<link rel="stylesheet" href="example.css" />'
+ '<script src="foobar.js"><\/script> ';
var head = document.head;
while (temp.firstChild) {
head.appendChild(temp.firstChild);
}
Compared with rewriting entire HEAD contents via its innerHTML, this wouldn’t affect existing child elements of the HEAD element in any way.
Note that scripts inserted this way are apparently not executed automatically, while styles are applied successfully. So if you need scripts to be executed, you should load JS files using Ajax and then execute their contents using eval().
Try a javascript pure:
Library JS:
appendHtml = function(element, html) {
var div = document.createElement('div');
div.innerHTML = html;
while (div.children.length > 0) {
element.appendChild(div.children[0]);
}
}
Type:
appendHtml(document.head, '<link rel="stylesheet" type="text/css" href="http://example.com/example.css"/>');
or jQuery:
$('head').append($('<link rel="stylesheet" type="text/css" />').attr('href', 'http://example.com/example.css'));
With jquery you have other option:
$('head').html($('head').html() + '...');
anyway it is working. JavaScript option others said, thats correct too.