Hello I found a code that switches the content of your body when you click a button from this codepen and I would like to add a feature that it waits with switching the content until the page is done scrolling for cross browser support I use this script for my smooth scroll:
// add event listener on load
window.addEventListener('load', function() {
// scroll into view
var btns = document.querySelectorAll('.scrollwrap');
for (let i = 0; i < btns.length; i++) {
btns[i].addEventListener('click', function(e) {
e.preventDefault();
document.querySelector('.wrapper').scrollIntoView({
behavior: 'smooth'
});
document.getElementById("wrap").scrollTop -= 100;
});
}
I got this script from here.
How can I make it wait until the page is fully scrolled to the set destination?
I think you can try to catch Event
const wrap = document.getElementById("wrap");
wrap.addEventListener('scroll', function(e) {
const lastKnownScrollPosition = wrap.scrollTop;
Here you can do what you want to do =)
});
While the page scrolls, if the page has any loading icon or anything indicating new contents loading, you need to get the selector of that icon or whatever.
Then do something like this.
var checkExist = setInterval(function() {
if ($('#loadingIcon').length) {
console.log("Exists!");
clearInterval(checkExist);
}
}, 100); // check every 100ms
Refer to this for more information.
To get selector to your loading icon, you will have to pause the dom by pressing F8 and then inspecting the loading icon. Pausing the dom will prevent the icon from disappearing.
Related
How can you synchronize scrollbars between two elements without recursively calling each event?
Usually you would expect the following code:
$div1.scroll(function() {
$div2.scrollTop($div1.scrollTop());
});
$div2.scroll(function(){
$div1.scrollTop($div2.scrollTop());
});
But in this case, if you scroll $div1 1px, it will scroll $div2 1px as well, which will prompt the $div2 scroll event to fire and re-apply the scroll position to $div1. While this might not seem like an issue, when this code is applied to a page and you naturally scroll with a mouse, it scrolls in 1px increments because the handlers call eachother and don't allow the scroll to flow.
So, how would you solve this issue?
Example: https://jsfiddle.net/axtn/a91fsar3/2
Found out a good solution. Debouncing does the trick.
You can use a combination of timers and bools to make sure the element is being scrolled by the user. Thus, when the scroll event is rapidly and consecutively fired (like when a user scrolls down), it prevents the handlers from recursively calling eachother. The following code does the trick:
var userScroll1 = true;
var userScroll2 = true;
var timer;
$div1.scroll(function() {
if(userScroll2) {
userScroll1 = false;
clearTimeout(timer);
$div2.scrollTop($div1.scrollTop());
timer = setTimeout(function() {
userScroll1 = true;
}, 100);
}
});
$div2.scroll(function(){
if(userScroll1) {
userScroll2 = false;
clearTimeout(timer);
$div1.scrollTop($div2.scrollTop());
timer = setTimeout(function() {
userScroll2 = true;
}, 100);
}
});
Check out the properly functioning jsbin: https://jsfiddle.net/axtn/a91fsar3
I'm trying to solve a quite simple task but stuck with JQuery behavior.
I have a HTML button which I disable (add disabled attribute) right after it get clicked to prevent multiple clicks, do something long running (i.e. update DOM with a lot of elements) and enable the button back.
Problem is that even the button is disabled jquery queues all clicks on it and raise my click handler right after it became enabled.
According to JQuery docs it should not raise events for a disabled element.
Bellow is my code. Open JS console, click two times on the button, notice couple 'START --' messages in the console.
<div>
<button id="mybtn" type="button">Find</button>
</div>
var btnElement = $('#mybtn');
btnElement.click(doClick);
function doClick() {
var btnElement = $('#mybtn');
btnElement.attr('disabled', true);
console.log('START --' + Date());
for (var i = 0; i < 70000; i++) {
var el = $('#mybtn');
var w = el.width();
w += 10;
}
console.log('STOP --' + Date());
el.attr('disabled', false);
}
Here is my solution http://jsfiddle.net/DRyxd/8/
var btnElement = $('#mybtn');
var buttonIsBusy = false;
function doHeavyJob () {
console.log('START --' + Date());
for (var i = 0; i < 70000; i++) {
var el = $('#mybtn');
var w = el.width();
w += 10;
}
var timeoutId = setTimeout (unblockTheButton, 0);
console.log('STOP --' + Date());
}
function unblockTheButton () {
console.log('unblockTheButton');
btnElement.attr('disabled', false);
buttonIsBusy = false;
}
function doClick() {
console.log('click', buttonIsBusy);
if (buttonIsBusy) {
return;
}
btnElement.attr('disabled', true);
buttonIsBusy = true;
var timeoutId = setTimeout (doHeavyJob, 0);
}
btnElement.click(doClick);
The issue here is that click-handler function has not finished and browser has not refreshed the DOM. That means that block was not yet applied to the button. You can try pushing your heavy code out of the current context like this:
function someHeavyCode () {
/* do some magic */
}
var timeoutId = setTimeout(someHeavyCode, 0);
This will push your heavy code out of the current context.Letting browser to update the DOM first and only after execute the heavy code.
While the heavy code is executed, browser (at least Chrome) kept the user input queue somewhere in other place (or most-likely other thread). And as soon as heavy code completes - it feeds the DOM with all that queued events. We need to ignore that events somehow. And I use the setTimeout with 0-time again. Letting the browser do what was queued before unblocking the button.
WARNING But be extremely careful with this technique. Browser will still be blocked and if you spawn a lot of such blocks it may hang.
See also this Why is setTimeout(fn, 0) sometimes useful? and consider using webworkers.
P.S. Blocking a user input in such a way is not a good approach, try to rethink what you are going to do, probably there is a better solution for that.
I am trying to implement kind of player on my website.
If press 'Play' button, the music starts and the page smoothly scrolls down.
But when you press 'Mute' button (function(){music.volume=0}) I am not sure why the page appears at the top again. window.scroll() doesn't do anything without delay. So i am using setTimeout function to scroll the page on the current place. The problem is that in Opera and IE setTimeout takes about 10 ms, so when i click 'Mute' button i see like ticks to top and back. In chrome it takes only 2 ms and there is no problems.
Now when i decide to create my own timeout function the window.scroll() does not work again.
Here is my code:
var isMuted = false;
muteButton.onclick = function() { ////This function works with big delay.
if (!isMuted) {
mainAudio.volume = 0;
isMuted = true;
} else {
mainAudio.volume = bgAudioTrackVolume;
isMuted = false;
}
setTimeout(function() {
window.scroll(0, offset); /// Works
}, 0)
};
Change setTimeout with:
i = 9542155.873; /// I have tried delay time from 1ms - 250ms by changing this value.
while (i > 0.00001) {
i = i / 1.0001234567;
if (i < 0.00001) {
window.scroll(0, offset); /// Does not do anything. Strange! Have tried to change variable with a number.
}
}
Every time i check offset value, it is always available before calling scroll function.
I know that my problem is not usual and i am realy need your help.
The reason that the page scrolls to the top is that you are using a link with the empty bookmark #, which represents the top of the page. The reason that the scroll method doesn't work without a timeout is that jumping to the bookmark happens after the event handler.
Instead of trying to scroll the page back to where it was, just stop the default action of the link by returning false from the event handler:
var isMuted = false;
muteButton.onclick = function() {
if (!isMuted) {
mainAudio.volume = 0;
isMuted = true;
} else {
mainAudio.volume = bgAudioTrackVolume;
isMuted = false;
}
return false;
};
Alternatively, use some other element than a link.
I want that when a user clicks on any external link (identified by either particular id or class) on my site then he should get a popup with a counter of 10 seconds, after 10 seconds the popup should close and the user should be able to access the external URL. How can this be done? I'm able to show a warning like below but I don't know how to add timeout to it, also this is a confirm box, not a popup where I can add some div and more stuff for user to see until the counter stops.
$(document).ready(function(){
var root = new RegExp(location.host);
$('a').each(function(){
if(root.test($(this).attr('href'))){
$(this).addClass('local');
}
else{
// a link that does not contain the current host
var url = $(this).attr('href');
if(url.length > 1)
{
$(this).addClass('external');
}
}
});
$('a.external').live('click', function(e){
e.preventDefault();
var answer = confirm("You are about to leave the website and view the content of an external website. We cannot be held responsible for the content of external websites.");
if (answer){
window.location = $(this).attr('href');
}
});
});
PS: Is there any free plugin for this?
I've put together a little demo to help you out. First thing to be aware of is your going to need to make use of the setTimeout function in JavaScript. Secondly, the confirmation boxes and alert windows will not give you the flexibility you need. So here's my HTML first I show a simple link and then created a popup div that will be hidden from the users view.
<a href='http://www.google.com'>Google</a>
<div id='popUp' style='display:none; border:1px solid black;'>
<span>You will be redirected in</span>
<span class='counter'>10</span>
<span>Seconds</span>
<button class='cancel'>Cancel</button>
</div>
Next I created an object that controls how the popup is displayed, and related events are handled within your popup. This mostly is done to keep my popup code in one place and all events centrally located within the object.
$('a').live('click', function(e){
e.preventDefault();
popUp.start(this);
});
$('.cancel').click(function()
{
popUp.cancel();
});
var popUp = (function()
{
var count = 10; //number of seconds to pause
var cancelled = false;
var start = function(caller)
{
$('#popUp').show();
timer(caller);
};
var timer = function(caller)
{
if(cancelled != true)
{
if(count == 0)
{
finished(caller);
}
else
{
count--;
$('.counter').html(count);
setTimeout(function()
{
timer(caller);
}, 1000);
}
}
};
var cancel = function()
{
cancelled = true;
$('#popUp').hide();
}
var finished = function(caller)
{
alert('Open window to ' + caller.href);
};
return {
start : start,
cancel: cancel
};
}());
If you run, you will see the popup is displayed and the countdown is properly counting down. There's still some tweaks of course that it needs, but you should be able to see the overall idea of whats being accomplished. Hope it helps!
JS Fiddle Sample: http://jsfiddle.net/u39cV/
You cannot using a confirm native dialog box as this kind of dialog, as alert(), is blocking all script execution. You have to use a cutomized dialog box non-blocking.
You can use for example: jquery UI dialog
Even this has modal option, this is not UI blocking.
Consdier using the javascript setTimeout function to execute an action after a given delay
if (answer){
setTimeOut(function(){
//action executed after the delay
window.location = $(this).attr('href');
}, 10000); //delay in ms
}
I have this page: http://www.yasyf.com/services.html, in which a video autoplays. I would like to have it so that once the video finishes playing (a set amount of time), the page automatically scrolls down to the text, using a jQuery scrollto with timed delay, but only if the page has not yet been scrolled. Is this possible?
See here the example I made for you.
MORE INFO
Depending on the player you're using, a video finished event could be available. You can then attach the scrollTo function to it. You can read more about this event here:
YOUTUBE
FLOWPLAYER
ADOBE
If you can, give also a look to this incredibly useful resource and this spec about video in HTML5.
About vid.ly :
It seems to me that they use an HTML5 with Flash fallback player. See here the "how can I use vid.ly" section.
JS code :
// add a scrollTo method to jQuery
$.fn.scrollTo = function(duration){
if(duration == null){ duration = 1000; }
var offset = $(this).offset().top - $(window).height()/2 + $(this).height();
$('html,body').animate({ scrollTop: offset}, duration);
}
// Then when the dom is loaded
$("document").ready(function() {
//for HTML5 (for flash please see the ADOBE link above.)
$("video").bind("ended", function() {
// Log on console just for debug
console.log("autoplay ended! About to scroll to...");
// scroll to a div with id="scroll_to_here"
$('#scroll_to_here').scrollTo();
});
});
var scrolled = false;
$(window).scroll(function(){
scrolled = true;
});
var scroll_timer = setTimeout(function(){
if(scrolled !== true)
{
// scroll to whatever
}
},10000);
This is a simple script to do that. I assume scroll / keydown / mouse click to say "the user has interacted with the page, don't auto-scroll."
(function() {
var scrollPage = function() {
$.scrollTo(xyz);
};
var c = setTimeout(scrollPage, 35000);
$(document.body).bind('scroll mousedown keydown', function() {
clearTimeout(c);
});
})();
Let me know if this helps.