Adding a Style Sheet to a document using jQuery - javascript

jQuery(document).ready(function($) {
/******* Load CSS *******/
$('head').append('<link rel="stylesheet" type="text/css" media="all" href="'+('https:' == document.location.protocol ? 'https://' : 'http://') +'thesite.com/api/widgets/tghd/pages.css">');
});
The above code is what I use to add the style sheet to the document. The code inspector shows that the code has been added but the console does not display that the browser has requested the document and the styles do not take affect.
How can I add a style sheet to an already loaded document and have it take affect.
BTW. if it matters, I am using this code for a widget so I will be used across multiple domains.
Thank You in advance for any help!

try this:
(function () {
var li = document.createElement('link');
li.type = 'text/css';
var href='http://' + 'thesite.com/api/widgets/tghd/pages.css';
li.setAttribute('href', href);
var s = document.getElementsByTagName('head')[0];
s.appendChild(li, s);
})();

OK after doing a few tests, I finally figured out what was going on. This original code was provided by: #Vicky Gonsalves
var li = document.createElement('link');
li.type = 'text/css';
var href=('https:' == document.location.protocol ? 'https://' : 'http://') +'thesite.com/api/widgets/pages.css';
li.setAttribute('href', href);
li.setAttribute('rel','stylesheet');
var s = document.getElementsByTagName('head')[0];
s.appendChild(li, s);
The changes that I made to this are:
I added the http and https switch to help with different connection types
added the attribute li.setAttribute('rel','stylesheet'); <-- which I believe fixed the problem.

Related

How to determine when document has loaded after loading external css

How to determine when document has loaded(or is loading) after loading external css?
Normal page has loaded and complete at first time(with using document.onreadystatechange or document.readyStage), but after time script will call function to place a new stylesheet CSS into HTML for changing a background or images. During change stylesheet, document has still stage complete. Stage never has been changed after calling function? Why?
Timeline(example):
Visit one page : localhost/index.html
Document has stage loading
Document has stage complete
User was trying to change a theme, at this time stage hasnt been changed yet.
UPDATE: Without jQuery:)
UPDATE:
Example problem with using one image:
<!DOCTYPE html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<script>
document.onreadystatechange = function(){
console.log(document.readyState);
};
function checkDocumentState(){
console.log(document.readyState);
return setTimeout(function(){
checkDocumentState();
}, 1000);
}
checkDocumentState();
</script>
</head>
<body>
<img src="" onclick="this.setAttribute('src','http://i.imgur.com/uRBtadp.jpg')" style="width:50px; height:50px; background-color:gray; " /> Press empty image and open new image.
</body>
</html>
FOUND ANSWER: How can I tell when a CSS background image has loaded? Is an event fired?
But hopeless .. lack of universality...
CSS is called after DOM elements are populated. This is why in the days of dial up internet, the page would load all funky looking, and then all of a sudden start to develop into the desired page bit by bit. I would suggest using Jquery instead, where you could use the following code to be able to ensure the document is fully loaded and the CSS is already implemented
$document.ready(function() {
//Insert Code here
}
Hope that helps
Answering the question, how to determine the document has loaded after dynamically loading a css file depends upon the different browser vendors out there. There is not a single sure shot way for all the browsers, but lets tackle the problem one by one for each of these browsers.
Preface
var url = "path_to_some_stylesheet.css",
head = document.getElementsByTagName('head')[0];
link = document.createElement('link');
link.type = "text/css";
link.rel = "stylesheet"
link.href = url;
head.appendChild(link);
Once that appending is done:
Internet Explorer : fires readystatechange and load.
Opera : fires load event via onload.
Chrome : Doesnt fire an event but increments document.styesheets.length only after the file has arrived.
Firefox: I was not able to reliably get anything other than mozAfterPaint.
I wrote this code, what i wanted and worked for me:
window.engineLoading = {images_count:0, images_loaded_count:0, fonts_count:0, fonts_loaded_count:0 };
document.querySelector("a").onclick = function(){ // first elemnet a
var before_stylesheets_length = document.styleSheets.length;
var before_fonts_size = document.fonts.size;
document.fonts.onloadingerror = function(a){
window.engineLoading.fonts_loaded_count++;
}
document.fonts.onloading = function(a){
window.engineLoading.fonts_count++;
}
document.fonts.onloadingdone = function(a){
window.engineLoading.fonts_loaded_count++;
}
var head= document.getElementsByTagName('head')[0];
var style= document.createElement('link');
style.rel= 'stylesheet';
style.setAttribute("href","./new_style.css");
style.onload = function(){
for(i=before_stylesheets_length; i<document.styleSheets.length; i++){
var rules = document.styleSheets[i].rules;
for(q=0; q<rules.length; q++){
var styles = rules[q].style;
for(s=0; s<styles.length; s++){
console.log(styles[s]);
if((styles[s] == "background-image" || styles[s] == "background") && styles.backgroundImage.length > 0){
window.engineLoading.images_count++;
var body= document.getElementsByTagName('body')[0];
var image = document.createElement('img');
var url = styles.backgroundImage;
url = url.replace(/^url\(["']?/, '').replace(/["']?\)$/, '');
image.src = url;
image.width = 0;
image.height = 0;
image.setAttribute("class","pace-load-style");
image.onload = function(e){
console.log(e);
window.engineLoading.images_loaded_count++;
};
image.onerror = function(e){
window.engineLoading.images_laoded_count++;
}
body.appendChild(image);
break;
}
}
}
}
};
style.onerror = function(){};
head.appendChild(style);
setTimeout(function(){
checkCurrentState();
}, 1000);
return false;
};
function checkCurrentState(){
if(window.engineLoading.images_count == window.engineLoading.images_loaded_count && window.engineLoading.fonts_count == window.engineLoading.fonts_loaded_count){
console.log("loaded"); return true;
}console.log("still loading...");
return setTimeout(function(){
checkCurrentState();
}, 1000);
};
UPDATE: Scipt has bug on localfile because of empty rule. CSSRules is empty I don't worry about it , and no need fix it.
UPDATE: Mozilla Firefox hasnt reference document.fonts.

Add stylesheet to Head using javascript in body

I'm working with a CMS that prevents us from editing the head section. I need to add css stylesheet to the site, right after the tag. Is there a way to do this with JS, where I can add a script to the bottom of the page (I have access to add script right before the tag) that would then inject the stylesheet into the head section?
Update: According to specs, the link element is not allowed in the body. However, most browsers will still render it just fine. So, to answer the questions in the comments - one really has to add link to the head of the page and not the body.
function addCss(fileName) {
var head = document.head;
var link = document.createElement("link");
link.type = "text/css";
link.rel = "stylesheet";
link.href = fileName;
head.appendChild(link);
}
addCss('{my-url}');
Or a little bit easier with jquery
function addCss(fileName) {
var link = $("<link />",{
rel: "stylesheet",
type: "text/css",
href: fileName
})
$('head').append(link);
}
addCss("{my-url}");
Original answer:
You don't need necessarily add it to the head, just add it to the end of body tag.
$('body').append('<link rel="stylesheet" type="text/css" href="{url}">')
as Juan Mendes mentioned, you can insert stylesheet to the head instead
$('head').append('<link rel="stylesheet" type="text/css" href="{url}">')
And the same without jQuery (see code above)
This will do what you want in an intelligent way. Also using pure JS.
function loadStyle(href, callback){
// avoid duplicates
for(var i = 0; i < document.styleSheets.length; i++){
if(document.styleSheets[i].href == href){
return;
}
}
var head = document.getElementsByTagName('head')[0];
var link = document.createElement('link');
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = href;
if (callback) { link.onload = function() { callback() } }
head.appendChild(link);
}
I've modified Eddie's function to remove or toggle the stylesheet on or off. It will also return the current state of the stylesheet. This is useful for example, if you want to have a toggle button on your website for vision-impaired users and need to save their preference in a cookie.
function toggleStylesheet( href, onoff ){
var existingNode=0 //get existing stylesheet node if it already exists:
for(var i = 0; i < document.styleSheets.length; i++){
if( document.styleSheets[i].href && document.styleSheets[i].href.indexOf(href)>-1 ) existingNode = document.styleSheets[i].ownerNode
}
if(onoff == undefined) onoff = !existingNode //toggle on or off if undefined
if(onoff){ //TURN ON:
if(existingNode) return onoff //already exists so cancel now
var link = document.createElement('link');
link.rel = 'stylesheet';
link.type = 'text/css';
link.href = href;
document.getElementsByTagName('head')[0].appendChild(link);
}else{ //TURN OFF:
if(existingNode) existingNode.parentNode.removeChild(existingNode)
}
return onoff
}
Sample usage:
toggleStylesheet('myStyle.css') //toggle myStyle.css on or off
toggleStylesheet('myStyle.css',1) //add myStyle.css
toggleStylesheet('myStyle.css',0) //remove myStyle.css
You can use pure javascript and still elegance in the modern browser.
const range = document.createRange()
const frag = range.createContextualFragment(`THE CONTENT IS THE SAME AS THE HTML.`)
document.querySelector("YOUR-NODE").append(frag)
It's very easy to add any HTML code.
Document
createRange
createContextualFragment
Example 1
Add the style on the head by javascript.
<head></head><body><button class="hover-danger">Hello World</button></body>
<script>
const range = document.createRange()
const frag = range.createContextualFragment(`
<style>
.hover-danger:hover{
background-color: red;
font-weight: 900
}
</style>
`
)
document.querySelector("head").append(frag)
</script>
Example 2
Import CSS, JS, and modify the existing stylesheet.
<head></head>
<body><button class="btn btn-primary hover-danger">Hello world</button></body>
<script>
const range = document.createRange()
const frag = range.createContextualFragment(`
<link href="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css" rel="stylesheet" crossorigin="anonymous">
<script src="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/js/bootstrap.bundle.min.js"/>
`)
document.querySelector("head").append(frag)
window.onload = () => {
// 👇 If you don't want to import the new source, you can consider adding the data to exists source.
const nodeLink = document.querySelector(`link[href^="https://cdn.jsdelivr.net/npm/bootstrap#5.0.2/dist/css/bootstrap.min.css"]`) // ^: match begin with my input
if (nodeLink) { // !== null
const stylesheet = nodeLink.sheet
const myCSS = `
background-color:red;
font-weight: 900;
`
stylesheet.insertRule(`.hover-danger:hover{ ${myCSS} }`, stylesheet.cssRules.length)
}
}
</script>
📙 You must have permission to modify the CSS directly
If you get the error:
Failed to read the 'cssRules' property from 'CSSStyleSheet': Cannot access rules,
then you can reference: https://stackoverflow.com/a/49994161/9935654
Here is a simple one-liner to add a stylesheet:
document.head.insertAdjacentHTML('beforeend', `<link typs="text/css" rel="stylesheet" href="<Source URL>">`);

Changing innerHTML of script tags in IE for loading google plusone button explicitly

To add Google's plusone button on your website the following script tag is to be inserted (for explicit load).
<script type="text/javascript" src="https://apis.google.com/js/plusone.js">
{"parsetags": "explicit"}
</script>
It looks pretty straight forward in HTML. However I wan't to insert the script using a JS file. So I use the following code:
var e = document.createElement('script');
e.src = "https://apis.google.com/js/plusone.js";
e.id = "googplusonescript";
e.innerHTML = '{"parsetags": "explicit"}';
document.getElementsByTagName("head")[0].appendChild(e);
It works pretty awesome in all the browsers except IE because IE doesn't allow us to write the innerHTML of script tags. Anywork arounds anyone ? (I have jquery inserted in the page. So can use jquery too.)
Came across the same issue.
Under IE you should use
script.text = '{"parsetags": "explicit"}';
instead of script.innerHTML
try creating a textNode and appending it to your script tags:
var myText = document.createTextNode('{"parsetags": "explicit"}');
myScriptTag.appendChild(myText);
Try the following:
window['___gcfg'] = { parsetags: 'explicit' };
var ispoloaded;
function showpo() {
var pohd = document.getElementsByTagName('head')[0];
var poscr = document.createElement('script');
poscr.type ='text/javascript';
poscr.async = true;
poscr.text ='{"parsetags": "explicit"}'; //works on IE too
poscr.src = "http://apis.google.com/js/plusone.js";
pohd.appendChild(poscr);
ispoloaded = setInterval(function () {
//check if plusone.js is loaded
if(typeof gapi == 'object') {
//break the checking interval if loaded
clearInterval(ispoloaded);
//render the button, if passed id does not exists it renders all plus one buttons on page
gapi.plusone.go("idthatexists");
}
}, 100); //checks every 0.1 second
}

How to load all scripts, stylesheets, and markup from one js file?

The following small snippet of code cannot be changed once deployed (it's in an RIA) so everything must be loaded via a bootstrapper.js file:
<div id="someDivID"></div>
<script type="text/javascript" src="bootstrapper.js"></script>
What's the best way to load up all the js, css, and markup? Is there a better (cleaner, faster, crisper) way than the following?:
function createDivs() {
var jsDiv = document.createElement('div');
jsDiv.id = 'allJavascriptHere';
var contentDiv = document.createElement('div');
contentDiv.id = 'allContentHere';
document.getElementById("someDivID").appendChild(jsDiv);
document.getElementById("someDivID").appendChild(contentDiv);
function importScript(url){
var script = document.createElement('script');
script.type = 'text/javascript';
script.src = url;
document.getElementById("jsDiv").appendChild(script);
}
importScript("http://example.com/jquery-1.4.2.min.js");
importScript("http://example.com/anotherScript.js");
}
window.onload = function(){
$.get("http://example.com/someHTML.html", function(data) {
$('#contentDiv').html(data);
setTimeout("javaScript.init()", 200);
});
}
with stylesheets in the someHTML.html file as so:
<style type="text/css">
#import url("example.com/styleSheet.css");
</style>
(note: I don't know why I need the setTimeout but for some reason I do. Maybe your answer won't require it.)
You can use jQuery's $.getScript() to import scripts.
I recently wrote a function to import CSS.
var getCss = function(file, callback) {
if (typeof callback !== 'function') {
throw 'Not a valid callback';
};
$.get(file, function(css) {
var top = $('head > link[rel=stylesheet]').length ? $('head > link[rel=stylesheet]:last') : $('head > *:last');
top.after('<link rel="stylesheet" type="text/css" href="' + file + '">');
callback();
});
};
If your css is also in that js file, you can simply add css code to the documents style tag. It can be useful in some situations, where using different css file is not allowed etc.
If you're looking to load CSS asynchronously in an easy fashion similar to $.getScript check out loadCSS, a standalone library for loading CSS without a dependency on jQuery.

Google Analytics pageTracker is not defined?

Little bit confused... I am trying to track mailto links being clicked, but constantly 'pageTracker is not defined' is shown. I have the following code just before my end body tag ()
<script type="text/javascript">
var _gaq = _gaq || [];
_gaq.push(['_setAccount', 'UA-000000']); // This is my account number, I have added the zeros in this editor
_gaq.push(['_trackPageview']);
(function() {
var ga = document.createElement('script'); ga.type = 'text/javascript'; ga.async = true;
ga.src = ('https:' == document.location.protocol ? 'https://ssl' : 'http://www') + '.google-analytics.com/ga.js';
var s = document.getElementsByTagName('script')[0]; s.parentNode.insertBefore(ga, s);
})();
</script>
Then I am using this in my mailto links
hello#mydomain.co.uk
I cannot see why its not working? Any help would be appreciated
The new Async Google Analytics code (that you're using) works a bit differently than the non-Async. Any time that you want to call a method on pageTracker you simply push a "message" onto the "_gaq" queue.
hello#mydomain.co.uk
Although, tracking a mailto link may work better as an event:
hello#mydomain.co.uk
For more info take a look at the Async Tracking Users Guide.
We can also add:
//mantain syntax between old and new asynch methods
//http://code.google.com/apis/analytics/docs/tracking/asyncUsageGuide.html#Syntax
function _pageTracker (type) {
this.type = type;
this._trackEvent = function(a,b,c) {
_gaq.push(['_trackEvent', a, b, c]);
};
}
var pageTracker = new _pageTracker();
in new code to mantain old code in pages.
Here is the code :
onClick="_gaq.push(['_trackEvent', 'pdf', 'download', '/pdf/myPdf'])">myPdf</a>
I needed a way to tack downloading PDFs too and heres what I used:
Download Brochure
For more info about _trackEvent, heres the API Doc page

Categories

Resources