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>
Related
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.
How can I control the background image and colour of a body element within an iframe? Note, the embedded body element has a class, and the iframe is of a page that is part of my site.
The reason I need this is that my site has a black background assigned to the body, and then a white background assigned to divs that contain text. A WYSIWYG editor uses an iframe to embed content when editing, but it doesn't include the div, so the text is very hard to read.
The body of the iframe when in the editor has a class that isn't used anywhere else, so I'm assuming this was put there so problems like this could be solved. However, when I apply styles to class.body they don't override the styles applied to body. The weird thing is that the styles do appear in Firebug, so I've no idea what's going on!
Thanks
UPDATE - I've tried #mikeq's solution of adding a style to the class that is the body's class. This doesn't work when added to the main page's stylesheet, but it does work when added with Firebug. I'm assuming this is because Firebug is applied to all elements on the page whereas the CSS is not applied within iframes. Does this mean that adding the css after window load with JavaScript would work?
The below only works if the iframe content is from the same parent domain.
The following code works for me. Tested on Chrome and IE8. The inner iframe references a page that is on the same domain as the parent page.
In this particular case, I am hiding an element with a specific class in the inner iframe.
Basically, you just append a style element to the head section of the document loaded in a frame:
frame.addEventListener("load", ev => {
const new_style_element = document.createElement("style");
new_style_element.textContent = ".my-class { display: none; }"
ev.target.contentDocument.head.appendChild(new_style_element);
});
You can also instead of style use a link element, for referencing a stylesheet resource.
An iframe is a 'hole' in your page that displays another web page inside of it. The contents of the iframe is not in any shape or form part of your parent page.
As others have stated, your options are:
give the file that is being loaded in the iframe the necessary CSS
if the file in the iframe is from the same domain as your parent, then you can access the DOM of the document in the iframe from the parent.
You cannot change the style of a page displayed in an iframe unless you have direct access and therefore ownership of the source html and/or css files.
This is to stop XSS (Cross Site Scripting)
This code uses vanilla JavaScript. It creates a new <style> element. It sets the text content of that element to be a string containing the new CSS. And it appends that element directly to the iframe document's head.
Keep in mind, however, that accessing elements of a document loaded from another origin is not permitted (for security reasons) -- contentDocument of the iframe element will evaluate to null when attempted from the browsing context of the page embedding the frame.
var iframe = document.getElementById('the-iframe');
var style = document.createElement('style');
style.textContent =
'body {' +
' background-color: some-color;' +
' background-image: some-image;' +
'}'
;
iframe.contentDocument.head.appendChild(style);
Override another domain iframe CSS
By using part of SimpleSam5's answer, I achieved this with a few of Tawk's chat iframes (their customization interface is fine but I needed further customizations).
In this particular iframe that shows up on mobile devices, I needed to hide the default icon and place one of my background images. I did the following:
Tawk_API.onLoad = function() {
// without a specific API, you may try a similar load function
// perhaps with a setTimeout to ensure the iframe's content is fully loaded
$('#mtawkchat-minified-iframe-element').
contents().find("head").append(
$("<style type='text/css'>"+
"#tawkchat-status-text-container {"+
"background: url(https://example.net/img/my_mobile_bg.png) no-repeat center center blue;"+
"background-size: 100%;"+
"} "+
"#tawkchat-status-icon {display:none} </style>")
);
};
I do not own any Tawk's domain and this worked for me, thus you may do this even if it's not from the same parent domain (despite Jeremy Becker's comment on Sam's answer).
An iframe has another scope, so you can't access it to style or to change its content with javascript.
It's basically "another page".
The only thing you can do is to edit its own CSS, because with your global CSS you can't do anything.
This should work with cross domain if you're the owner of the both
The trick here is to assign a global css variable to your body, to listen message with the new color, and then to change the global css variable once receive a message.
I'm using angular, but it should work with pure javascript
My use case was to show to the user what he how the color change would impact his website in the iframe before saving it
Domain A
#ViewChildren('iframeContainer') iframeContainer: QueryList<ElementRef>
sendDataToIframe(
data = {
type: 'colorChange',
colors: {primary: '#000', secondary: '#fff'},
},
): void {
if (this.targetUrl)
this.iframeContainer.first.nativeElement.contentWindow.postMessage(data) // You may use document.getElementById('iframeContainer') instead
}
Domain B
acceptedEditOrigins = [
'https://my.origine.ccom', // Be sur to have a correct origin, to avoid xss injecto: https://en.wikipedia.org/wiki/Cross-site_scripting
]
constructor() {
// Listen to message
window.addEventListener('message', (event) => this.receiveMessage(event), false)
}
receiveMessage(event: MessageEvent) {
if (this.acceptedEditOrigins.includes(event.origin))
switch (event.data.type) {
case 'colorChange': {
this.setWebsiteConfigColor(event.data.colors)
}
}
}
setWebsiteConfigColor(colors: WebsiteConfigColors) {
if (colors) {
const root = document.documentElement
for (const [key, value] of Object.entries(colors)) {
root.style.setProperty(`--${key}`, value) // --primary: #000, --secondary: #fff
}
}
}
body {
background-color: var(--primary);
}
If you have control of the page hosting the iframe and the page of the iframe, you can pass a query parameter to the iframe...
Here's an example to add a class to the iframe based on whether or not the hosting site is mobile...
Adding iFrame:
var isMobile=$("mobile").length; //detect if page is mobile
var iFrameUrl ="https://myiframesite/?isMobile=" + isMobile;
$(body).append("<div id='wrapper'><iframe src=''></iframe></div>");
$("#wrapper iframe").attr("src", iFrameUrl );
Inside iFrame:
//add mobile class if needed
var url = new URL(window.location.href);
var isMobile = url.searchParams.get("isMobile");
if(isMobile == "1") {
$("body").addClass("mobile");
}
For juste one iframe, you can do something like this:
document.querySelector('iframe').contentDocument.body.style.backgroundColor = '#1e1e2d';
In case you have multiple iframe you're dealing with:
document.querySelectorAll('iframe').forEach((iframe) => {
iframe.contentDocument.body.style.backgroundColor = '#1e1e2d';
});
Perhaps it's changed now, but I have used a separate stylesheet with this element:
.feedEkList iframe
{
max-width: 435px!important;
width: 435px!important;
height: 320px!important;
}
to successfully style embedded youtube iframes...see the blog posts on this page.
give the body of your iframe page an ID (or class if you wish)
<html>
<head></head>
<body id="myId">
</body>
</html>
then, also within the iframe's page, assign a background to that in CSS
#myId {
background-color: white;
}
I am currently a beginner JavaScript learner. I was trying some special code logics found on various top websites like Facebook. One of them I found here: How does Facebook keep the header and footer fixed while loading a different page?. But I am unable to execute it properly. Following is my code:
<html>
<head>
</head>
<body>
<div id="header">TEST HEADER
SAMPLE</div>
<p>OUTSIDE</p>
<script type='text/javascript'>
var header = document.getElementById('header');
var headerLinks = header.getElementsByTagName('a');
for (var i = 0, l = headerLinks.length; i < l; i++) {
headerLinks[i].onclick = function () {
var href = this.href;
//Load the AJAX page (this is a whole other topic)
loadPage(href);
//Update the address bar to make it look like you were redirected
location.hash = '#' + href;
//Unfocus the link to make it look like you were redirected
this.blur();
//Prevent the natural HTTP redirect
return false;
}
}
</script>
</body>
</html>
Please tell me what I am doing wrong?
Actually the motive of my code is not just to persist header on a page but also when navigating to other page. The header should not reload when navigated to other page.
Solution from the answer by Bill F.:
Forgot to define loadPage() function:
<script type="text/javascript">
function loadPage() {
document.getElementById("content").innerHTML = '<object type="type/html" data="sample2.htm" ></object>';
}
</script>
You haven't defined the function loadPage is what you're doing wrong. Presumably, that function will use AJAX to retrieve a page's contents, whether in JSON, HTML, XML, CSV, whatever.
You can keep the position of a div fixed even while scrolling using position:fixed
#header
{
position:fixed;
}
i have managed to do it properly all you need to do is create 2 seperate container divs,1 for the nav bar(which you want to remain) and 2 for the content which you want changed then simply retrieve the data from an external page
CODE representation
<div class="container_for_persistent_nav-bar">
</div>
<div class="container_for_divs_that_are_not_persistent">
</div>
then just bind a click event to links that will,1.on click clear the div container for NON_PERSISTENT DIVS and then,2.load the divs from a separate page
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
We're using OpenX to serve ads on a number of sites. If the OpenX server has problems, however, it blocks page loads on these sites. I'd rather have the sites fail gracefully, i.e. load the pages without the ads and fill them in when they become available.
We're using OpenX's single page call, and we're giving divs explicit size in CSS so they can be laid out without their contents, but still loading the script blocks page load. Are there other best practices for speeding up pages with OpenX?
We load our ads in iframes to avoid the problem you're having. We size div and the iframe the same, with the iframe pointing to a page which just contains the ad snippet (you can pass the zone and other required options as parameters to that page).
cheers
Lee
We lazy-load OpenX's code. Instead of putting the single-page call at the top of the page, we put it at the bottom. After the page has loaded, the call will get the banner data and a custom code will add the correct banners in the correct zones.
The code below requires a proper DOM. If you have jQuery, DOMAssistant, FlowJS, etc, the DOM should be fixed for you.
This code will work with normal banners with images, flash, or HTML content. It may not work in some cases like when using banners from external providers (adform, etc). For that you may need to hack the code a bit.
How to use it?
add your SinglePageCall code towards the end of your HTML code
add this code under the SPC code.
after half a second or so, your OpenX code should be ready, and the code below will put the banners within the specified DIVs.
Oh, yeah, you need to add to your HTML code some DIVs as place holders for your banners. By default I have these banners set with CSS class "hidden" which totally hides the DIVs (with visibility, display, and height). Then, after the banner in a given DIV is successfully loaded, we remove the hidden class and the DIV (and the banner within) become visible.
Use at your own risk! :) Hope it helps
(function(){
if (!document || !document.getElementById || !document.addEventListener || !document.removeClass) {
return; // No proper DOM; give up.
}
var openx_timeout = 1, // limit the time we wait for openx
oZones = new Object(), // list of [div_id] => zoneID
displayBannerAds; // function.
// oZones.<divID> = <zoneID>
// eg: oZones.banner_below_job2 = 100;
// (generated on the server side with PHP)
oZones.banner_top = 23;
oZones.banner_bottom = 34;
displayBannerAds = function(){
if( typeof(OA_output)!='undefined' && OA_output.constructor == Array ){
// OpenX SinglePageCall ready!
if (OA_output.length>0) {
for (var zone_div_id in oZones){
zoneid = oZones[zone_div_id];
if(typeof(OA_output[zoneid])!='undefined' && OA_output[zoneid]!='') {
var flashCode,
oDIV = document.getElementById( zone_div_id );
if (oDIV) {
// if it's a flash banner..
if(OA_output[zoneid].indexOf("ox_swf.write")!=-1)
{
// extract javascript code
var pre_code_wrap = "<script type='text/javascript'><!--// <![CDATA[",
post_code_wrap = "// ]]> -->";
flashCode = OA_output[zoneid].substr(OA_output[zoneid].indexOf(pre_code_wrap)+pre_code_wrap.length);
flashCode = flashCode.substr(0, flashCode.indexOf(post_code_wrap));
// replace destination for the SWFObject
flashCode = flashCode.replace(/ox\_swf\.write\(\'(.*)'\)/, "ox_swf.write('"+ oDIV.id +"')");
// insert SWFObject
if( flashCode.indexOf("ox_swf.write")!=-1 ){
eval(flashCode);
oDIV.removeClass('hidden');
}// else: the code was not as expected; don't show it
}else{
// normal image banner; just set the contents of the DIV
oDIV.innerHTML = OA_output[zoneid];
oDIV.removeClass('hidden');
}
}
}
} // end of loop
}//else: no banners on this page
}else{
// not ready, let's wait a bit
if (openx_timeout>80) {
return; // we waited too long; abort
};
setTimeout( displayBannerAds, 10*openx_timeout );
openx_timeout+=4;
}
};
displayBannerAds();
})();
OpenX has some documentation on how to make their tags load asynchronously:
http://docs.openx.com/ad_server/adtagguide_synchjs_implementing_async.html
I've tested it, and it works well in current Chrome/Firefox.
It takes some manual tweaking of their ad code. Their example of how the ad tags should end up:
<html>
<head></head>
<body>
Some content here.
Ad goes here.
<!-- Preserve space while the rest of the page loads. -->
<div id="placeholderId" style="width:728px;height:90px">
<!-- Fallback mechanism to use if unable to load the script tag. -->
<noscript>
<iframe id="4cb4e94bd5bb6" name="4cb4e94bd5bb6"
src="http://d.example.com/w/1.0/afr?auid=8&target=
_blank&cb=INSERT_RANDOM_NUMBER_HERE"
frameborder="0" scrolling="no" width="728"
height="90">
<a href="http://d.example.com/w/1.0/rc?cs=
4cb4e94bd5bb6&cb=INSERT_RANDOM_NUMBER_HERE"
target="_blank">
<img src="http://d.example.com/w/1.0/ai?auid=8&cs=
4cb4e94bd5bb6&cb=INSERT_RANDOM_NUMBER_HERE"
border="0" alt=""></a></iframe>
</noscript>
</div>
<!--Async ad request with multiple parameters.-->
<script type="text/javascript">
var OX_ads = OX_ads || [];
OX_ads.push({
"slot_id":"placeholderId",
"auid":"8",
"tid":"4",
"tg":"_blank",
"r":"http://redirect.clicks.to.here/landing.html",
"rd":"120",
"rm":"2",
"imp_beacon":"HTML for client-side impression beacon",
"fallback":"HTML for client-side fallback"
});
</script>
<!-- Fetch the Tag Library -->
<script type="text/javascript" src="http://d.example.com/w/1.0/jstag"></script>
Some other content here.
</body>
</html>
Following #Rafa excellent answer, i'm using this code to invoke OpenX banners after the page loads. I'm using jquery as well and had to add a new replace call for the "document.write" that flash banners use, and replacing it with "$('#"+ oDIV.id +"').append" instead. I'm using a custom "my_openx()" call, to replace "OA_show()". My banners area called by the zone_id and are wrapped inside a div, like this:
<div id="openx-4"><script>wm_openx(4);</script></div>
It's working :)
<script type="text/javascript">
$is_mobile = false;
$document_ready = 0;
$(document).ready(function() {
$document_ready = 1;
if( $('#MobileCheck').css('display') == 'inline' ) {
$is_mobile = true;
//alert('is_mobile: '+$is_mobile);
}
});
function wm_openx($id) {
if($is_mobile) return false;
if(!$document_ready) {
setTimeout(function(){ wm_openx($id); },1000);
return false;
}
if(typeof(OA_output[$id])!='undefined' && OA_output[$id]!='') {
var flashCode,
oDIV = document.getElementById('openx-'+$id);
if (oDIV) {
// if it's a flash banner..
if(OA_output[$id].indexOf("ox_swf.write")!=-1) {
// extract javascript code
var pre_code_wrap = "<script type='text/javascript'><!--// <![CDATA[",
post_code_wrap = "// ]]> -->";
flashCode = OA_output[$id].substr(OA_output[$id].indexOf(pre_code_wrap)+pre_code_wrap.length);
flashCode = flashCode.substr(0, flashCode.indexOf(post_code_wrap));
// replace destination for the SWFObject
flashCode = flashCode.replace(/ox\_swf\.write\(\'(.*)'\)/, "ox_swf.write('"+ oDIV.id +"')");
flashCode = flashCode.replace(/document.write/, "$('#"+ oDIV.id +"').append");
// insert SWFObject
if( flashCode.indexOf("ox_swf.write")!=-1 ) {
//alert(flashCode);
eval(flashCode);
//oDIV.removeClass('hidden');
}// else: the code was not as expected; don't show it
}else{
// normal image banner; just set the contents of the DIV
oDIV.innerHTML = OA_output[$id];
//oDIV.removeClass('hidden');
}
}
}
//OA_show($id);
}
</script>
I was looking for this to load advertising from my openX server only when the advertising should be visible. I'm using the iFrame version of openX which is loaded in a div. The answer here put me on my way to solving this problem, but the posted solution is a bit too simple. First of all, when the page is not loaded from the top (in case the user enters the page by clicking 'back') none of the divs are loaded. So you'll need something like this:
$(document).ready(function(){
$(window).scroll(lazyload);
lazyload();
});
also, you'll need to know what defines a visible div. That can be a div that's fully visible or partially visible. If the bottom of the object is greater or equal to the top of the window AND the top of the object is smaller or equal to the bottom of the window it should be visible (or in this case: loaded). Your function lazyload may look like this:
function lazyload(){
var wt = $(window).scrollTop(); //* top of the window
var wb = wt + $(window).height(); //* bottom of the window
$(".ads").each(function(){
var ot = $(this).offset().top; //* top of object (i.e. advertising div)
var ob = ot + $(this).height(); //* bottom of object
if(!$(this).attr("loaded") && wt<=ob && wb >= ot){
$(this).html("here goes the iframe definition");
$(this).attr("loaded",true);
}
});
}
Tested on all major browsers and even on my iPhone, works like a charm!!