Say I have a URL: http://rythmengine.org/doc/expression.md#transformer
Immediately after the page is loaded, the anchor is shown correctly, however I have a script to automatically add some iframes across the page, chrome/opera will later on shift away from the anchor #comment, firefox and IE (10) are all good.
Any idea how to fix it in Chrome/opera?
I do not know if I would implement this or not since the iframes do take a noticeable amount of time to load and the user might already be scrolling around the page and get jolted back to the hash element but here is a solution I came up with using jQuery.
Since the iframes are being replaced in the document after it initially loads you can use the .load() function which normally never fires if you just have it on the document.
Demo on this page and edit the fiddle here.
Just add this jQuery code into your script tag where you replace all of the pre code:
Code:
$('iframe').load(function() {
moveToHash();
});
// Scroll to the url hash element
function moveToHash()
{
var hashElem = $(window.location.hash);
// If the hash elment exists
if(hashElem.length)
{
window.scrollTo(hashElem.position().left, hashElem.position().top);
}
}
Edit: had a few mistakes and unnecessary in the code that are now fixed.
When every iframe ends loading tell the browser to go to that hash
$('iframe').load(function() {
document.location.href = document.location.hash;
});
Related
I am making a website that uses a small amount of javascript javascript for non-essential or merely aesthetic functionalities. I am aware that there is a percentage of users that prefer to navigate with javascript disabled, so in principle I tried to use a css style sheet within a noscript tag in the head of the page so that where javascript was not available, certain elements of the page will be hidden.
However, while this approach works when javascript is disabled in the browser, it fails for users that block javascript with certain browser extensions (I tested with NoScript for Firefox, surely there are others). What would be an alternative method to achieve what I wanted to with the noscript tag in this scenario?
NoScript works by removing the script tags from the document and thus preventing the js files from being loaded, but it does not disable the execution of scripts, so the noscript tag does not work.
To remove certain elements of the page when javascript is not available, regardless of the cause, the best approach is to make those elements hidden by default, and reveal them with javascript after loading the page. The first step would be creating a CSS class like the one below in your stylesheet and apply it to everything you do not want to be visible unless JS scripts can be executed:
.hideOnNoScript {
display: none !important;
}
Second step would be to remove that CSS class with javascript on page load:
//Execute after page is ready
function ready(callback){
// in case the document is already rendered
if (document.readyState!='loading') callback();
// modern browsers
else if (document.addEventListener)
document.addEventListener('DOMContentLoaded', callback);
// IE <= 8
else document.attachEvent('onreadystatechange', function(){
if (document.readyState=='complete') callback();
});
}
var removeHideOnNoScript = function() {
var elementstohide = window.top.document.querySelectorAll('.hideOnNoScript ');
for (let i= 0; i< elementstohide.length; i++) {
const element = elementstohide[i];
element.classList.remove('hideOnNoScript');
}
}
ready(removeHideOnNoScript);
Note: I really dislike having to use !important, but I have not managed to make this solution work without it. I would be glad to change it if anyone can point me to an alternative.
This is my situation; I am displaying ads on my website but I want to display a specific banner if a visitor is using an ad blocker. First thing I've looked for is a script that detects the ad blocker, but after trying a few different scripts it seems most of them no longer work (at least, I couldn't get them to work).
So I gave up on that and went with a different solution. Displaying a CSS background image behind the ad so that if the ad isn't shown, the image is. Because a typical ad takes a moment to load I made the background image a GIF image with 2 seconds of transparency. This works like a charm the first time, but when you reload the page or open a different page the GIF animation doesn't play and instantly displays the last frame, skipping the transparency.
I've tried adding random stuff behind the URL in the CSS, which didn't work. I've tried a data/inline version of the image, that didn't seem to work either. I'm kinda running out of solutions.
The CSS:
.ads {
position: relative;
top: 15px;
float: right;
height: 60px;
width: 468px;
background-image: url('/images/ads/ads_top.gif?randomstuff=39485')
}
I'm basically looking for either;
1) A way to show an alternative image if the ad is blocked (that is still actual and works).
2) A way to delay a CSS background image from being loaded.
3) A way to prevent a GIF from being cached or forced to replay the animation on each pageload.
Any of these would fix my problem. Hope someone is able to help.
Thanks!
Look this link. It is very simple and I don't think you need comments. Another question is how to set up time to each image.
Time to use some jQuery:
Your html code:
<div class='ads'></div>
<div class='ads'></div>
And the css code:
.ads {
position: relative;
top: 15px;
float: right;
height: 60px;
width: 468px;
}
Your jQuery code:
$(".ads").each(function() {
var timestamp = $.now();
$(this).css("background-image", "url('/images/ads/ads_top.gif?"+timestamp+"')");
});
Your jQuery code have to be placed into the .js file. Do you have some js files? If yes, then add my code into onload handler. If you don't have any create new file, say, scripts.js and put this code into it:
$(document).ready(function()
{
$(".ads").each(function() {
var timestamp = $.now();
$(this).css("background-image", "url('/images/ads/ads_top.gif?"+timestamp+"')");
});
}
Explanation:
.ready function means that all instructions in body of this
function will be read and started on page load. You don't need them
to work before page loaded, right?
$(".ads") — we get element with selector .ads (with class ads).
$(".ads").each(function() { /* body */ } — .each function means that we will assign instructions from function body to all elements with selector .ads
var timestamp = $.now(); — getting timestamp and assigning it into variable
$(this).css("background-image", "url('/images/ads/ads_top.gif?"+timestamp+"')"); — adding css property to $(this) element (this element is current element with selector .ads)
Thats all. Simple. Now you have file scripts.js with content above. Put it somewhere on your site, where you usually put your media files. For example, {root}/media/ <-- here.
The last thing you should do is link your new js file and jQuery library. Note, that jQuery library have to be linked before file, using $ variable.
Add next code to the <head></head> tag to your view:
<script src="http://code.jquery.com/jquery-1.11.0.min.js"></script>
<script src="/media/script.js"></script>
Don't forget to do all js actions in onload handler.
Hope this will help. Tell me about result, please.
JSFIDDLE
A possible solution for option 1, is to check with javascript (or preferably jquery) if the banner is visible. (You probably need to put a setTimeout around it, because as far as I know the page js loads first, and after that the adblocker js.
var ads = $('.ads').filter(':visible');
if(!ads.length) {
//do your alternative image showing magic here
}
A possible solution for option 2 might be to link to a php script and put a sleep(2); inside it, with after that the appropriate headers and print/echo of the image.
Let me explain: I have a site, index.html
The site should start at a specific anchor, which is at the very bottom of the page. I did this using this code:
setTimeout("window.location.href='index.html#start'",0);
The problem is: I want to share a link to other people, e.g. index.html/#work
In this case, the site SHOULD NOT move to the #start anchor. But it does.
So here's my question: Is there a possibility that a site only scrolls to #start if the requested site is index.html and always remains like it is if the requested site has an anchor in it? (e.g. index.html/#anchor)
Thank you very much!
Sure:
if (window.location.hash === "") {
window.location.hash = "start"
}
There's no reason to wrap the hash change in a setTimeout, and instead of changing the href, just change hash, so that it will still work if you change the name of the file or move the code to a different file.
Also, remember to wrap the code in a window.onload, so the element that you're trying to jump to actually exists. (use window.onload = function() { /* code here */ })
Chrome flickers when reloading content in iframes. Can this be avoided in any way, thinking of:
Wrapping a-links with js that does some magic.
Meta-tags in content-html. (I have source control over the html in the iframes)
Please note that the content-type in the iframe may vary (pdfs, html, images) so if ajax is the only way out here, does it reflect the http-content-type back to the iframe?
Please visit the demo at http://jsfiddle.net/2tEVr/
Excerpt of fiddle:
<iframe name="if" width="800" height="600"></iframe>
UPDATE
The solution that worked best for me was to replace regular href's with ajax-requests, repopulating the body-area, (solution 4 below) Flickering is gone but comes at a price of akward debugging since sync between content and "view-source" is lost on ajax-request.
Also, since the content-type in my case may change, the method for performing the ajax-request had to have some brains and possibly fall back to regular location request.
regards,
#user247245: From your question, its not entirely clear how you (want to) use the iframe. Does it reload periodically, or once when the whole webpage loads?
Solution 1: Different background color
In case you just want to avoid the ugly white, and avoid over-complication. Set a different background color in your HTML header of the framecontents.html file, like so:
<!DOCTYPE html>
<html style="background-color: #F48;">
This way, while the CSS file loads,parses, and gets applied, the background is not #fff.
Solution 2: Transparent iframe
While there is no content, the iframe should simply not be visible. Solution:
<iframe src="/framecontents.html" allowTransparency="true" background="transparent"></iframe>
Ofcourse dont use this in combination with solution 1, you'll shoot yourself in the foot.
Solution 3: Preload iframe page
In case you are loading the iframe later (such as user clicking a link), consider preloading its contents. Hide this in near the top of your (parent) page:
<iframe src="/framecontents.html" style="position: absolute; width: 0px; height: 0px"></iframe>
But i'd advise using solution 2 instead.
Solution 4: If doing a mobile web interface:
See how jQuery Mobile did it. We built a web interface that had to feel like a native app, so without reload flashes. jQM fixed that. Basically does a background ajax call to retrieve the full HTML contents, then extracts the body (the "page" div to be more precise) and then replaces the contents (with a transition if you like). All the while a reload spinner is shown.
All in all this feels like more like a mobile application: no reload flashes. Other solutions would be:
Solution 5: Use JS to inject CSS:
See answer by jmva, or http://css-tricks.com/prevent-white-flash-iframe/ .
Solution 6: use JS to inject CSS (simple version)
<script type="text/javascript">
parent.document.getElementById("theframe").style.visibility = "hidden";
</script>
<iframe id="theframe" src="/framecontents.html" onload="this.style.visibility='visible';"></iframe>
You could ofcourse leave out the <script> part and add style="visibility:hidden;" to the iframe, but the above would make sure that the frame is visible for visitors with JS disabled. Actually, i'd advise to do that because 99% of visitors has it enabled anyway, and its simpler and more effective.
A common trick is to display the iframe just when it's full loaded but it's better to not rely on that.
<iframe src="..." style="visibility:hidden;"
onload="this.style.visibility='visible';"></iframe>
The same trick a bit optimized using JS.
// Prevent variables from being global
(function () {
/*
1. Inject CSS which makes iframe invisible
*/
var div = document.createElement('div'),
ref = document.getElementsByTagName('base')[0] ||
document.getElementsByTagName('script')[0];
div.innerHTML = '<style> iframe { visibility: hidden; } </style>';
ref.parentNode.insertBefore(div, ref);
/*
2. When window loads, remove that CSS,
making iframe visible again
*/
window.onload = function() {
div.parentNode.removeChild(div);
}
})();
Extracted from css-trick
If you have to switch between different sites and that trick of onload isn't working the only viable solution would be destroy and create the iframe programatically.
Try adding transform: translate3d(0, 0, 0); on a parent element.
I had an issue where the iframe was taller than its parent (parent has overflow: hidden). The iframe's overflown portion was flickering on each video loop on Chrome (YouTube iframe API).
Forcing hardware acceleration this way was the only thing that worked for me.
A simpler solution that worked in my case was just adding this CSS to the iframe
will-change: height;
min-height: 400px;
I'm doing some documentation where I make heavy use of anchors for linking between pages on a wiki.
see here:
http://code.google.com/p/xcmetadataservicestoolkit/wiki/ServicesExplained#Platform_Data_Structures
The feature that really makes this work well is when the browser shows the anchor at the absolute top of the pane. When it gets confusing is when linking to an anchor shows the anchor half-way down the page since the page is scrolled down all the way
see here:
http://code.google.com/p/xcmetadataservicestoolkit/source/browse/trunk/mst-common/src/java/xc/mst/utils/Util.java#227
My solution in the wiki (first link) was to put a blank image at the bottom of the page simply to make the browser show the anchor right at the top. Is there a better way to do this? Is there a way to do it in the second link (in which I can't add a blank image)?
Putting a blank image at the bottom of your page is a bad idea, since it will expand your document to a unnecessary height.
You could throw in some javascript to apply an effect to the anchor you just travelled to, to highlight it wherever it is.
Without altering the height of your document (i.e. adding extra padding at bottom), you'll always have this issue.
However, using bit of JS/jQuery, the user experience can be improved considerably:
On clicking a named anchor:
Instead of jumping in a flash (broswer's default behavior), add a smooth scroll
add an highlight to indicate current selection (this helps tremendously in 2nd case as the user can clearly see what is current)
Created a demo to illustrate the concepts: http://jsfiddle.net/mrchief/PYsyN/9/
CSS
<style>
.current { font-weight: bold; }
</style>
JS
function smoothScroll(elemId) {
// remove existing highlights
$('.current').css({backgroundColor: "transparent"}).removeClass('current');
var top = $(elemId).offset().top;
// do a smooth scroll
$('html, body').animate({scrollTop:top}, 500, function(){
// add an highlight
$(elemId).animate({backgroundColor: "#68BFEF" }, 500, function () {
// keep tab of current so that style can be reset later
$(elemId).addClass('current');
});
});
}
// when landing directly
if (document.location.hash) {
smoothScroll(document.location.hash);
}
$('a[href*="#"]').click(function() {
// utilizing the fact that named anchor has a corresponding id element
var elemId = $(this).attr('href');
smoothScroll(elemId);
});
You can create a absolutre positioned pseudo-element with a great height to targeted block using just the following CSS (for the second link in your post:
#nums td:target a::before {
content: '';
position: absolute;
height: 700px;
}
The height must be around the height of the viewport, so the best solution is to create these styles on the fly using js. But if you don't wan't to use js, just use height: 1000px or more — if you don't mind a gap at the bottom of course.
The best part: it's only CSS and there would be no gap when no anchors are targeted.
Edit: just a sneak peek into the future: if the vw/vh units would come to other browsers (now it's only in IE9), this could be awesomely done with just CSS using height: 100vh :)
You could use Javascript / jQuery to create a white div that has the necessary height needed to put your element at the top of the browser window, and you could even remove this upon scrolling away.
However I would highly recommend against doing so as this will expand your page where it isn't needed. It's a lot smarter to simply style the tag upon going there (through Javascript / jQuery) so it pops out to the viewer, for instance by setting the font-weight to bold or changing the background-color.
I would probably use a combination of jQuery and PHP for this:
PHP(somewhere right after your <body> element):
<?php
$anchor = explode('#', $_SERVER['REQUEST_URI']);
$anchor = $anchor[1];
echo '<div id="selected-anchor" anchor="'.$anchor.'"></div>';
?>
And then the jQuery:
<script type="text/javascript">
$(function(){
$('#selected-anchor').css('background-color', '[Whatever highlight color you want]');
});
</script>
Hope this helps.