Detect scroll intent - javascript

I once came across a script or article about the following issue:
Imagine a page which is scrollable with multiple elements inside that are also scrollable. When scrolling down the page, the cursor will come across elements that are scrollable, and they will take focus. Resulting in having to either remove your cursor from that element, or scrolling down that element before you're able to scroll the entire page again.
The demo I saw fixed that issue by only focussing on the scrollable elements after cursor movement or some sort of interruption of the scrolling. So when you would scroll down the page you could keep scrolling (floating over the scrollable elements) without interruptions.
Does anyone know what script I'm talking about?

If I understood ok otherwise let me know: if you want to detect scroll event then you have to use scroll() from jquery page.
try this example:
<!DOCTYPE html>
<html>
<head>
<style>
div { color:blue; }
p { color:green; }
span { color:red; display:none; }
</style>
<script src="http://code.jquery.com/jquery-latest.js"></script>
</head>
<body>
<div>Try scrolling the iframe.</div>
<p>Paragraph - <span>Scroll happened!</span></p>
<script>
$("p").clone().appendTo(document.body);
$("p").clone().appendTo(document.body);
$("p").clone().appendTo(document.body);
$(window).scroll(function () {
$("span").css("display", "inline").fadeOut("slow");
});
</script>
</body>
</html>
See here the demo: http://jsfiddle.net/4M7XK/ (minimize the height of the bottom right block)

I am sorry, but I do not now the original article you are referring to, but here is idea, how I would make it work.
Once the users starts scrolling. (e.g. $(window).scroll(function(){...}) from jQuery ), I would place a empty div to cover the whole page from top to bottom. This element would be above all other possibly scrollable divs, preventing them every catching the scroll event. It element has to be removed with a few miliseconds timeout.
$(window).scroll(function(){
var $cover = $('<div style="position: absolute; left: 0px; top: 0px; width: 100%; height: '+ $(document).height() + 'px; z-index: 100000">asdasd</div>')
$cover.appendTo($("body"));
setTimeout(function(){
$cover.remove();
},200);
});

Related

How to detect the bottom viewport scrollbar scrolling horizontally with Javascript / Jquery

I am using the following code with a JS .scroll to detect when the bottom viewport scroll bar is being scrolled sideways (and then do something based on that event). It doesn't trigger when I target the HTML tag, but if I target the BODY tag with the .scroll, it does trigger.
The problem I'm seeing with the BODY tag scroll bar, is that it will only show up if you scroll all the way to the bottom of the 5000px I have the inner div set to. With what I believe is the natural, HTML-bottom-of-the-viewport-scroll-bar, it's always just sitting at the bottom of the browser window if there's something to scroll to, but I don't know how to detect it moving.
Is there a way for .scroll to detect it being scrolled, or is there another method that can detect if the viewport is scrolling sideways?
<html>
<head>
<title>Side Scroll</title>
<script src="js/jquery.min.js"></script>
</head>
<body>
<style>
.extra_wide_div {
width: 6000px;
height: 5000px;
background: linear-gradient(to right, red , yellow);
}
html {
overflow-x: auto;
overflow-y: auto;
}
body {
/*
overflow-x: auto;
overflow-y: hidden;
*/
}
</style>
<div class="extra_wide_div">
Hello
</div>
<script>
$scrollTarget = $('html');
$scrollTarget.scroll(function(e) {
console.log("scroll triggered");
});
</script>
</body>
</html>
You should select both the html and body tags to detect scrolling.
var $scrollTarget = $('html, body');
$scrollTarget.scroll(function(e) {
console.log("scroll triggered");
});
This is because different browsers attach the scrollbar to different tags. The browsers Firefox and Internet Explorer utilize the html portion of this selector and webkit browsers like Chrome and Safari respond to the body.
For your CSS, you should target both the html and body tags when setting a fixed height.
html, body{
height: 1000px;/*For scrolling*/
}
To set the height with Javascript, you can use jQuery's .css() function.
$('html, body').css("height", "1000px");
Demo:
$('html, body').css("height", "1000px");
$('html, body').animate({scrollTop: 500}, 500);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
The answer can be found here (you don't target body nor html: you target 'window' without the quotes): How to detect horizontal scrolling in jQuery?

Prevent browser viewport from sticking to bottom when page height increases in runtime?

Modern browsers seem to have a feature where the viewport sticks to bottom when page height increases. What actually happens is that browser scrolls the viewport at the same rate as height being increased when initial position is at (or very close to) the bottom of the page. This results in appearance as if page is expanding upwards instead of downwards.
How can this feature be disabled for a certain page using CSS or JS, so that the page would always visually expand downwards?
This of course, also happens when added element's height is expanded animated. For this reason, if possible, I would want to avoid resetting scroll position afterwards to prevent visible jump. The demo of this "feature" (that seems to happen only within rare conditions) interacting with the viewport and drop animation can be observed in the gif below.
I know there must be a way, otherwise every site with infinite scroll would suffer from an infinite loop. Counter argument: Chrome appears not to do this for containers that surpass certain height limit. So maybe infinite-scroll sites don't even bother addressing this in their sites.
Check this fiddle. You can observe that in Chrome, the first container snaps to the bottom, while the other divs has a scroll relative to the top. In Firefox or IE 11, you cannot observe this behavior.
This happens when the top bound of the last element on a scroll container is above the top bound of the container. The browser decides that the last element is what the user is interested in and decides to stay in that position.
The last div doesn't snap to the bottom because the scroll happens relative to the top bound of the last element and the last element is growing.
If you want a different behavior, I would not suggest handling it with Javascript, but I would suggest changing your layout considering these rules. For example the last div should be the growing one, instead of the previous siblings of it.
Obligatory code:
var div = document.querySelectorAll('.growing');
var height = 500;
setInterval(function(){
height += 100;
div[0].style.height = height + 'px';
div[1].style.height = height + 'px';
div[2].style.height = height + 'px';
},1000);
.start, .end{
height: 110px;
}
.start{
background: red;
}
.end{
background: green;
}
.growing{
background: yellow;
}
.cnt1,.cnt2,.cnt3{
overflow: auto;
border: 5px solid black;
margin: 5px 0;
scroll-snap-type: mandatory;
}
.cnt1{
height: 100px;
}
.cnt2{
height: 120px;
}
.cnt3{
height: 100px;
}
<div class="cnt1">
<div class="start"></div>
<div class="growing"></div>
<div class="end"></div>
</div>
<div class="cnt2">
<div class="start"></div>
<div class="growing"></div>
<div class="end"></div>
</div>
<div class="cnt3">
<div class="start"></div>
<div class="end"></div>
<div class="growing">
Content
</div>
</div>
Edit:
If the bounds of the growing div is in the visible area, the scroll is relative to the top of the growing div. So you can hack CSS to show the growing div, but actually not show it.
In this fiddle I have used two different CSS hacks. First one is adding a negative margin bottom and a positive padding bottom at same amount. The second hack is adding an :after element to the growing div but hide its visibility.
for click events, use blur, avoid scrollTo
It seems like this issue is focus-related. I came across a similar bug and when the element that triggered a height change was switched to an unfocusable element, like a div, the screen jumping disappeared. This clearly isn't a great solution because we should be able to use buttons! It also implicates focus in this strange behavior. Further experimentation led to blurring the trigger element before the height change, which solves the problem without moving the viewport. I've only tried this with click events so I'm not sure if it works for drag n drop.
codepen that showcases viewport jumping with accordions and a blur fix
function handleClick(e) {
e.currentTarget.blur();
// code to change height
}
Do you mean that when you scroll to the bottom, and a piece of content gets added, you stay at the bottom? Because the solution for that is real simple:
Option 1
Store the current scrolloffset to the top (eg how many px you've scrolled down)
Add new content
Set scrolloffset to the top to the stored value
Those last two steps can be done so fast that the user wont notice.
Option 2
Not 100% sure this works, but i'm guessing it does:
When the visitor scroll to the bottom, always scroll them back 3px. This way, they're not at the bottom at the point where new content gets added, so the browser stays where it is.
As per my understanding regarding your requirement, I have given a working jsfiddle sample.
Hope it would help to you.
If you expect something more, feel free to add comment.
Cool!
$(function(){
var height = 200;
var pos = 0;
setInterval(function(){
if($(document).height() >= $(window).height()){
var height = $('.container1').height();
$('.container1').height(height + 20);
pos = pos + 20;
$(window).scrollTop(pos);
}
}, 1000);
});
.container1 {
border: 1px solid #ccc;
min-height: 200px;
background: #ccc;
height: auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="container1">
<p>11</p>
<p>12</p>
<p>13</p>
</div>
All of your draggable elements are in a container with no auto overflow, when you drag and drop your elements the whole page scrolls due to dragging.
Instead of that do as:
<div class="container">
<!-- Place all your draggable elements here -->
</div>
set a max-height and overflow of the container class as:
.container {
max-height: 400px;
overflow: auto;
}
Now when you drag and drop your elements, instead of the whole page, the only container will scroll.
After implementing this solution, it will look like this.
Before dragging.
While dragging.
Hope this helps you.

Hiding background elements is a good idea?

I have a mobile website. It's ajax based and when clicking a row from a table in the main screen, a div is populated with ajax data and then fades in, occupying the whole window, in fixed position. Then the user can navigate the div like if it's a separate window but can back out to the main table (fading out the fixed div). So, when the user navigate the fixed div, in reality there is also the main page body in the background. Would disabling/hiding the background main page make the website more lightweight for a mobile or not? The structure is similar to:
<html>
<head>
<script>
function navigateIn(url){
$.get(url,function(data){ //get data from url
$('#navigate').html(data); //put data into div
$('#navigate').fadeIn(200,function(){ //fade in div
//Now, after div is faded in, hide the background:
$('#main').css('overflow','hidden'); //Is this helpful?
$('#main').css('visibility','hidden'); //Is this helpful?
$('#main').css('display','none'); //Is this helpful? This void the scrolltop of the body, so it's not my greatest choice
});
});
}
function navigateOut(){
//Display the main page before back out!
$('#main').css('overflow','');
$('#main').css('visibility','');
$('#main').css('display','');
$('#navigate').fadeOut(200);
}
</script>
<style>
#navigate {
position: fixed;
height: 100%;
width: 100%;
top: 0; bottom: 0; left: 0; right: 0;
overflow: auto;
}
</style>
</head>
<body>
<div id="main">
<button onclick="navigateIn('http://www.test.com');">Navigate In!</button>
</div>
<div id="navigate"></div>
</body>
</html>
Here's a jsfiddle which is showing what I'm talking about: jsfiddle
But the effect is a bit different because it's not full screen view.
I don't actually know how to test by myself if it's helpful or not (or even worse) to hide the content. So I ask to you.
PS: I know it's not a beautiful effect when fading in, but in reality I made a slideIn from right extension, so it's much better...

How to automatically scroll when div expands at bottom of page?

Lately I have come into a dead end. I'm trying to expand the footer (#footernotes) and that works, it's basically a div behind the body (done with z-index) and when you click on a button it moves down. The scroll bar goes with it too, meaning that the page is now longer.
But what I'm trying to do is to make the viewport move with the expanded div. What happens now is that when I press the button (.secret) the div (#footernotes) comes in but it is still out of the viewport UNLESS you manually scroll to view the longer page.
So to some it up, how do you make the viewport automatically scroll down after you expanded the page? In other words, how do you make the viewport stay at the bottom of the page.
Here is my code:
<script>
$(document).ready(function(){
$('.secret').click(function(){
$("#footernotes").animate({top: "100px"}, 1000);
return false;
});
});
</script>
<div id="footer">
</div>
<div id="footernotes">
</div>
</div> <!-- end #footer -->
And the CSS for #footernotes
#footernotes {
background-color: red;
width: 100%;
position: relative;
top: -80px;
height: 150px;
z-index: -400;
}
EDIT: While typing up the question I figure out the answer, you have to use the scrollTop. I have added the line code in the example below:
<script>
$(document).ready(function(){
$('.secret').click(function(){
$("#footernotes").animate({top: "100px"}, 1000);
$('body,html').animate({scrollTop: "210px"},1000);
return false;
});
});
</script>
You can still answer this if you think there is a better way, I just thought I'll leave this question posted in case other people have the same question.
document.getElementById('divID').scrollIntoView();
try and see if that would do the job.
It can be done using Jquery method .focus(). just need to add
$(divname / .class / #id).focus();
and it would be done.

iOS Safari onscroll event within nested element

My ultimate aim is to have an inline div on my page which horizontally scrolls natively (using -webkit-overflow-scrolling: touch) that also snaps.
I can achieve this without -webkit-overflow-scrolling because I have access to the ontouchend event, so I can calculate my snap when that happens, however, to achieve the best possible UX for this feature, I want to use native-like scrolling on this element.
The problem with using -webkit-overflow-scrolling is that using a flick/some force, the div will continue to scroll for a bit after you've taken your finger off (i.e. AFTER ontouchend has fired); which means my snap calculates before the scrolling is finished.
Having spent a long time trying to find ways round, I have had no success yet.
In the entire page context, safari fires the onscroll event when a scroll is finished. My question is, is it possible to have this event fire within the context of an element? i.e. have onscroll fire inside <div id="slideShow">?
If not, is it possible to either
(a) Access velocity of a ontouchmove for example, so I could calculate when to run the snap?
or
(b) Emulate -webkit-overflow-scroll: touch (the elasticity and velocity effects).
NOTE: For the sake of example, using iPad w/ iOS5.
The scroll event gets fired on every scrolling container separately, and on iOS only after scrolling has stopped and is complete. You can simply listen for the scroll event on your container.
Here is an example:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8" />
<title>Test Touch Scrolling</title>
<style>
body {
font-size: 15em;
}
#outer {
height: 1200px;
width: 300px;
overflow-x: scroll;
-webkit-overflow-scrolling: touch;
}
#inner {
width: 600px;
}
</style>
<script>
document.addEventListener("DOMContentLoaded", function() {
var list = document.getElementById("outer");
list.addEventListener("scroll", function(event) {
alert("Scroll has ended for element with ID '" + event.currentTarget.id + "'");
});
}, false);
</script>
</head>
<body>
<div id="outer">
<div id="inner">Some text. And more.</div>
</div>
</body>
</html>
You will see the alert only when you have scrolled the text horizontally, not when the out div has been scrolled.

Categories

Resources