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.
Related
I need to include two <script> tags just before the </body> element via a custom tag in Google Tag Manager:
<script src="https://cdn.jsdelivr.net/npm/cookieconsent#3/build/cookieconsent.min.js" data-cfasync="false"></script>
and
<script>window.cookieconsent.initialise({"palette":{"popup":{"background":"#000"},"button":{"background":"#f1d600"}}});</script>
Because I need them to show up just before the </body> element, I am using jQuery to append these values as strings via appendTo():
<script>
var cookieConsentStyles = '<link rel="stylesheet" type="text/css" href="https://cdn.jsdelivr.net/npm/cookieconsent#3/build/cookieconsent.min.css" />';
var cookieConsentJS = '<script src="https://cdn.jsdelivr.net/npm/cookieconsent#3/build/cookieconsent.min.js" data-cfasync="false"></script>';
var cookieConsentInit = '<script>window.cookieconsent.initialise({"palette":{"popup":{"background":"#000"},"button":{"background":"#f1d600"}}});</script>';
jQuery(cookieConsentStyles).appendTo('head');
jQuery(cookieConsentJS).appendTo('body');
jQuery(cookieConsentInit).appendTo('body');
</script>
I have confirmed this works in the browser console but this does not work in Google Tag Manager because any JS code needs to be between <script> tags. So the <script> tags within the variable strings get interpreted despite being part of a string variable. See screenshot below.
I tried escaping the less-than and greater-than signs with the appropriate entity (i.e. > ;) but this also failed.
You can run the cookie consent script when the parent script is loaded using the onload event. Here is an example:
var cookieConsentJS = document.createElement( 'script' );
cookieConsentJS.type = 'text/javascript';
cookieConsentJS.src = '/path/to/cookieconsent.min.js';
cookieConsentJS.setAttribute('data-cfasync', false); // not sure what this is, but not touching.
// this part of the code will run when the script is loaded.
cookieConsentJS.onload = function() {
// here is your code running outside of a string.
window.cookieconsent.initialise({
"palette":{
"popup":{"background":"#000"},
"button":{"background":"#f1d600"}
}
});
};
// now let's append your code to the body.
document.body.appendChild( cookieConsentJS );
Note that jQuery was not used in this context.
Marked Ibu's answer as the final answer because his example using onload gave me an alternative approach that I was not aware of (running window.cookieconsent.initialise directly however did not work for some reason).
The exact solution, based on his example, is below:
var cookieConsentJS = document.createElement( 'script' );
cookieConsentJS.type = 'text/javascript';
cookieConsentJS.src = 'https://cdn.jsdelivr.net/npm/cookieconsent#3/build/cookieconsent.min.js';
cookieConsentJS.setAttribute('data-cfasync', false);
var cookieConsentInit = document.createElement( 'script' );
cookieConsentInit.innerText = 'window.cookieconsent.initialise({"palette":{"popup":{"background":"#000"},"button":{"background":"#f1d600"}}});';
cookieConsentJS.onload = function() {
document.body.appendChild( cookieConsentInit );
};
document.body.appendChild( cookieConsentJS );
I am using document.write in a function to give different CSS to user's based on their choosing.
function blue() {
document.write('<link rel="stylesheet" type="text/css" href="http://ilam.irib.ir/documents/697970/237563314/blue.css" />');
}
I am calling the function from an anchor tag.
function color2(){
document.getElementById("navigation").innerHTML +='<a class="myButton" onclick="blue()" background-color:"#05c8f2";></a>';
}
As you can guess, when the link is clicked, the page clears out and I get a blank page.
Is there any way to fix this problem? I don't want to stop page refreshing, I'm just trying to fix the problem in any way possible!
Note: don't ask why I'm adding code using JavaScript, and not directly into HTML code. This site is a large scale system and we just have access to JavaScript and CSS. So this is all we can do to edit our pages.
document.write rewrites the body , as a result the only thing in your document remains is the css file you added and hence it is blank.
View this
Code from above link :-
var cssId = 'myCss'; // you could encode the css path itself to generate id..
if (!document.getElementById(cssId))
{
var head = document.getElementsByTagName('head')[0];
var link = document.createElement('link');
link.id = cssId;
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = 'http://website.com/css/stylesheet.css';
link.media = 'all';
head.appendChild(link);
}
Instead of rewriting while dom , we append the link element inside head tag
I am trying to add a stylesheet only on the condition that the browser is either Chrome or Opera. I have the following control flow using the YUI library:
if ((Y.UA.chrome > 0) || (Y.UA.opera > 0)){
document.write("<link rel='stylesheet' media='print' type='text/css' href='../../../css/style_ticket_printing_header.css'/>");
}
Here is the conditionally attached css file, style_ticket_printing_header.css
#page
{
size: auto;
margin: 0mm;
}
Here is the full HTML:
https://gist.github.com/ebbnormal/b1cff9d45914bc2f63a4
When I run the page in Chrome, none of the <div>s that are defined within the <body> tag are rendered or are displayed within the DOM.
What is particularly confusing is that, when this CSS is loaded in the normal way (by simply referencing it via a <link> tag in the <head> of the page, all of the DOM are loaded perfectly.
And finally I know that it successfully renders the condition of seeing it is chrome as I formerly had an alert message in the body of the if block which successfully executed.
document.write() for adding a stylesheet causes document to be blank
Right. When you use document.write after the main page parsing is complete, it implicitly does a document.open, which wipes out the page.
Instead, use createElement and appendChild:
if ((Y.UA.chrome > 0) || (Y.UA.opera > 0)){
var link = document.createElement('link');
link.rel = "stylesheet";
link.media = "print";
link.type = "text/css";
link.href = "../../../css/style_ticket_printing_header.css";
document.querySelector("head").appendChild(link);
}
Or if you really like to use HTML: :-)
if ((Y.UA.chrome > 0) || (Y.UA.opera > 0)){
document.querySelector("head").insertAdjacentHTML(
"beforeend",
"<link rel='stylesheet' media='print' type='text/css' href='../../../css/style_ticket_printing_header.css'/>"
);
}
(Both of the above assume you have a head element, which you presumably do; it's required in a well-formed HTML document, either explicitly or because the browser adds it for you [but explicit is best].)
About querySelector: It finds the first element that matches a CSS selector. It's supported by all modern browsers, and also IE8. (There's also querySelectorAll, which finds a list of matching elements.)
Inside of your <head> tag in html file,
<SCRIPT LANGUAGE="JavaScript">
if ((Y.UA.chrome > 0) || (Y.UA.opera > 0)){
document.write("<LI" + "NK rel='stylesheet' media='print' type='text/css' href='../../../css/style_ticket_printing_header.css'/>");
}
</SCRIPT>
it may work.
Assuming you want to add the stylesheet into the head, take a look at this: Append some HTML into the HEAD tag?
The basic idea is to use
var newElement = document.createElement('element')
and
newElement.setAttribute('attr', 'val')
This will work (as originally suggested by users1100's answer on SharePoint.SE):
var head = document.getElementsByTagName('head')[0];
var link = document.createElement('link');
link.id = cssId;
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = 'http://website.com/css/stylesheet.css';
link.media = 'all';
head.appendChild(link);
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 want to append a style sheet(css) link to the head of an iframe using jquery .
i tried with the following code but not working.
$('#tabsFrame').contents().find("head").append(cssLink);
i am used to append data to an iframe by using this line of code
$('body', window.frames[target].document).append(data);
In your case, this line would look like this
$('head', window.frames['tabsFrame'].document).append(cssLink);
EDIT:
Add <head></head> to the iframe and change your var cssLink to
cssLink = '<link href="cupertino_1.4/css/cupertino/jquery-ui-1.8.7.custom.css" type="text/css" rel="Stylesheet" class="ui-theme" />
well, you can check with this:
$('#tabsFrame').contents().find("head")[0].appendChild(cssLink);
I believe you can't manipulate the content of an iframe because of security.
Having you be able to do such a thing would make cross-site-scripting too easy.
The iframe is totally seperate from the DOM of your page.
Also, java and javascript are two completely different things!
Follow the Link to see the difference here
This could be related to IE not allowing you to add elements in the DOM, check out the clever solution here
EDIT:
Thanks #kris, good advice to add more info in case links break:
Here is the main code snippet from the link, in case it goes out again.
(This is only needed with some IE version, for the most part, the other answer work just fine)
var ifrm;
//attempts to retrieve the IFrame document
function addElementToFrame(newStyle) {
if (typeof ifrm == "undefined") {
ifrm = document.getElementById('previewFrame');
if (ifrm.contentWindow) {
ifrm = ifrm.contentWindow;
} else {
if (ifrm.contentDocument.document) {
ifrm = ifrm.contentDocument.document;
} else {
ifrm = ifrm.contentDocument;
}
}
}
//Now that we have the document, look for an existing style tag
var tag = ifrm.document.getElementById("tempTag");
//if you need to replace the existing tag, we first need to remove it
if (typeof tag != "undefined" || tag != null) {
$("#tempTag", ifrm.document).remove();
}
//add a new style tag
$("HEAD", ifrm.document).append("");
}