I want to show the user that the document which he wants to access
is loading and not ready yet.
I want to show the web-page when it is fully loaded.
I use
$(document).ready(function(){});
for document ready. What should I do for my approach?
The first thing to do is ask why the page is so slow to load that you feel you need a loading banner, and to do whatever you can to fix that.
If you can't fix that because of the nature of the page in question, the next consideration is making sure that the "Loading" banner only appears for people who have JavaScript enabled (because we're going to remove it later with JavaScript, so it would be a bit mean to put it there and then not remove it if they don't have JavaScript). This may be one of the few valid remaining uses of the document.write statement (and only if you're not using XHTML, because it's not valid in XHTML):
<body>
<script>
document.write("<p id='loading'>Loading...</p>");
</script>
...which you'd style with CSS, presumably:
#loading {
position: absolute;
left: 0px;
top: 0px;
background-color: #ddd;
/* ... */
}
And then in your ready handler, remove it:
$('#loading').remove();
If you're using XHTML (or you just don't want to use document.write on principle), you can do something similar without document.write, along the lines of:
<body>
<script>
(function() {
var p = document.createElement('p');
p.id = 'loading';
p.innerHTML = "Loading...";
document.body.appendChild(p);
})();
</script>
Live example (Tested on IE6/7/8 on Windows; Safari on Windows; and Chrome, Opera, and Firefox on Linux and Windows.)
Write some element with the loading text/animation at the start of the code, then remove or hide that element with javascript on document ready. Some output buffering might be needed to get the loading-message to show up right away.
$(function() {
$("#loading_element").hide();
});
Related
I am trying to replace some text on my sites page using javascript. I must use javascript because the replacement is dependent on the site resolution. However I found that the code bellow doesn't work. Why is it? Does similar things work on iphone (these javascript functions)? Thanks.
<SCRIPT language="JavaScript">
<!--
if ((screen.width<=500))
{
document.body.innerHTML = document.body.innerHTML.replace('text to replace', 'replacement');
}
//-->
</SCRIPT>
The screen property does not have a resize cause it's like they built it in the factory :)
You're probably interested in window.innerWidth
probably you're also interested in listening for a resize event so here you go:
function doOnResize() {
var winW = window.innerWidth;
if(winW <= 500) {
document.body.innerHTML = document.body.innerHTML.replace('text to replace', 'replacement');
}
}
doOnResize(); // Do it as soon as you can
window.addEventListener("resize", doOnResize); // and on window resize
Also make sure to place the above <script> right before the closing </body> tag. This will make sure that the JS parser is in known about the DOM content before searching and replacing text.
Your code does not work because it is executed before the DOM is ready.
window.onload = function() { /* Your code here */ };
This will make sure the DOM is ready and everything is loaded.
What about using css and js (well, jquery would probably be best) to change the display attribute of the element on the event that triggers the text change?
I'm encountering a strange issue. I am developing a books application and using javascript onload. I read somewhere that its best to include your javascript at the end of the html. This works for most of the html loaded. However some complain that onload init() not found. This gets solved if i include the javascript in the html head. But than other htmls start behaving strangely. onload gets called before the page is fully loaded. i dont get the correct scroll width. Please suggest what could be worng. Whats the best way of including javascripts. Thanks
html is as follows
columizer id use css column-width which i've defined like this.
css style below
#columnizer
{
width:290px;
height:450px;
column-width:290px;
column-gap:10px;
word-wrap:break-word;
}
Javascript onload is defined like this.
function init()
{
docScrollWidth = document.getElementById('columnizer').scrollWidth;
document.getElementsByTagName('body')[0].style.width = docScrollWidth + "px";
window.external.notify(str);
}
Since the actual answer was in my comment, I'll add that to my answer:
My guess is that you're doing something like window.onload = init(); instead of window.onload = init; and the init function will have to be declared before you do that assignment. You assign function references without the parens. Using the parens causes it to get executed immediately.
You say you're using this code:
docScrollWidth = document.getElementsByTagName('body')[0].style.width
The main problem with this is that style.width ONLY reads a style attribute set directly on the body object. It doesn't get the width of the object as calculated by layout or CSS rules.
So, what you should use instead really depends upon what you're trying to do. The body width will nearly always be the same or more than the window width unless your content is entirely fixed width. So, that makes me wonder what you're trying to accomplish here? What you should use instead depends upon what you're really trying to do.
FYI, document.body is a direct reference to the body object so you don't need document.getElementsByTagName('body')[0].
First, let me define the problem. The window.onload event is used by programmers to kick-start their web applications. This could be something trivial like animating a menu or something complex like initialising a mail application. The problem is that the onload event fires after all page content has loaded (including images and other binary content). If your page includes lots of images then you may see a noticeable lag before the page becomes active. What we want is a way to determine when the DOM has fully loaded without waiting for all those pesky images to load also.
Mozilla provides an (undocumented) event tailor-made for this: DOMContentLoaded. The following code will do exactly what we want on Mozilla platforms:
// for Mozilla browsers
if (document.addEventListener) {
document.addEventListener("DOMContentLoaded", init, false);
}
So what about Internet Explorer?
IE supports a very handy (but non-standard) attribute for the tag: defer. The presence of this attribute will instruct IE to defer the loading of a script until after the DOM has loaded. This only works for external scripts however. Another important thing to note is that this attribute cannot be set using script. That means you cannot create a script using DOM methods and set the defer attribute – it will be ignored.
Using the handy defer attribute we can create a mini-script that calls our onload handler:
<script defer src="ie_onload.js" type="text/javascript"></script>
The contents of this external script would be a single line of code to call our onload event handler:
init();
There is a small problem with this approach. Other browsers will ignore the defer attribute and load the script immediately. There are several ways round this. My preferred method is to use conditional comments to hide the deferred script from other browsers:
<!--[if IE]><script defer src="ie_onload.js"></script><![endif]-->
IE also supports conditional compilation. The following code is the JavaScript equivalent of the above HTML:
// for Internet Explorer
/*#cc_on #*/
/*#if (#_win32)
document.write("<script defer src=ie_onload.js><\/script>");
/*#end #*/
So far so good? We now need to support the remaining browsers. We have only one choice – the standard window.onload event:
// for other browsers
window.onload = init;
There is one remaining problem (who said this would be easy?). Because we are trapping the onload event for the remaining browsers we will be calling the init function twice for IE and Mozilla. To get around this we should flag the function so that it is executed only once. So our init method will look something like this:
function init() {
// quit if this function has already been called
if (arguments.callee.done) return;
// flag this function so we don't do the same thing twice
arguments.callee.done = true;
// do stuff
};
I’ve provided a sample page that demonstrates this technique.
Let's say I have the following code:
var style = $("<style/>")
.html("body{background:grey; color:white;} /*and more CSS style*/")
.on("load", function () {
console.log("The New style injection has finished to load!");
});
$("head").append(style);
On Chrome, Safari and Firefox browsers the load event triggers on time and works perfectly, exactly as expected.
But on Internet Explorer (any version) it doesn't trigger the load event at all!
Why doesn't it works on IE?
What is the solution for IE (if any)?
An example that works on all browsers except IE, can be found here:
http://jsfiddle.net/KWHyZ/2/
I propose a different way altogether of tackling this problem, though I don't have a page with enough css to test it with.
Rather than waiting for the load event to be fired, which, appears not to happen - why not make the content hidden by default, only making it visible with the added css?
That is to say, the following provides an alert and a message on the console in Chrome, but it's never fired in IE. However, since the (pre-existing) css appears before the <body> tag, page remains 'blank' until the dynamically added css has loaded.
JS
window.addEventListener('load', mInit, false);
function onStyleLoaded()
{
var mStr = "The New style injection has finished to load!";
console.log(mStr);
alert(mStr);
}
function mInit()
{
var style = newEl('style');
style.addEventListener('load', onStyleLoaded, false);
style.innerHTML = ".styleMe{font-weight: bold; color: red;} body{visibility:visible;}";
document.head.appendChild(style);
}
CSS
body
{
visibility: hidden;
}
HTML
<body>
<div class='styleMe'>Style this stuff!</div>
</body>
If you're adding only a couple of CSS rules - do them individually:
$('body').css({background:'#000', color:'#fff'});
$('#element').css({color:'#000', textDecoration:'underline'});
//etc...
If you're adding a bunch of stuff, then create a stylesheet and load it dynamically onto the page:
$('<link/>')
.attr('href','http://example.com/urltostylesheet.css')
.attr('rel','stylesheet')
.attr('type','text/css')
.appendTo($('head'))
.on('load',function() {
// do stuff
});
Normally, when a page is loaded, and the browser has Javascript disabled, we use the <noscript> tag to write something like a warning and tell the client to enable Javascript. However, Facebook, even after you load the page with JS enabled, the moment it's disabled you get a notification. How can I do something like this?
UPDATE : This mechanism is no longer available in Facebook, but it was before, I was too late in asking this question, but if any answer is found, I would really appreciate it.
What I have tried
I thought about having a segment inside my page which keeps checking if Javascript is disabled, if yes, show the contents of <noscript>.
To Achieve this, I created a page CheckJS.html.
<!DOCTYPE html>
<html>
<head>
<meta http-equiv="refresh" content="0">
</head>
<body>
<noscript>
JS is disabled!
</noscript>
</body>
</html>
This page will keep on refreshing, when JS is disabled, JS is disabled! will appear.
To add this page inside my original page. I tried the following:
1- .load()
I used JQuery to .load('CheckJS.html') inside a div. However, it seems that .load() only loads the contents of the <body> of CheckJS.html. Means the <head> element and what's inside it will not be loaded inside the div.
2- iframe
After some searching, I found that the only possible way to load a FULL html page including <head> is to use an <iframe>.
<iframe src="CheckJS.html"></iframe>
However, the <meta http-equiv="refresh" content="0"> of CheckJS.html affects the parent page, the original page itself started refreshing.
If we are able to use this <iframe> without forcing the original page to refresh, then this could be a solution, but even if this solution is found, I feel its more of a trick rather than a real solution.
UPDATE
Antony 's answer proved that I was wrong about that the iframe refreshes the original page, the browser shows that its refreshing but actually its not, if this is it, then Javascript can be avoided, the CheckJS.html that I provided does the job, and even better, the <noscript> will be hidden when JS is re-enabled. Still this whole iframe approach isn't so user friendly (could freeze the browser), unless refresh occurs every 10 seconds or so, which isn't an instant detection.
CSS Solution
See DEMO. Also available as a JS library.
Stop the CSS animation by continuously replacing the element with JavaScript. Once JavaScript is disabled, the CSS animation kicks in and displays a message.
#keyframes Browser compatibility: Chrome, Firefox 5.0+, IE 10+, Opera 12+, Safari 4.0+
<style>
.nojs_init {
position: relative;
animation:nojs-animation 0.2s step-end;
-moz-animation:nojs-animation 0.2s step-end; /* Firefox */
-webkit-animation:nojs-animation 0.2s step-end; /* Safari and Chrome */
-o-animation:nojs-animation 0.2s step-end; /* Opera */
}
#keyframes nojs-animation
{
from {visibility:hidden;opacity:0;}
to {visibility:visible;opacity:1;}
}
#-moz-keyframes nojs-animation /* Firefox */
{
from {visibility:hidden;opacity:0;}
to {visibility:visible;opacity:1;}
}
#-webkit-keyframes nojs-animation /* Safari and Chrome */
{
from {visibility:hidden;opacity:0;}
to {visibility:visible;opacity:1;}
}
#-o-keyframes nojs-animation /* Opera */
{
from {visibility:hidden;opacity:0;}
to {visibility:visible;opacity:1;}
}
</style>
<body>
<div id="content"></div>
<div id="nojs" class="nojs_init"><noscript>JavaScript is <span style="font-weight:bold;">disabled</span>.</noscript></div>
</body>
<script>
document.getElementById("content").innerHTML = 'JavaScript is <span style="font-weight:bold;">enabled</span>. Try disabling JavaScript now.';
var elm = document.getElementById("nojs"),
animation = false,
animationstring = 'animation',
keyframeprefix = '',
domPrefixes = 'Webkit Moz O ms Khtml'.split(' '),
pfx = '';
if( elm.style.animationName ) { animation = true; }
if( animation === false ) {
for( var i = 0; i < domPrefixes.length; i++ ) {
if( elm.style[ domPrefixes[i] + 'AnimationName' ] !== undefined ) {
pfx = domPrefixes[ i ];
animationstring = pfx + 'Animation';
keyframeprefix = '-' + pfx.toLowerCase() + '-';
animation = true;
break;
}
}
}
// Continuously replace element
function jsdetect() {
var elm = document.getElementById("nojs");
var newone = elm.cloneNode(true);
elm.parentNode.replaceChild(newone, elm);
}
// Only apply to browsers that support animation
if (animation) {
elm.innerHTML = 'JavaScript is <span style="font-weight:bold;">disabled</span>.';
setInterval(jsdetect, 0);
}
</script>
Hrm, I think it depends on the browser. HTML5 supports <noscript> in the HEAD element, so you might try something like this:
<style>
.noscriptMessage {
display: none;
}
</style>
<noscript>
<style>
.noscriptMessage {
display: block
}
</style>
</noscript>
<body>
<div class=".noscriptMessage">Foo bar baz</div>
...
</body>
Spec: http://dev.w3.org/html5/markup/noscript.html
From the spec:
Permitted contents: Zero or more of: one link element, or one meta
http-equiv=default-style element, or one meta http-equiv=refresh
element, or one style element
Edit: hey peeps, SO does the very same! Just try turning off JS now.
What about javascript code that continuously postpones a http-equiv=refresh (each time replacing the meta element?) As soon as javascript is turned off, the meta element is no longer replaced and the refresh will eventually take place. This is just a thought, I've no idea if meta element insertion is even possible.
I'd recommend looking into how this is done by HTML5 Boilerplate and Modernizr.
If you look at HTML5 Boilerplate's HTML, on line 7 you'll see the <html> tag is given a class of no-js. Then, when Modernizr's JavaScript runs, the first thing it does is remove the no-js class.
That done, you could apply CSS rules that only display content if the no-js class is present:
#no-script-message {
display: none;
}
.no-js #no-script-message {
display: block;
}
Expanding upon #JoshMock's answer, here is a simple approach (via Paul Irish) to detect if the client has JS enabled:
HTML
<html class="no-js">
<head>
<script>(function(H){H.className=H.className.replace(/\bno-js\b/,'js')})(document.documentElement)</script>
This should be compatible with all browsers and is quite fast. Then you can hide/show elements in your css with .js and .no-js classes.
If you are doing any other feature detection, I would suggest using Modernizr with the html class="no-js" markup (modernizr will automatically add the js classes for you, along with css3 detection).
Actually, it is easier to detect if java-script is supported by the browser than the opposite.
Of course, this is in the case of 'a site instantly detect javascript'. Witch is the very first http-request <--> response from the browser to the server. You just 'cannot'. You would have to send another request to the server after determining browser capabilities.
Now, there is no way of checking if JavaScript is enabled from the server-side on the first request. So, if JavaScript is disabled, you have to do a postback, or redirect to a non JavaScript page, using what some other suggested (witch is not valid, but seems to work):
<head>
<noscript><meta http-equiv="refresh" content="0; url=whatyouwant.html"></noscript>
...
</head>
There are some 'browser capabilities' and browser 'plugins' that can be get with http request, so you would need a good 'server-side' script to meet your goal.
See browserhawk or quirksmode for some infos on a javascript to detect browser.
Also, there is a 'protected' question aboout how-to-detect-if-javascript-is-disabled
I'm looking for a way to remove the entire content of a web page using pure Javascript -- no libraries.
I tried:
document.documentElement.innerHTML = "whatever";
but that doesn't work: it replaces the inside of the <html/> element. I'm looking at replacing the entire document, including if possible the doctype and <?xml declaration.
I think a browser rightfully assumes a page with content-type text/html will always be a web page - so whilst you may do something like...
document.body.innerHTML = '';
It will still have some HTML hanging around.
You could try...
document.documentElement.innerHTML = '';
...which left me with <html></html>.
Yi Jiang did suggest something clever.
window.location = 'about:blank';
This will take you to a blank page - an internal mechanism provided by most browsers I believe.
I think however the best solution is to use document.open() which will clear the screen.
var i = document.childNodes.length - 1;
while (i >= 0) {
console.log(document.childNodes[i]);
document.removeChild(document.childNodes[i--]);
}
Removes everything (doctype also) on FF 3.6, Chrome 3.195, and Safari 4.0. IE8 breaks since the child wants to remove its parent.
Revisiting a while later, could also be done like this:
while (document.firstChild) {
document.removeChild(document.firstChild);
}
According to Dotoro's article on the document.clear method, they (since it's deprecated) recommend calling document.open instead, which clears the page, since it starts a new stream.
This way, you avoid the nasty about:blank hack.
One can remove both the <html> element (document.documentElement) and the doctype (document.doctype).
document.doctype.remove();
document.documentElement.remove();
Alternatively, a loop can be used to remove all children of the document.
while(document.firstChild) document.firstChild.remove();
document.open() or document.write() work as well.
After the page has already fully loaded:
document.write('');
document.close();
I believe this will do it
document.clear() //deprecated
window.location = "about:blank" //this clears out everything
I believe this will still leave the doctype node hanging around, but:
document.documentElement.remove()
or the equivalent
document.getElementsByTagName("html")[0].remove()
document.documentElement.innerHTML='';
document.open();
The Document.open() method opens a document for writing.
if you dont use open method, you cant modify Document after set innerhtml to empty string
Live demo
If youre using jQuery here's your solution
<div id="mydiv">some text</div>
<br><br>
<button id="bn" style="cursor:pointer">Empty div</button>
<script type="text/javascript">
$(document).on('click', '#bn', function() {
$("#mydiv").empty();
$("#bn").empty().append("Done!");
});
</script>
If youre using javascript here's your solution
<div id="purejar">some text</div>
<br><br>
<button id="bnjar" onclick="run()" style="cursor:pointer">Empty div</button>
<script type="text/javascript">
var run = function() {
var purejar = document.getElementById("purejar");
var bn = document.getElementById("bnjar");
purejar.innerHTML = '';
bn.innerHTML = 'Done!';
}
</script>
Im just curious as to why you'd want to do that. Now theres no way that I know of to replace absolutely everything down to the doctype declaration but if you are wanting to go to those lengths why not redirect the user to a specially crafted page that has the template you need with the doctype you need and then fill out the content there?
EDIT: in response to comment, what you could do is strip all content then create an iframe make it fill the entire page, and then you have total control of the content. Be aware that this is a big hack and will probably be very painful - but it would work :)
REMOVE EVERYTHING BUT --- !DOCTYPE html ---
var l = document.childNodes.length;
while (l > 1) { var i = document.childNodes[1]; document.removeChild(i); l--; }
TESTED ON FIREFOX WEB INSPECTOR - childNodes[1] IS --- !DOCTYPE html ---