hide body until external resources(loaded asynchronously) load - javascript

So, I have various external resources like google material icons and so on which are loaded using the link and script tags:
<link href="https://fonts.googleapis.com/icon?family=Material+Icons" rel="stylesheet">
<link href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.4.0/css/font-awesome.min.css" rel="stylesheet" type="text/css">
How can I hide the body until all these resources(loaded via link and script) are loaded completely? Can I do this using custom directives? And also, I am NOT using jQuery.
EDIT:
The reason I want this is that google's material design icons are included in the following way:
<i class="material-icons">
visibility
</i>
So, while the material icons css is still loading, I can see all these icon texts, 'visibility' in my case on the screen in their textual form. And, only when the css loads, does the text translate to icon form. I'll add a screenshot soon.

Hide your body in our CSS, and show it when the event DOMContentLoaded is triggered
JAVASCRIPT
document.addEventListener("DOMContentLoaded", function(event) {
document.body.style.display = 'block';
});
CSS
body {
display:none;
}

Just add display:none for body tag in header :-
<html>
<head>
<style>
body{
display: none;
}
</style>
/* Load all your external CSS and JS */
</head>
<body>
<script>
$(document).ready(function(){
$(body).css("display", "block");
})
</script>
</body>
</html>
It may help you.

Using this: https://github.com/typekit/webfontloader
Will output a class to HTML tag while loading fonts, this way:
.wf-loading
.wf-active
.wf-inactive
.wf-<familyname>-<fvd>-loading
.wf-<familyname>-<fvd>-active
.wf-<familyname>-<fvd>-inactive
With that you can do anything from html > to any other tag, body for example, so:
.wf-loading body{display:none;}
.wf-active body{display:block;}
Also you have callbacks to use via js, take a look, it´s working: http://fiddle.jshell.net/m2d6k8er/ it´s just a very basic example of course.

Edit 2
OP's issue concerning loading external scripts may need further testing with async and defer attributes. The following links will help in that direction:
Async and Defer (non-blocking JavaScript with HTML5)
JavaScript Execution Order; Asynchronous JavaScript
Promises - Thinkster
In 3 Minutes, JavaScript Loading of Scripts
MDN
Deep dive into the murky waters of script loading
Here's the JS equivalent of Harsh's code (if placed at the closing </body> tag):
EDIT 1
delayedBy(ms) is triggered by the onload event of <body>. You can adjust the delay.
function delayedBy(ms) {
setTimeout('visible()', ms);
}
function visible() {
var body = document.getElementsByTagName("body")[0];
body.style.visibility = "visible";
}
body {
visibility: hidden;
}
<body onload="delayedBy(1000);">
<h1>Here I am!</h1>
</body>

Related

Define specific CSS-style only if JavaScript is enabled

My webpage contains a DIV. If Javascript is enabled, I want the DIV to be invisible (display: none;) when the page loads. If JS is disabled, I want it to be visible (display: block;).
I can do:
document.write('<div style="display:none;">...</div>');
or
document.getElementById('foo').style.display = 'none';
With the first code there won't be a DIV if JS is disabled. With the second, the DIV will be visible when the page loads and disappear when the JS is executed.
I'm too stupid to solve this.
Can I put JavaScript inside the <div>-tag to write only the style? Certainly not like this:
<div <script>document.write('style="display:none;"');</script>>
Maybe something like:
<div onLoad="document.write('<div style="display:none;">...</div>');">
Does someone have an idea?
One problem with displaying an element unless JS hides it is that, even with JS on, the element is likely to display until the JS kicks in. So it's often better to have some JS at the top of the file that adds a class to the root element straight away, to get in before the CSS loads. Here's a simple example (in my noob JS):
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<script>
(function() {
var root = document.querySelector('html');
root.className = "js";
}());
</script>
<style media="all">
div {width: 500px; height: 200px; background: blue;}
.js div {display: none;}
</style>
</head>
<body>
<div></div>
</body>
</html>
This is much better than using oldfashioned <noscript> and document.write() etc.
EDIT: I should just note that an easier way to target the html element is with document.documentElement. Thus, the code above could be written as—
<script>
(function() {
document.documentElement.className = "js";
}());
</script>
Why don't you just put the <div> in a <noscript>?
<noscript><div style="display:none;">...</div></noscript>
Now you don't even have to use Javascript to deal with it.

Hide everything on dom until everything is loaded

I am trying to change the content of a div on the page but the page has a lot of things to load and on slower computers there is a flicker where you can see the div changing (changing through jquery btw). Is there anyway that everything can be hidden and display it all at including the changes I made using jquery?
I had a similar issue with my web application.. This is what I did
Hide body in HTML
<body style="display:none">
And write this script :
$(window).bind("load", function() {
$("body").fadeIn(100);
});
OR this script
$(window).load(function () {
$("body").fadeIn(100);
}
This creates beautiful effect and shows the page ONLY after everything is fully loaded..
Perhaps you could do something like
<head>
<style>
body{
display:none;
}
</style>
</head>
<body>
flickery <div></div>s go here
</body>`
And your script
$(window).load(function(){
$(document.body).css("display","block"); //shows it when all the elements are ready for presentation
});

TypeError is Null?

This is an error in Firebug I keep seeing.
TypeError: $("#gallery-nav-button") is null
[Break On This Error]
$('#gallery-nav-button').addClass('animated fadeOutRightBig');
Here is my code:
JS
$(function() {
$("#close-gallery-nav-button").click(function() {
$('#gallery-nav-button').addClass('animated fadeOutRightBig');
});
});
HTML
<div id="gallery-nav-button">
<h4 id="close-gallery-nav-button">X</h4>
<h3 class="text-center small-text"><a class="inline text-center small-text" href="#gallery-nav-instruct">Click Here for Gallery <br /> Navigation Instructions.</a></h3>
</div>
CSS
#close-gallery-nav-button{
text-indent:-9999px;
width:20px;
height:20px;
position:absolute;
top:-20px;
background:url(/images/controls.png) no-repeat 0 0;
}
#close-gallery-nav-button{background-position:-50px 0px; right:0;}
#close-gallery-nav-button:hover{background-position:-50px -25px;}
I also want to add - because this is the #1 Google search result for the important error message "TypeError: [x] is null" - that the most common reason a JavaScript developer will get this is that they are trying to assign an event handler to a DOM element, but the DOM element hasn't been created yet.
Code is basically run from top to bottom. Most devs put their JavaScript in the head of their HTML file. The browser has received the HTML, CSS and JavaScript from the server; is "executing"/rendering the Web page; and is executing the JavaScript, but it hasn't gotten further down the HTML file to "execute"/render the HTML.
To handle this, you need to introduce a delay before your JavaScript is executed, like putting it inside a function that isn't called until the browser has "executed" all of the HTML and fires the event "DOM ready."
With raw JavaScript, use window.onload:
window.onload=function() {
/*your code here*
/*var date = document.getElementById("date");
/*alert(date);
}
With jQuery, use document ready:
$(document).ready(function() {
/*your code here*
/*var date = document.getElementById("date");
/*alert(date);
});
This way, your JavaScript won't run until the browser has built the DOM, the HTML element exists (not null :-) ) and your JavaScript can find it and attach an event handler to it.
I have several scripts running on this page and evidently one script was conflicting with another. To solve my issue I added jQuery.noConflict();
var $j = jQuery.noConflict();
$j(function() {
$j("#close-gallery-nav-button").click(function() {
$j('#gallery-nav-button').addClass('animated fadeOutRightBig');
});
});
As additional comment on #1 solution:
Another possibility for loading the script after finishing/building the HTML should be placing a defer parameter inside the script tag:
<script defer type="text/javascript" src="x.js"></script>
I agree with the advice given above, relating to the onload event. https://stackoverflow.com/a/18470043/2115934
A more simple solution (though not necessarily a better one) is to put your script tag just before the closing body tag of the document.
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Document</title>
</head>
<body>
<h1></h1>
<p></p>
<script src="script.js" type="text/javascript"></script> <!-- PUT IT HERE -->
</body>
</html>
I know this has been answered and it is an old post but wanted to share my experience. I was having the hardest time getting my code to load and was getting this error constantly. I had my javascript external page loading in the head section. Once I moved it to just before the body ended the function fired up right away.

Is it possible to use Bootstrap without it taking over the entire style?

Is there an easy way to use Bootstrap in an existing project?
Currently it adds styles for table,a etc. which messes up everything in the page.
I really love the modal window, some buttons, but I don't want to hunt bootstrap css all the time to switch items back to default styles.
Bootstrap 3 // Less 1.4.0 edit:
After Bootstrap 3 and Less 1.4.0 has come out, bootstrap has started using the :extend() pseudo selector. This means that certain things will fail in the original code I've posted (you'll get some .bscnt .bscnt form-horizontal code which means you have to nest two divs inside eachother, which is just dumb). The easy way to fix this is to remove the first two lines from bootstrap.less (#import variables.less and #import mixins.less) and instead import these files outside of the .bs-cnt scope:
#import "variables.less";
#import "mixins.less";
.bscnt {
#import "bootstrap.less";
}
You can also download bootstrap from here: Bootstrap source and then enter the "less" directory and add a file called "bootstrap-custom.less" where you'll enter the following content:
.bs-cnt {
#import "bootstrap.less";
}
"bs-cnt" for BootStrap-CoNTainer. You can make it longer if you want, but remember that it'll be pasted in a lot of places in the compiled CSS, so it's to save space in the end file.
After you've done this, simple compile the bootstrap-custom.less file with your favourite less compiler (SimpLESS is pretty good if you're on Windows), and then you'll have a compiled bootstrap file that only works when you place a container element with the class of "bs-cnt".
<div class="bs-cnt">
<button class="btn btn-success btn-large">This button will be affected by bootstrap</button>
</div>
<button class="btn btn-danger">This however; Won't</button>
You can use the "customize" feature on the bootstrap website to get only those features you want: Twitter Bootstrap Download Page. Most of bootstrap's rules are explicit. You'll probably only want to leave out the reset rules which are implicit by default.
I think the link in answered section is not already updated. Here is where you can customize your Bootstrap directly on GetBootstrap site:
Customize and download - GetBootstrap
Using IFrame
Just make one html document with bootstrap in it, have your bootstrap element that you want on that page, and use Iframe to get it on the other one..
element_name.html
<!DOCTYPE html>
<html lang="en">
<head>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.1/js/bootstrap.min.js"></script>
<title>Element</title>
</head>
<body>
<!--Code for the actual element-->
</body>
</html>
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<style>
iframe {
border: none;
}
</style>
</head>
<body>
<iframe src="element.html"></iframe>
<!--Other stuff on the page-->
</body>
</html>
The element in the element.html will be integrated in the index.html like it's own element, without even importing a single bootstrap stylesheet in the index.html and there is no need to make custom bootstraps, which can be tedious.
You can tag the styles you want to not get overwritten by a special tag. Just put the !important tag. It can take a long time to paste it after every line of code but it'll be worth the time. Or you can use the bootstrap.css file instead of the bootstrap link and delete all the styles that are overriding your styles. You can download the bootstrap css file here

YUI Calendar: how does it load the Sam's Skin CSS?

I'm using YUI 2's calendar in YUI 3. How does it load Sam's skin CSS?
I didn't manually include it (though it seems like I should so the user can download it in the one request I make to the combo loader for css). Strangely, I don't see it being downloaded nor do I see it in the JS files themselves. I must be overlooking it. This is how I'm loading the CSS and JS now:
<head>
...
<link rel="stylesheet" type="text/css" href="http://yui.yahooapis.com/combo?3.1.0/build/cssreset/reset.css&3.1.0/build/cssfonts/fonts.css&3.1.0/build/cssbase/base.css"/>
...
</head>
...
<!--and at the end of the body tag:-->
<script type="text/javascript" src="http://yui.yahooapis.com/combo?3.1.1/build/yui/yui-min.js&3.1.1/build/oop/oop-min.js&3.1.1/build/event-custom/event-custom-base-min.js&3.1.1/build/event/event-base-min.js&3.1.1/build/json/json-parse-min.js&3.1.1/build/querystring/querystring-stringify-simple-min.js&3.1.1/build/io/io-base-min.js&3.1.1/build/dom/dom-base-min.js&3.1.1/build/dom/selector-native-min.js&3.1.1/build/dom/selector-css2-min.js&3.1.1/build/node/node-base-min.js&3.1.1/build/node/node-style-min.js&3.1.1/build/stylesheet/stylesheet-min.js&2in3.1/2.8.0/build/yui2-calendar/yui2-calendar-min.js&2in3.1/2.8.0/build/yui2-yahoo/yui2-yahoo-min.js&2in3.1/2.8.0/build/yui2-dom/yui2-dom-min.js&2in3.1/2.8.0/build/yui2-event/yui2-event-min.js"></script>
<script type="text/javascript">//<![CDATA[
YUI().use('yui2-calendar', function(Y) {
var YAHOO = Y.YUI2;
var cal = new YAHOO.widget.Calendar("cal",{navigator:true,mindate:'1/1/2000');
cal.render();
// ...
Edit:
I want to make a few minor changes to the default sam skin. What is the best way to do that?
I answered this part of my question. If I wrap the calendar in an extra div, then specifying CSS rules which include that div as part of the selector makes the rule more specific so the browser uses it over Sam's skin. Rough example:
<style type="text/css">
.magic .yui-skin-sam .yui-calendar td.calcell {
height: 10em;
width: 15em;
}
</style>
...
<div class="magic">
<div class="yui-skin-sam">
<div id="cal"></div>
</div>
</div>
http://yuilibrary.com/forum/viewtopic.php?f=93&t=2269&p=7608&hilit=insertbefore#p7608
That thread contains information about using the insertBefore configuration, which allows you to ensure that the YUI CSS is inserted above your style overrides in the CSS cascade.
-Eric

Categories

Resources