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
Related
I have built a mobile webapp in html/js and I am using the 'window.onerror' to track client side js errors and report them to the server.
Recently I noticed that I receive many reports of ScriptError on line 0.
A quick google search brought me to discussions like Cryptic "Script Error." reported in Javascript in Chrome and Firefox and https://ravikiranj.net/posts/2014/code/how-fix-cryptic-script-error-javascript/
For most people such errors seem to be triggered by failures in scripts that are included from a foreign origin. But unfortunately that's not the case for me.
After many hours of debugging I came up with the following minimal example to reproduce the error:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Test</title>
<meta name="google" content="notranslate"/>
<script type="text/javascript">
function init() {
window.onerror = function() {
alert(JSON.stringify(arguments));
}
}
</script>
</head>
<body onload="init()">
<h1>Hello</h1>
<svg width="300" height="300">
<a href="#">
<rect x="50" y="50" width="200" height="200" />
</a>
</svg>
<p>
Link
</p>
</body>
</html>
As we can see it's a simple html page with no javascript at all except for the onerror handler itself.
In Safari (ios 12.4.1) no error is triggered. But in both Google Chrome for iOS and Firefox for iOS a ScriptError on line 0 is reported each time the link inside the <svg> element is tapped - but not when tapping the link outside the <svg>. Note that no js event handler is attached to the <svg>.
A live version of the code is online at https://static.laszlokorte.de/scripterror.php
I know that all third party browsers on iOS actually just use safari under the hood extending in with a few custom features. I suspect that those custom features cause the error but I have no idea how to track it down further.
Why does clicking a link inside a plain svg element causes an error in iOS Chrome and Firefox but not in Safari? Is there a way to connect the Safari Webdev tools to mobile browsers other than native Safari?
Update
After taking a deeper look at both the Chrome(iOS) and Firefox(iOS) source code I now found the cause of the problem. Both browsers inject javascript code that runs on touchstart and processes the event's target node. Both browsers check if an '' or '' element has been touched and try to access their their href or src attribute respectively. They both then try to send the attributes values via webkit.postMessage to the host application.
The error seems to be caused by the fact that an <a> element inside an <svg> is actually an SVGAElement and it's href attribute is not a String but an SVGAnimatedString which (other than String) can not be cloned to be sent to another process.
The corresponding code for Firefox can be found here:
https://github.com/mozilla-mobile/firefox-ios/blob/826cb396a9eb225b7eb667b47b245e2d98d26ed8/Client/Frontend/UserContent/UserScripts/AllFrames/AtDocumentEnd/ContextMenu.js#L14-L35
The code for Chrome is here:
https://github.com/chromium/chromium/blob/master/ios/web/web_state/js/resources/all_frames_context_menu.js#L136-L139
So for Chrome the solution is actually simple because it allows to explicitly opt-out of all this by setting the css property -webkit-touch-callout: none (You can see the check for that in the linked file). For example like this:
#namespace svg url(http://www.w3.org/2000/svg);
svg|a {
-webkit-touch-callout: none;
}
For Firefox I have not found a easy solution yet.
Update 2
For Firefox I now came up with the following monkey patch solution:
(function() {
var origClosest = SVGElement.prototype.closest;
SVGElement.prototype.closest = function (sel) {
var c = origClosest.apply(this, arguments);
if(c && sel === 'a' && c.namespaceURI === this.namespaceURI) {
return c.parentNode && c.parentNode.closest(sel);
} else {
return c;
}
};
})();
I override the closest method (that Firefox itself uses to find the touched <a>) on an SVG elements with my own method that skips all <a> elements that belong to the SVG namespace.
Additionally I submitted an issue in the Firefox repo at Github and an issue for Chromium.
There is an HTML file with many embedded YouTube videos.Page load times were slow so I decided to use this JS file to force the page load an image instead of iframe, until the user clicks on it. http://www.skipser.com/p/2/p/youtube-video-embed-like-google-plus.html
CSS checks if the visitor uses mobile and optimizes the layout for mobile.I modified the above mentioned JS script to show smaller thumbnails so it will work better on mobile(no need to scroll horizontally).I have 2 version of that JS script now.
The goal: Check if visitor uses desktop.If yes, execute the regular gplus-youtubeembed.js.If visitor uses mobile then execute gplus-youtubeembed-mobile.js
This was the original HTML.It would only load the desktop version of JS.As a result, mobile visitors would see a very large video thumbnail.
<!DOCTYPE html>
<html>
<head>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<meta name="viewport" content="width=device-width; initial-scale=1.0; user-scalable=yes">
<script src=gplus-youtubeembed.js></script>
<link rel=stylesheet type="text/css" href="css/style.css" media=screen />
<title>Page Title</title>
</head>
<body>
<h1>My First Heading</h1>
<p>My first paragraph.</p>
<script>optimizeYouTubeEmbeds()</script> <!--needed to load image instead of iframe-->
</body>
</html>
Then I used this method http://www.coalmarch.com/blog/how-to-execute-javascript-based-on-screen-size-using-jquery
if ( $(window).width() > 700) {
//added the content of gplus-youtubeembed.js here
}
else {
//added the content of gplus-youtubeembed-mobile.js here
}
I named that gplus-youtubeembed-combine.js and replaced gplus-youtubeembed.js with gplus-youtubeembed-combined.js , in the HTML doc.
The outcome: The only JS that gets executed is the mobile version.Desktop visitors see small thumbnails.Everyting works fine in mobile.Why doesn't the gplus-youtubeembed-combined.js work properly ? It's supposed to detect if the screen width is over 700 and execute the gplus-youtubeembed.js file but it doesn't.Any help is appreciated.Thanks !
From what I understand
if ( $(window).width() > 700) {
//added the content of gplus-youtubeembed.js here
}
else {
//added the content of gplus-youtubeembed-mobile.js here
}
works only when a window is first loaded or refreshed. Try changing the size of your window and refresh your page. If the code works, you'll need something to reload the script or the page on resize.
Something like this:
$(window).resize(function() {
// add the stuff here to execute the your slider again;
});
or this might do the trick:
<script>
function refresh() { location.reload(); }
</script>
<body onresize="refresh()">
I'm no expert but I had similar issue just a few minutes ago. Hope I helped.
Here is a little more detail on the second code that you asked for.
I'm only sharing with you what I'm learning as I go. I'm a real noob. Having the same problem as you but with a different snippet.
$(document).ready(function(){
$(window).on('resize', function(){
if ($(window).width() > 700) {
// code here
} esle {
// code here
}
});
});
But you said refreshing your page didn't make the JS run. Which means this method might not help you. Have you checked to make sure both JS run and work regardless of page width? Maybe test each JS individually to make sure the mobile version is good.
Sorry if I can't be much help to you. I'm learning as I try to solve my own issues. Thought yours was close to the issue I was having.
Problem was fixed.When I copy/pasted two JS files into the if/else statement, something broke the "if" statement so "else" was always being executed.I confirmed this by swapping the mobile and desktop versions and changing ">" to "<".In that case only desktop version would load.
Instead of copy/pasting the entire JS files into else/if, I left the common part out and added only the portion that was different in desktop/mobile version.Sounds simple, but it didn't come to my mind at the beginning.
The author of the original JS did not provide the mobile friendly version of the JS so people who use that code on their website might benefit from this post.One issue with the below code is that on mobile version, the image doesn't have a play button.It only has a thumbnail so make sure the visitor knows it's a video.This can be fixed by further tweaking the code but that's another topic.
Working version.
gplus-youtubeembedded-combine.js
// gplus-youtubeembed - Makes embedded YouTube video iframes Google+ style to improve page loading speed.
// Copyright (c) 2013 by Arun - http://www.skipser.com
// Licensed under the GNU LGPL license: http://www.gnu.org/copyleft/lesser.html
// For usage details, read - http://www.skipser.com/510
// Call this function at the end of the closing </body> tag.
function optimizeYouTubeEmbeds() {
// Get all iframes
var frames = document.getElementsByTagName( 'iframe' );
// Loop through each iframe in the page.
for ( var i = 0; i < frames.length; i++ ) {
// Find out youtube embed iframes.
if ( frames[ i ].src && frames[ i ].src.length > 0 && frames[ i ].src.match(/http(s)?:\/\/www\.youtube\.com/)) {
// For Youtube iframe, extract src and id.
var src=frames[i].src;
var p = /^(?:https?:\/\/)?(?:www\.)?(?:youtu\.be\/|youtube\.com\/(?:embed\/|v\/|watch\?v=|watch\?.+&v=))((\w|-){11})(?:\S+)?$/;
var id=(src.match(p) ? RegExp.$1 : false);
if(id == false) { continue;}
// Get width and height.
var w=frames[i].width;
var h=frames[i].height;
if(src == '' || w=='' || h=='') {continue;}
if ( $(window).width() > 700) {
// Thease are to position the play button centrally.
var pw=Math.ceil(w/2-38.5);
var ph=Math.ceil(h/2+38.5);
// The image+button overlay code.
var code='<div alt="For this Google+ like YouTube trick, please see http://www.skipser.com/510" style="width:'+w+'px; height:'+h+'px; margin:0 auto"><img src="http://i.ytimg.com/vi/'+id+'/hqdefault.jpg" style="width:'+w+'px; height:'+h+'px;" /><div style="background: url(\'data:image/png;base64,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\') no-repeat scroll 0 0 transparent;height: 77px;width: 77px; position:relative; margin-left:'+pw+'px; margin-top:-'+ph+'px;z-index:5;"></div></div>';
}
else {
var pw=Math.ceil(w/7.5-1.5);
var ph=Math.ceil(h/4.7+10);
var code='<div alt="For this Google+ like YouTube trick, please see http://www.skipser.com/510" style="max-width:100%;height:auto; margin:0 auto"><img src="http://i.ytimg.com/vi/'+id+'/hqdefault.jpg" style="max-width:100%;height:auto;" /> <div style="background: url(\'data:image/png;base64,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\') no-repeat scroll 0 0 transparent;height: 77px;width: 77px; position:relative; margin-left:'+pw+'px; margin-top:-'+ph+'px;z-index:5;"></div><br><br><br></div>';
}
// Replace the iframe with a the image+button code.
var div = document.createElement('div');
div.innerHTML=code;
div=div.firstChild;
frames[i].parentNode.replaceChild(div, frames[i]);
i--;
}
}
}
// Replace preview image of a video with it's iframe.
function LoadYoutubeVidOnPreviewClick(id,w ,h) {
var code='<iframe src="https://www.youtube.com/embed/'+id+'/?autoplay=1&autohide=1&border=0&wmode=opaque&enablejsapi=1" width="'+w+'" height="'+h+'" frameborder=0 allowfullscreen style="border:1px solid #ccc;" ></iframe>';
var iframe = document.createElement('div');
iframe.innerHTML=code;
iframe=iframe.firstChild;
var div=document.getElementById("skipser-youtubevid-"+id);
div.parentNode.replaceChild( iframe, div)
}
I've implemented the code here (it's my website) http://www.veryslowpc.com/security-measures.html
The outcome: in order to reduce page load times, embedded video iframes don't load until the user clicks on them, and the thumbnails are within page width when viewed on mobile.
Thank you for suggestions.
EDIT: The code should display the play button now.
I know this question won't be well received but I searched far and long and can't find anything, probably not using the right keywords.
I own an online radio station and I want to create a js player that once added to a website will stay in the header on all the domains of the site. I first saw this thing on a tumblr music player(http://scmplayer.net/) , you would add their code to your page and once opened the player will stay as a header even if you browse to other sub-pages of your blog.
I'm searching for this to use in forums, where you change your page so often you can't listen to anything using a built-in radio player.
I found a similar solution by using a button that opens a really small pop-up with the player, but I'd like to know if it's possible to do what I want, and how.
Even a right link, query or term to search for would help me greatly, I don't want someone to do this for me, just point me in the right way.
Edit::
Here's some stuff I forgot to mention. I'm trying to build a code users can just copy paste into their website and have it work.
If it was only for me, I wouldn't be here, since I went trough iframes and jquery to load content too(see www.r4ge.ro).
I can't expect other people to tamper with their website only to embed my radio there, and I can't iframe their site content and add my radio as an index because that would ruin google ranking and indexing.
There are multiple ways of doing this, here goes one!
First thing, I'd personally use backbone.js - backbone.js allows you to create 'partial' views that can be updated independently of another. For your scenario, it seems ideal to create a header view and then a content view.
Both the header and the content could have their own logic, and update at separate times that you specify and under your control.
Take a look at http://backbonetutorials.com/why-would-you-use-backbone/ to get started. prepare yourself ample time to do a lot of reading and following tutorials. Backbone takes time to ramp up on, but once you get it, you'll be making some awesome apps!
You basically have three options:
The one you found, opening a really small pop-up (perhaps with just the media controls visible), so that when the user navigates, it isn't affected by the page being torn down.
The same thing using frames.
The same thing using ajax to load content when navigating instead of actually navigating.
As you didn't like #1 much, let's look at #2, then come back to #3.
When the use opens the player, you'd really be going to a page with the player and a very large iframe with the rest of the content:
<!doctype html>
<html>
<head>
<!-- ... -->
</head>
<body>
<!-- player here -->
<iframe class="main" src="main.html"></iframe>
</body>
</html>
You'd use CSS to make that as seamless as you could. To make it linkable, you could use a large fragment in the URL which is the URL of the page that should go in the frame, e.g.:
http://example.com/#forum.html§ion=23
When your main page loads, you grab the fragment, and use it as the src on the iframe.
You can listen for navigation events on the iframe and update the hash fragment on the main window, so that bookmarks work, and/or have JavaScript on each page of your site that might be navigated to that tells the container page (parent) what its URL is.
#3 is similar to #2 except that rather than letting navigation happen the normal way, you load everything via ajax as the user clicks around, loading it into (say) a main content div rather than an iframe. This can also use hash fragments to ensure that it's fully linkable/bookmarkable, etc., but requires that all links in the pages loaded get rewritten so they update the hash fragment rather than the main URL instead.
#2 and #3 (and #1) all have their advantages and disadvantages. #1 is probably the least work. #2 probably comes in second, then #3, but I could have those backward.
Here's a quick and dirty version of #2 that polls for hash updates so that the pages loaded in the frame don't have to know anything about this at all. Note that all you'd have to give to the other people is the page; their pages remain the same. If they're concerned about page rank, they'll want to include the canonical URL of their pages in the markup.
withplayer.html:
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Example</title>
<style>
html, body {
padding: 0;
margin: 0;
}
html {
height: 100%;
box-sizing: border-box;
}
*, *:before, *:after {
box-sizing: inherit;
}
body {
height: 100%;
position: relative;
}
div.player {
height: 30px;
padding: 2px;
}
iframe.content {
border: none;
position: absolute;
top:30px;
width: 100%;
/*bottom: 0px; Sigh, this works on elements other than iframe, see 'resize' JavaScript below */
}
</style>
</head>
<body>
<div class="player"></div>
<iframe class="content"></iframe>
<script>
(function() {
// Fill in our "player"
var dt = new Date().toISOString();
document.querySelector(".player").innerHTML =
"This div is our pretend player: The div was loaded on " +
dt.substring(0, 10) + " at " + dt.substring(11, 19) + ".";
// Get the iframe
var content = document.querySelector(".content");
// Listen for hash changes
window.onhashchange = loadContent;
// Load any initial hash we have
loadContent();
// Get our current hash, without the leading #
function getHash() {
return location.hash.replace(/^#/, '');
}
// Get the hash equivalent of the current content in the content iframe
function getContentHash() {
var loc, hash;
loc = content && content.contentWindow && content.contentWindow.location;
hash = loc && loc != "about:blank" ? loc.pathname + loc.search + loc.hash : undefined;
return hash;
}
// Load the content for the current hash
function loadContent() {
// If we have an initial hash, apply to the iframe
var hash = getHash();
if (hash) {
content.src = hash;
}
}
// Poll for changes to the frame's location, update our hash if
// it doesn't match
setInterval(pollContent, 100);
function pollContent() {
var newHash;
newHash = getContentHash();
if (newHash !== undefined && newHash !== getHash()) {
location.hash = "#" + newHash;
}
}
// Stoopid iframes won't stick to the bottom, have to resize their height
resize();
window.onresize = resize;
function resize() {
content.style.height = (window.innerHeight - 30) + "px";
}
})();
</script>
</body>
</html>
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
});
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();
});