I have in http://www.g3eo.com/#!/page_About the following in line 96:
<li>Side scan sonar surveys</li>
and need to create an anchor to go to line 180:
<li id="sidescan"><strong>Side scan sonar surveys</strong></li>
I understand that to get this working I would need to do:
<li>Side scan sonar surveys</li>
<li id="sidescan"><a name="sss"><strong>Side scan sonar surveys</strong></a></li>
But this does nothing. I was wondering if the problem is the hashbang in #!/page_Services, without it the web page stops working properly.
Something like this will work:
// Run the code on page load. Change this to whatever your page callback is
window.addEventListener('load', function(e)
{
// Find any of the anchors that have a hash link.
// Change document to whatever the container is for your new elements
as = document.querySelectorAll('a[href^="#"]');
as.forEach(function(a)
{
a.addEventListener('click', function(e)
{
// This stops the hash being added to the URL on click
e.preventDefault();
// Find the hash and the target element (based on ID)
var hash = e.target.href.split('#')[1];
var targetEl = document.getElementById(hash);
// Scroll the window to the target elements offsetTop
window.scrollTo(0, targetEl.offsetTop);
});
});
});
But you'll need to run this code after the content that you want to use is loaded (rather than on page load).
Basically, this simulates hash linking without adding the hash to the url. See here for a working version - https://plnkr.co/edit/mubdlfjuFTgLeYq6ZpCR?p=preview
I started working on a solution very similar to #Liam Egan's, which is good, but I thought "What if someone wants to share a link to an anchor tag? I'll just try using both a hashbang and an anchor hash in the URL!".
After multiple tests, as it turns out, it's really hard to maintain, especially if you use an external library which uses the hash. It will break, so I abandoned that idea.
Here is a solution for clicks on links, which I tested on your website:
$(function(){
$('a[href^="#"]').click(function(e){
// Get the hashes in link
var h = this.href.split('#');
// If the first hash is not a hashbang or if there are several hashes
if(h[1].indexOf('!') !== 0 || h.length > 2) {
// Prevent default behavior of the link so it does not break the site
e.preventDefault();
// If the first hash is a hashbang (but there are multiple hashes),
// only include the first one in the page URL
if(h[1].indexOf('!') === 0) { window.location.hash = '#' + h[1]; }
// Get the element with the right ID (last hash) and its scrolling container
var el = $('#' + h.pop()), cont = el.closest('div[class^="scroll"]');
// Scroll the scrolling container to that element after a delay,
// because it does not work during the page transition
setTimeout(function() {
cont.scrollTop(0) // Reset it first to get the right position below
.scrollTop( el.position().top );
},500);
}
});
});
I had to adapt it for two reasons:
Not the whole document should scroll, just your wrapping .scroll div
The scrolling won't work during page transition, so it needs a delay
It does not affect links such as #!/page_XXX, and will work with links such as #myID or #!/page_XXX#myID.
Finally, for simplicity, since you are using jQuery, I did too. Place that piece of code anywhere on your page after loading jQuery, and it should work.
Related
I'm building a photography portfolio website on Wordpress using this theme: http://wpshower.com/themes/expositio/ . The theme hasn't been updated in years but still works smoothly. I have an issue with assigning target="_blank" to some external links though. The option is there but it has no effect whatsoever.
I've looked for advice and have tried every available plugin that addresses the problem, with the best result being opening the external link in both a new tab and the current tab.
I've looked into all the theme files, they are not many, and thinking that this is a javascript issue, I have identified the following code. It deals with the mobile menu animations but it's the only mention of links.
It was also discussed in a similar thread in here: Wordpress navbar links using href="#" not working as a dummy link
$('a').on('click', function(e) {
e.preventDefault();
var _this = $(this);
// close mobile menu if it's open, redirect otherwise
if (_body.hasClass('toggled-on') && _this.parents('#page').length == 1
&& _this.parents('#primary-navigation').length == 0
) {
load_effect.menuOff();
} else {
load_effect.loader.show();
var href = $(this).attr('href');
$('.site').css('opacity', 0);
setTimeout(function() {
window.location = href;
}, load_effect.duration);
}
Finally, here is website using the same theme where the external links do open in a new tab: http://www.tokyogoodidea.com/
I'd be grateful for any advice on solving this little glitch. I'm not good at all with js and don't know what to change.
Here's my project's link: http://one.clrblnd.com/
Thanks in advance.
There seems to be no reliable way to open a new tab in Javascript (a quick search tells it could be tricky), and the code indeeed looks like it is blocking a new page being opened. You can probably try if this works.
Firstly after this line
var href = $(this).attr('href');
add another line that says (this line gets the value of target attribute/properties from the tag, and assumed to be _self if undefined)
var target = $(this).prop('target') || '_self';
Then look for this line
$('.site').css('opacity', 0);
What it does is to make the whole page blank essentially. You may want to do something with this, for example wrap it in a if statement so it doesn't execute when target="_blank". A quick way to fix it is by replacing it to
target === '_blank' || $('.site').css('opacity', 0);
Next replace (just a few lines after the previous one)
window.location = href;
with
window.open(href, target)
The respective block should look like
load_effect.loader.show();
var href = $(this).attr('href');
var target = $(this).prop('target') || '_self';
target === '_blank' || $('.site').css('opacity', 0);
setTimeout(function() {
window.open(href, target)
}, load_effect.duration);
This is asuming window.open works as expected (documentation is here). What happens in the code is that the author stopped the default behavior after clicking a link with
e.preventDefault();
in order to allow some fancy animation to complete before the browser proceeds to load the intended page. However by simplifying the page load with
window.location = href;
it ignores the target attribute/property of the respective <a /> tag.
I'm talking about an icon that is displayed on a tab during page loading.
Chrome:
Firefox (with TreeTab plugin):
You get the idea. I want to make it seem like the page is loading, when it's already loaded. Some event fires is javascript and then the tab looks like it's being loaded. Is there a way to do that?
One way I can think of is to replace a favicon with a spinner, but I'm not sure if it's possible to change on the fly and even if it is, it would be a hassle to make it cross-browser.
I don't think it is a good idea to do it, you'll make your users do a lot of useless requests, and this kills trees : /
IMO, it's better to do all you have in the page itself, and let the browser's UI do his own stuff.
But since I liked the challenge, here is one hacky way :
Loading an iframe will trigger this icon in both chrome and Firefox[1], so you could ,
append an iframe in the document,
set its src to some huge document,
onload of the iframe, set it again with a ? cache hack,
regularly check if the duration has elapsed so you can remove the iframe's src.
[1] It seems that Firefox does trigger the icon only if it was triggered when the document was still loading.
In code :
// how to use :
showTabLoader(25000);
// takes duration in ms as only parameter
function showTabLoader(duration) {
if (!duration) return;
var now = performance.now();
// To avoid flickering, you need some big document
// Please change this url in your script, wikimedia may not be happy with us.
var url = 'https://upload.wikimedia.org/wikipedia/commons/3/35/Viborg_Katedralskole_Symmetrical.jpg';
var iframe = document.createElement('iframe');
iframe.style.display = 'none';
document.body.appendChild(iframe);
iframe.onload = function() {
if (performance.now() - now < +duration) {
this.src = url + '?' + Math.random();
}
};
var check = function(time) {
if (time - now > +duration) {
iframe.src = '';
iframe.parentNode.removeChild(iframe);
return;
}
requestAnimationFrame(check);
}
requestAnimationFrame(check);
iframe.src = url;
}
I recently thought of the same idea. A neat option is to use a dynamic favicon instead of hacking in hidden requests, which is a really bad idea in my opinion. I found this example. It's to much code to include here and doesn't work in iframes so no way of showing it directly on Stackoverflow. Instead i describe the idea behind.
https://www.cssscript.com/favicon-loading-indicator-favloader/
The idea is simple. Replace the favicon in an interval with the loading animation icons. A favicon cannot be GIF so you have to load each image step by step with JS. When you are done, simply replace it back with the original favicon.
For me this works at least in all chrome based browsers. Firefox throw some errors in this example, but i guess it can be fixed.
Alternitive:
There is no function that shows the actual loading process of the webpage. But you can do it manually, like you said!
The event below starts to run when the page is fully loaded, even after all the images are loaded:
$(window).on('load', function() {
// do stuff
});
So what you could do is set up your html like this:
<div class="preloader">
// your loader here, animations, video, gif, anything you want
</div>
<div class="main" style="display: none;">
// the page
</div>
and your jquery like this:
$(window).on('load', function() {
setTimeout(function() {
$('.preloader').css('display', 'none');
$('.main').css('opacity', '1');
}, 5000); // <-- 5seconds
});
And there you have your manual loading function! Works perfect.
Example website: ifly50
EDIT:
added code snippet
Code snippet:
$(window).on('load', function() {
setTimeout(function() {
$('.preloader').css('display', 'none');
$('.main').css('display', 'block');
}, 3000); // <-- 3 seconds
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="preloader">loading</div>
<div class="main" style="display: none;">main</div>
I am using Cincopa to embed my video into my website. The page that it is embedded in is hidden and navigation is removed. So I would like everyone to be redirected to the home page once the video is finished.
Here is my code:
<div id="cp_widget_55a42f1b-6e51-4738-87f9-eaf52dc6a826">...</div>
<script type="text/javascript">
var cpo = [];
cpo["_object"] = "cp_widget_55a42f1b-6e51-4738-87f9-eaf52dc6a826";
cpo["_fid"] = "AsBAj2M3MQOr";
var _cpmp = _cpmp || [];
_cpmp.push(cpo);
(function() {
var cp = document.createElement("script");
cp.type = "text/javascript";
cp.async = true;
cp.src = "//www.cincopa.com/media-platform/runtime/libasync.js";
var c = document.getElementsByTagName("script")[0];
c.parentNode.insertBefore(cp, c);
})();
</script>
<noscript>Powered by Cincopa <a href='http://www.cincopa.com/video-hosting'>Video Hosting for Business</a> solution.<span>Test</span><span>bitrate</span><span> 39961 kb/s</span><span>height</span><span> 1080</span><span>duration</span><span> 00:02:35.31</span><span>lat</span>:<span> +33.2269</span><span>long</span>:<span> 21-96.93</span><span>fps</span><span> 59.94</span><span>width</span><span> 1920</span><span>originaldate</span><span> 2015-06-06 19:08:58</span>
</noscript>
Cincopa embeds a video HTML tag, you have to add an event as explained here
Well, right now I'm not quite in the mood to make a complete test, so I'll just suggest a workaround which you will need to adapt.
In order to give you the exact code, I need to know:
What CMS are you using?
Can you add an id or a class to your video tag with cincopa?
Are you including jQuery?
Then you'll have to add this lines in the bottom of your script:
//Wait until the page is entirely loaded, and so you can access the rendered video tag (you'll need jQuery)
$( document ).ready(function() {
function goHomeYouAreDrunk(e) {
window.location.href = "http://url.to.your.home.page";
}
//I'm supposing that your video is the sole video tag in your page, if it's not, you'll have to get it by its id or class
document.find('video').addEventListener('ended',goHomeYouArDrunk,false);
});
Normally, that would be via an event listener on the <audio> or <video> element.
How to add Event Listeners | W3Schools : https://www.w3schools.com/Jsref/met_element_addeventlistener.asp
But a way I'd do it with Javascript just to be sure is:
// The interval clocks every .1 second(s).
setInterval(function() {
// If the element's current playback time is the playback duration (has reached the end).
if (audioElement.currentTime == audioElement.duration)
doSomething()
}, 100)
Although if you are wary about performance and don't want to use a setInterval() function, then stick with adding an event to the element.
By the way, to re-direct to another page, use the Javascript function location.assign("https://www.example.com.").
This code has been tested in https://www.cincopa.com/:
document.getElementById("video_iframe_id_in_your_page")
.contentWindow
.document.getElementsByTagName("video")[0]
.addEventListener("ended", function(args){
window.open("/", "_top");
});
wish can help you.
You can redirect to the home page by setting window.location="/"
I'm not sure how you're checking if the video has ended, you can add a listener like this.
Upon completion, you can call a handler function to redirect the user to the homepage.
document.getElementById('myVideo').addEventListener('ended',redirectToHomePage,false);
redirectToHomePage(){
window.location = "/";
}
For a mockup-webpage used for research on interaction on websites, I created a mockup message-stream using JavaScript. This message stream is loaded in an IFrame and should show images at pre-set intervals and scroll to the bottom of the page after placing a new image at the bottom of the page. Getting the images to appear is working quite well with the provided script. However, both Chrome and IE seem to have trouble scrolling the page to the bottom. I would like to scroll to the bottom of the page as soon as the image is attached, but have for now added a 5 ms delay because that seemed to work sometimes. My questions are:
Is it okay to use document.body.scrollHeight for this purpose?
Can I make the scroll occur directly, or do I need a small interval before scrolling?
How to make the code scroll to the bottom of the IFrame directly after adding an image?
The following functions are used and trypost() is started onLoad:
function scrollToBottom(){
window.scrollBy(0,document.body.scrollHeight);
}
function trypost(){
point = point + 1;
if(point < interval.length){
//create and append a new image
var newImg = document.createElement("IMG");
newImg.src = "images/"+images[point]+".png";
document.getElementById('holder').appendChild(newImg);
//create and append a return
var br = document.createElement("br");
document.getElementById('holder').appendChild(br);
//time scroll to bottom (after an arbitrary 5 seconds)
var stb = window.setTimeout(scrollToBottom, 5);
//time next post
var nextupdate = interval[point]*400;
var tp = window.setTimeout(trypost, nextupdate);
}
}
My script section contains at least the following variables:
var point = -1;
var interval = [10, 10, 15];
var images = ["r1", "a1", "r2"];
This questions is a continuation of the project described in How to proper use setTimeout with IE?
To answer one of your questions, document.body.scrollHeight is appropriate for this purpose, but not if you're actually calling for document. That'll give you the scroll height of the document the iFrame is in, not the iFrame's document. The iFrame's document can be called upon by [insert variable for iFrame here].contentDocument.
Here's how I did it (and by that, I mean I tested it out with my own stuff to make sure it worked):
let i = document.querySelector('iframe')
i.contentWindow.scrollTo(0, i.contentDocument.body.scrollHeight);
That being said, the other answer by Thomas Urban will also work most of the time. The difference is only if your page has a really long scroll height. Most pages won't be longer than 999999 (for all I know that's impossible and that's why they chose that number), but if you have a page longer than that, the method I showed here would scroll to the bottom and the 999999 would scroll to somewhere not yet at the bottom.
Also note, if you have more than one iFrame, you're gonna want to query it in a different way than I did, like by ID.
Scrolling to bottom is always like scrolling to some ridiculously large top offset, e.g. 999999.
iframe.contentWindow.scrollTo( 0, 999999 );
In addition see this post: Scrolling an iframe with javascript?
If scrolling occurs too early it's probably due to images not being loaded yet. Thus, you will have to scroll as soon as added image has been loaded rather than on having placed it. Add
newImg.onload = function() { triggerScrolling(); };
after creating newImg, but before assigning property src.
If several events are required to trigger scrolling you might need to use some "event collector".
function getEventCollector( start, trigger ) {
return function() {
if ( --start == 0 ) { trigger(); )
};
}
You can then use it like this:
var collector = getEventCollector( 2, function() { triggerScrolling(); } );
newImg.onload = collector;
window.setTimeout( collector, 100 );
This way triggerScrolling() is invoked after 100ms at least and after image has been loaded for collector has to be invoked twice for triggerScrolling() being invoked eventually.
I have a page with some fixed and absolute elements that are causing an issue for hash path links. I was able to fix it while the user is navigating around the page with function() { window.scrollBy(0, -80) }; however if I try to call this on my document ready (to scroll for incoming hashes) it does not work.
I found the reason it does not work is that the page does not actually adjust to the hash until after the document ready. If I cannot do this at document ready when can I do it?
As clearly the browser only scrolls to the HTML element from hash only after the whole page is loaded - including all JS -, I think the best option is to bind actions to the scroll event of the page.
You could try something like this:
<script type="text/javascript">
$(function() {
// Retrieves the hash from URL
var hash = window.location.hash.substring(1);
// If hash length > 0 (there is actually a hash)
// And the #hash element exists on page
if(hash.length > 0 && $('#'+ hash).size() > 0){
// Binds a function to the page scroll
$(document).on('scroll', function(){
// Here's the bright part: when the browser finish loading the page, it will
// scroll right to the #hash element. So, whenever the page is scrolled, if
// the #hash element offset top matches the page scroll offset, it means the page
// was scrolled right to that element.
var elemTop = $('#'+ hash).offset().top; // Retrieve element's offset top
var docTop = $(document).scrollTop(); // Retrieve page's offset
if(elemTop == docTop){
alert('Now I do my stuff!! :)');
// Do your stuff
}
// And now you make sure "your stuff" won't happen again if the user
// accidentally scrolls precisely to the #hash element's offset by
// unbinding scroll action of the page.
$(document).unbind('scroll');
});
}
});
</script>
I hope that help you to solve your problem! Let me know if anything was unclear.