Vanilla JS + VueJS: Scroll to top of div on button click - javascript

I have an app created using VueJS. It is a multistep form with a next button.
You can view the app working here:
https://staging.evbox.com/configurator.html
The issue I am trying to solve, is once the user clicks the next button, the top of the following question is visible. Can someone help me with a vanilla JS solution or some advice?
The button html:
<button class="button-container__next" type="button" #click="goToNextStep()">Next</button>
And the function is:
goToNextStep: function () {
this.currentStep++
}

It seems that the scrollbar is for body. So you can do this:
goToNextStep: function () {
this.currentStep++;
window.scrollTo(0, 0);
}
If the main scrollbar is not attached to the body, try two following lines:
document.body.scrollTop = 0; // For safari
document.documentElement.scrollTop = 0;

I solved it by doing the following. I found this script but I have to be honest im not really sure how it works. Can someone explain it to me?
goToNextStep: function () {
this.currentStep++
let myDiv = document.getElementById('wrapper');
scrollTo(document.body, myDiv.offsetTop, 100);
function scrollTo(element, to, duration) {
if (duration < 0) return;
var difference = to - element.scrollTop;
var perTick = difference / duration * 2;
setTimeout(function() {
element.scrollTop = element.scrollTop + perTick;
scrollTo(element, to, duration - 2);
}, 10);
}
}
I also added this to the CSS:
html { height: 100%; overflow:auto!important; }
body { height: 100%!important; }

Related

how to refresh two functions without reloading the page in html

i need to refresh the blockrandompos and animblock without refreshing the page
var player = document.getElementById("player");
var block = document.getElementById("block");
function goleft(argument) {
player.classList.add("animatel");
setTimeout(function() {
player.classList.remove("animatel");
}, 1);
console.log("left");
}
function goright(argument) {
player.classList.add("animater");
console.log("right");
}
function blockrandompos(argument) {
var block3 = document.getElementById("block");
var posleftblock = Math.floor(Math.random() * 370) + 1; //random numbers from 200 to 300 pos
var info = block3.setAttribute("style", "width:30px; height:30px; position: relative; left:" + posleftblock + "px;"); //block settings
console.log(posleftblock);
}
function animblock(argument) {
block.classList.add("animationblock");
console.log(block.classList);
}
blockrandompos()
animblock()
You are probably looking for an event and subsequently an event-listener that can call a function when the event takes place. Beyond onLoad and onClick, there are a crazy amount of events that you can use.
https://developer.mozilla.org/en-US/docs/Web/Events
So the question is, when do you want to run your functions exactly? Maybe we can help tell you which event to use.

My JS code doesn't execute when I scroll down

The main problem is when I scroll down with the mouse my vanilla JS code doesn't execute because forEach is not a function. I don't know why this happens, I hope you can help me with this issue, thanks!
const boxes = document.querySelector(".box");
// event listener on scroll
window.addEventListener("scroll", animateDiv);
// visible content on load
animateDiv();
function animateDiv() {
const animateTrigger = (window.innerHeight / 5) * 4;
boxes.forEach((box) => {
// height of div from in comparison to scroll
const divTop = box.getBoundingClientRect().top;
if (divTop < animateTrigger) {
box.classList.add("show");
} else {
box.classList.remove("show");
}
});
}
I think you need to use this
https://developer.mozilla.org/en-US/docs/Web/API/Document/querySelectorAll
And not querySelector

How to prevent iOS keyboard from pushing the view off screen with CSS or JS

I have a responsive web page that opens a modal when you tap a button. When the modal opens, it is set to take up the full width and height of the page using fixed positioning. The modal also has an input field in it.
On iOS devices, when the input field is focused, the keyboard opens. However, when it opens, it actually pushes the full document up out of the way such that half of my page goes above the top of the viewport. I can confirm that the actual html tag itself has been pushed up to compensate for the keyboard and that it has not happened via CSS or JavaScript.
Has anyone seen this before and, if so, is there a way to prevent it, or reposition things after the keyboard has opened? It's a problem because I need users to be able to see content at the top of the modal while, simultaneously, I'd like to auto-focus the input field.
first
<script type="text/javascript">
$(document).ready(function() {
document.ontouchmove = function(e){
e.preventDefault();
}
});
then this
input.onfocus = function () {
window.scrollTo(0, 0);
document.body.scrollTop = 0;
}
For anyone stumbling into this in React, I've managed to fix it adapting #ankurJos solution like this:
const inputElement = useRef(null);
useEffect(() => {
inputElement.current.onfocus = () => {
window.scrollTo(0, 0);
document.body.scrollTop = 0;
};
});
<input ref={inputElement} />
I struggled with this for awhile, I couldn't find something that worked well for me.
I ended up doing some JavaScript hackery to make it work.
What I found was that Safari wouldn't push the viewport if the input element was in the top half of the screen. That was the key to my little hack:
I intercept the focus event on the input object and instead redirect the focus to a invisible (by transform: translateX(-9999px)). Then once the keyboard is on screen (usually 200ms or so) I trigger the focus event on the original element which has since animated on screen.
It's a kind of complicated interaction, but it works really well.
function ensureOffScreenInput() {
let elem = document.querySelector("#__fake_input");
if (!elem) {
elem = document.createElement("input");
elem.style.position = "fixed";
elem.style.top = "0px";
elem.style.opacity = "0.1";
elem.style.width = "10px";
elem.style.height = "10px";
elem.style.transform = "translateX(-1000px)";
elem.type = "text";
elem.id = "__fake_input";
document.body.appendChild(elem);
}
return elem;
}
var node = document.querySelector('#real-input')
var fakeInput = ensureOffScreenInput();
function handleFocus(event) {
fakeInput.focus();
let last = event.target.getBoundingClientRect().top;
setTimeout(() => {
function detectMovement() {
const now = event.target.getBoundingClientRect().top;
const dist = Math.abs(last - now);
// Once any animations have stabilized, do your thing
if (dist > 0.01) {
requestAnimationFrame(detectMovement);
last = now;
} else {
event.target.focus();
event.target.addEventListener("focus", handleFocus, { once: true });
}
}
requestAnimationFrame(detectMovement);
}, 50);
}
node.addEventListener("focus", handleFocus, { once: true });
Personally I use this code in a Svelte action and it works really well in my Svelte PWA clone of Apple Maps.
Video of it working in a PWA clone of Apple Maps
You'll notice in the video that the auto-complete changes after the animation of the input into the top half of the viewport stabilizes. That's the focus switch back happening.
The only downside of this hack is that the focus handler on your original implementation will run twice, but there are ways to account for that with metadata.
you could also do this if you don't want scrollTo the top(0, 0)
window.scrollBy(0, 0)
const handleResize = () => {
document.getElementById('header').style.top = window.visualViewport.offsetTop.toString() + 'px'
}
if (window && window.visualViewport) visualViewport.addEventListener('resize', handleResize)
Source: https://rdavis.io/articles/dealing-with-the-visual-viewport
In some situations this issue can be mitigated by re-focusing the input element.
input.onfocus = function () {
this.blur();
this.focus();
}
Both IOS8 and Safari bowsers behave the same for input.focus() occuring after page load. They both zoom to the element and bring up the keyboard.(Not too sure if this will be help but have you tried using something like this?)
HTML IS
<input autofocus>
JS is
for (var i = 0; i < 5; i++) {
document.write("<br><button onclick='alert(this.innerHTML)'>" + i + "</button>");
}
//document.querySelector('input').focus();
CSS
button {
width: 300px;
height: 40px;
}
ALso you will have to use a user-agent workaround, you can use it for all IOS versions
if (!/iPad|iPhone|iPod/g.test(navigator.userAgent)) {
element.focus();
}

Why window onscroll event does not work?

I want to execute the window onscroll event, but I don't know why it doesn't work on all browsers(firefox, chrome, etc), and there is no errors occurred.
Full code:
var elem = document.getElementById('repeat');
var show = document.getElementById('show');
for (i = 1; i <= 300; i++) {
elem.innerHTML += i + "<br/>";
}
window.onscroll = function () {
show.innerHTML = document.body.scrollTop;
};
#show {
display:block;
position:fixed;
top:0px;
left:300px;
}
<pre id="repeat"></pre>
<div style="position:relative;">
<div id="show">x</div>
</div>
Also jsfiddle:
http://jsfiddle.net/sqo0140j
What is the problem ?
You said something interesting:
x changed to 0 and remains as is.
The only way in your code that can happen is if the onscroll function block makes a change because your HTML sets x.
If your window.onscroll = function() is indeed firing, but you are not getting the right scroll position (i.e. 0), try changing the way the scroll position is returned:
window.onscroll = function () {
show.innerHTML = document.documentElement.scrollTop || document.body.scrollTop;
};
I found out that document.documentElement.scrollTop always returns 0 on Chrome. This is because WebKit uses body for keeping track of scrolling, but Firefox and IE use html.
Please try your updated snippet:
var elem = document.getElementById('repeat');
var show = document.getElementById('show');
for (i = 1; i <= 300; i++) {
elem.innerHTML += i + "<br/>";
}
window.onscroll = function () {
show.innerHTML = document.documentElement.scrollTop || document.body.scrollTop;
};
#show {
display:block;
position:fixed;
top:0px;
left:300px;
}
<pre id="repeat"></pre>
<div style="position:relative;">
<div id="show">x</div>
</div>
For me the statement document.body.scrollTop; works well in Chrome and Opera, but on Firefox returns 0.
Viceversa the statement document.documentElement.scrollTop; works good on Firefox but not in Chrome and Opera...
Maybe document.body.scrollTop; is not well supported by FF
Possible Solutions:
I tried:
Math.max(document.body.scrollTop, document.documentElement.scrollTop);
and
document.body.scrollTop || document.documentElement.scrollTop;
They both works well on all above browsers.
I had also the same problem , but I didn't know the proper reason for that .
In my case
window.onscroll = function () {
console.log(document.documentElement.scrollTop || document.body.scrollTop);
};
this code didn't work even after removing margin:0; and padding:0; .
But by mention the addEventListener on the document.body it is worked
document.body.addEventListener('scroll',()=>{
console.log(document.documentElement.scrollTop || document.body.scrollTop);
})
This question has been answered, but I wanted to include details of my situation that prevent onscroll from working.
I have datacontainer that had its own scroll bar which overrides the built in window scroll bar. I didnt notice this until I started giving a more thorough look at the elements on the page using chrome developer. My outer tag looked like this,
This caused two scroll bars to appear on the left. This was because the property, overflow:auto, was telling the data container to make another scroll bar.
Once I removed the overflow:auto I could now correct hit the onscroll event.
Because a lot of people use W3Schools i wanted to leave this here.
This simple scroll event wasn't firing
window.onscroll = function () { myFunction() };
var navbar = document.getElementById("navbar");
var sticky = navbar.offsetTop;
function myFunction() {
if (window.pageYOffset - 20 >= sticky) {
navbar.classList.add("sticky");
}
}
Until I removed < link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
and everything was working again flawlessly.
For people having issues with this function. Another reason that it looks like it is not working is that you define it multiple times.
window.onscroll = function() {
console.log('scroll 1');
};
// some other js code
window.onscroll = function() {
console.log('scroll 2');
};
Only the last one gets executed since it overwrites your first declaration. The solution is then
window.addEventListener('scroll', function() {
console.log('scroll 1');
})
window.addEventListener('scroll', function() {
console.log('scroll 2');
})

lock a div on header when window scrolled past element

I want a circle div to lock in the header when the user scrolls past in.
I'm using the following code but it doesn't work
var circle$ = $('.circle'),
oCircleBottom = circle$.offset().top + circle$.outerHeight(true),
window$ = $(window);
window$.scroll(function() {
if (window$.scrollTop() > oCircleBottom) {
}
}.bind(this));
I want to perform an action when the user scrolls pass the circle div; however, the code above does not seem to work. Is oCircleBottom computed correctly?
Enclose your code in $(document).ready function
$(document).ready(function () {
var circle$ = $('.circle'),
oCircleBottom = circle$.offset().top + circle$.outerHeight(true),
window$ = $(window);
window$.scroll(function () {
if (window$.scrollTop() > oCircleBottom) {
$('.circle').css({
position: 'fixed',
top: '0',
left: '0'
});
}
else{
$('.circle').css({
position: 'static'});
}
}.bind(this));
});
You need to take window height into account because if the height of the page isnt enough to scroll down, your code doesnt work. Take a look at this example
However, if the increase page height, you code will work fine without subtracting window height. Take a look at this example
Hence, its better to subtract the window height. jsFiddle
$(window).bind('scroll', function() {
if($(window).scrollTop() >= $('.circle').offset().top + $('.circle').innerHeight() - window.innerHeight) {
//Do you stuff
}
});

Categories

Resources