Scrolling past certain point does - javascript

I'm trying to use a scroll function to run a function once it passes greater than or less than <a> tags. First the starting point which is fixed on the page:
<div style="height: 200px">
<input type="text" id="starting-point" />
<div>
This is setting the starting point at 200px from the top of the page. Then the container behind it could be anything from 1000px to 3000px when scrolling (using the window as scrolling).
<div style="height: 200px;">
<input type="text" id="starting-point" />
<div>
<div style="height: 3000px;">
<!-- ... content here -->
<div style="height: 200px;">
1
</div>
<div style="height: 300px;">
2
</div>
<div style="height: 240px;">
3
</div>
etc...
</div>
What I'm trying to achieve is for each <a> tag that passes the starting point, to do show something. So when scrolling it starts at 1, once 2 reaches the starting point, something on the page (like a textbox) would switch it from 1 to 2, and so on going down, and then work in reverse going back up. This is what I have so far:
$(document).ready(function () {
window.addEventListener('scroll', function (e) {
var setStart = $('#starting-point').offset().top - $(window).scrollTop(); // starting point
var getTag = $('a');
if (setStart >= getTag) {
run function here
}else{
run function here
}
});
});
I don't know how to set a variable to when an <a> tag passes that starting point to pass it into the function to run what I need. There could be 20 <a> tags on the page. Running a for loop I don't think solves the issue.

Here is a demo on how you could do it.
There could be some other way too.
On load, we get the position of the #starting-point and all the anchors which now have the scroll_target class.
Then, on scroll, you have to determine the scrolling direction... Because the logic is slightly different going up compared to going down.
Each time it passes a "target" position, the scroll_target is decremented/incremented.
So you know which anchor just passed because of the position array.
I made a text array to update the input based on the anchor's text that just passed. It could also be the anchor's value or a data-* attribute.
I left all console logs for you to see what is going on.
$(document).ready(function(){
var startPoint = $("#starting-point").offset().top;
console.log(startPoint);
var scrollTargets_pos = [];
var scrollTargets_text = [];
var scrollingDown = true;
var lastScroll = 0;
$(".scroll_target").each(function(){
scrollTargets_pos.push($(this).offset().top);
scrollTargets_text.push($(this).text());
});
console.log(scrollTargets_pos);
console.log(scrollTargets_text);
var passedIndex = -1;
$(window).on("scroll",function(){
var scrolled = $(this).scrollTop();
console.log(scrolled);
// Scroll direction
scrollingDown = (scrolled > lastScroll);
lastScroll = scrolled;
if(scrollingDown){
// Scrolling down...
//console.log("down");
if( scrolled+startPoint > scrollTargets_pos[passedIndex+1] ){
console.log("======================");
$("#starting-point").val(scrollTargets_text[passedIndex+1]);
passedIndex++;
}
}else{
// Scrolling up...
//console.log("up");
if( scrolled+startPoint < scrollTargets_pos[passedIndex] ){
console.log("======================");
$("#starting-point").val(scrollTargets_text[passedIndex])
passedIndex--;
}
}
});
}); // End ready
.startPointDiv{
position: fixed;
top: 100px;
left:0;
width:100%;
border-top: 1px solid red;
text-align: center;
}
.content{
height: 3000px;
margin-top: 200px;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="startPointDiv">
<input type="text" id="starting-point" />
</div>
<div class="content">
<!-- ... content here -->
<div style="height: 200px;">
1
</div>
<div style="height: 300px;">
2
</div>
<div style="height: 240px;">
3
</div>
etc...
</div>

Related

How will you detect that a scroll caused by a swipe gesture has ended on a mobile web browser?

I have a horizontal slider for a web app which will be run in mobile browsers. I want to apply some styling right at the moment the scroll ends caused by a swipe gesture. This is the my html and css
.container {
display: flex;
overflow: scroll;
}
.box {
flex-shrink: 0;
width: 25%;
height: 50px;
background: yellow;
}
.box+.box {
margin-left: 15px;
}
<body>
<div class="container">
<div class="box">
</div>
<div class="box">
</div>
<div class="box">
</div>
<div class="box">
</div>
<div class="box">
</div>
<div class="box">
</div>
</div>
</body>
Please note that I am not interested in finding when a user has fully scrolled the element, I am specifically interested in when a scroll ends caused by a swipe gesture. There is no scrollStart or scrollEnd event for browsers, there is only scroll event, but scroll event contains no such info allowing me to find that there are no scroll events afterwards.
There are touchstart and touchend events that could help you do what you want to do.
Check this out:https://developer.mozilla.org/en-US/docs/Web/API/Touch_events
The question is quite old, but I couldn't find the answer, and I have just had to solve the problem myself, so I thought I can share this.
On a mobile device, after the swipe is done, and after touchEnd event, scrolling still takes some time. This makes it hard to manipulate scrollLeft and scrollTop properties in touchEnd callback.
I solved this with window.requestAnimationFrame (please note a polyfill is here: https://www.paulirish.com/2011/requestanimationframe-for-smart-animating/)
How it works:
On touchEnd you start recording current scroll of the container - this is currentScroll variable.
You call animation frame, and in the callback compare current scroll of the element (container.scrollLeft) with the recorded currentScroll. If they are the same, that means scrolling has ended. You can log it in the console or do anything else in here.
If they are not the same, update currentScroll to reflect current scroll position and then call animation frame with the same callback, and it will check if container is still scrolling.
Please note that in this case I used only scrollLeft property, since we are only swiping horizontally. The same can be used to test scrollTop.
var container = document.getElementById('container')
var detectScrollEnded = function(ev) {
var currentScroll = container.scrollLeft
function testIfScrolling() {
if (container.scrollLeft !== currentScroll) {
currentScroll = container.scrollLeft
console.log('still scrolling...')
window.requestAnimationFrame(testIfScrolling)
} else {
console.log('scrolling stopped!')
}
}
window.requestAnimationFrame(testIfScrolling)
}
container.addEventListener('touchend', detectScrollEnded)
.container {
display: flex;
overflow: scroll;
}
.box {
flex-shrink: 0;
width: 25%;
height: 50px;
background: yellow;
}
.box+.box {
margin-left: 15px;
}
<body>
<div class="container" id="container">
<div class="box">
</div>
<div class="box">
</div>
<div class="box">
</div>
<div class="box">
</div>
<div class="box">
</div>
<div class="box">
</div>
</div>
</body>

Where does this inaccuracy with DOM scroll events come from?

Have a look at the code below, there is a jsbin for it too here: http://output.jsbin.com/qosevogeka/
var container = document.querySelector('.container')
var firstEventHandled = false
container.addEventListener('scroll', function(e) {
if (firstEventHandled) return
console.log(e.target.scrollLeft)
firstEventHandled = true
})
.container {
display: flex;
overflow: scroll;
}
.box {
flex-shrink: 0;
width: 40%;
height: 50px;
background: yellow;
}
.box+.box {
margin-left: 15px;
}
<body>
<div class="container">
<div class="box">
</div>
<div class="box">
</div>
<div class="box">
</div>
<div class="box">
</div>
<div class="box">
</div>
<div class="box">
</div>
</div>
</body>
If you scroll the resulting view, you will see that 0 is never logged to the scroll which I expect since the scrollLeft was 0 before I started scrolling. Where does this inaccuracy with the scroll events come from? Thanks
Where does this inaccuracy with the scroll events come from? Thanks
As per documentation
The scroll event is fired when the document view or an element has
been scrolled.
So this line
console.log(e.target.scrollLeft)
is logging the e.target.scrollLeft after the scroll has happened, since this function is an event-handler which is executed after the event has happened already. And by definition, once the scroll has happened you cannot be at the starting point.
If you scroll the resulting view, you will see that 0 is never logged
to the scroll which I expect since the scrollLeft was 0 before I
started scrolling
Unfortunately, there is no event called scrollstart like dragstart or mousedown or keydown, so there is no way to know when the scroll had started and we only know once the scroll has happened.

How to swap images from side bar to the middle div on clicking on those sidebar images?

I'm new to JavaScript and I'm trying to build a web page and I've 3 images of that product in my sidebar and one main image in the middle now I want to get the sidebar image in the middle when a user clicks on that sidebar image. I don't know how to go about this. I've already tried couple of ways which I've found online, one of them is this
1. How to swap image and video to another div?
But these are not working out for me.
What you have to do is save both images in a variable and then swap them. Look at the example below
var imgleft,
imgcenter,
$center = $(".center img");
$(".sidebar img").click(function(){
imgleft = $(this).attr("src");
imgcenter = $center.attr("src");
$center.attr("src", imgleft);
$(this).attr("src", imgcenter);
});
.sidebar{
position: absolute;
top: 0;
width: 70px;
height: 100%;
background: red;
}
.center{
width: 80px;
height: 80px;
margin:25% auto;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="sidebar">
<img src="http://placehold.it/70x70">
<img src="http://placehold.it/70x60">
<img src="http://placehold.it/70x50">
</div>
<div class="center">
<img src="http://placehold.it/70x40">
</div>
You can use javascript's event handling (on each of your sidebar images) to solve this problem. First add the following java script code in your html:
<script type="text/javascript">
function changeToImage1(){
if(centerImage.src != "[1st-image-url.*]"){
centerImage.src = "[1st-image-url.*]";
}
}
function changeToImage2(){
if(centerImage.src != "[2nd-image-url.*]"){
centerImage.src = "[2nd-image-url.*]";
}
}
function changeToImage3(){
if(centerImage.src != "[3rd-image-url.*]"){
centerImage.src = "[3rd-image-url.*]";
}
}
</script>
Then you can simply add the above functions in the onClick attributes of your three sidebar div's accordingly. This can be done like this:
<div id = "first" onclick = "changeToImage1()">
...
</div>
<div id = "second" onclick = "changeToImage2()">
...
</div>
<div id = "third" onclick = "changeToImage3()">
...
</div>

How to automatically scroll horizontally as page width increase

I am building a website that expands horizontally as user takes action like http://portal.azure.com style. When they click a button(from a list) in one div, the details of the selected items appear in another div beside it. this can get really long and over flow the mother div.
I am looking for a way i can automatically scroll the page to the right most edge when a new div overflows.
layout
<div style="overflow-x: auto">
<div layout="row">
<div class="col" style="width: 400px">
</div>
//SHOWN DYNAMICALLY
<div class="col" style="width: 400px">
</div>
//SHOWN DYNAMICALLY
<div class="col" style="width: 400px">
</div>
//SHOWN DYNAMICALLY
<div class="col" style="width: 400px">
</div>
//SHOWN DYNAMICALLY
<div class="col" style="width: 400px">
</div>
</div>
</div>
As you can see above, the first div shows by default but the other divs appear based on user interaction.
By the time the 3 div appears, it overflows.
How can i scroll to the right edge anytime it over flows? (you should really check out http://portal.azure.com to see what im talking about)
PS: i am using AngularJS. I am not using jquery. But i dont mind including it if its the only option
You can use plain Javascript for keeping the scroll to right.
Something like this:
var myDiv = document.getElementById("row");
myDiv.scrollLeft = myDiv.scrollWidth;
You need to fire the above function every time you add a new div. That way it will always automatically be scrolled when divs are dynamically added.
You will need to hook up the DOMNodeInserted event on your container. The function will be called whenever a div is added to your row container. This way you will not have to change anything in your existing code.
Here is a very simple example with dynamically added divs:
var num = 1,
btn = document.getElementById('btn'),
row = document.getElementById("row");
scroller(); // fire teh scroller right away for initial scroll
// function to keep it scrolled towards right
// function scroller() { row.scrollLeft = row.scrollWidth; }
// edited to add simple animation
function scroller() {
var maxScroll = row.scrollWidth - row.clientWidth; // required to stop
row.scrollLeft += 2;
if (row.scrollLeft < maxScroll) {
timer = window.setTimeout(scroller, 1000 / 60);
}
}
// hook up event to call scroller whenever an element is dynamically added
row.addEventListener("DOMNodeInserted", scroller);
// for demo to simluate dynamically adding divs
btn.addEventListener("click", function() {
var newDiv = document.createElement("div");
newDiv.setAttribute("class", "col");
num += 1; newDiv.innerText = num;
row.appendChild(newDiv);
});
div[layout] {
width: 500px; height: 140px; white-space: nowrap;
overflow: hidden; overflow-x: auto;
}
div.col { height: 140px; width: 400px; display: inline-block; text-align:center; }
div { border: 1px solid red; }
<div id="row" layout="row"><div class="col">1</div></div>
<button id="btn">Add</button>
Edit: Added simple animation using setTimeout (in order to keep jQuery away). Ideally you should be using requestAnimationFrame or a suitable library if you are already using one.

Once user reaches a particular point on a page, automatically scroll to particular point/achor

So, here it is:
I'll have 4 divs. Example below. Each div a particular height (around 1500px) but have a width of 100%. Each div is a different colour.
I want it so that when the user scrolls the page and reach a particular point, javascript will kick in and automatically scroll the user to the next div.
So, say the user is vertically scrolling and div #2 is appear and div #1 is disappearing. When div #1 has about 200px left, the page will automatically scroll down so that div #2 is flush with the top of the browser window.
A good example: http://thejuly16.com/ Which basically does it but can't work out how.
1
Content here
2
Content here
3
Content here
4
Content here
That page isn't doing anything for me :/
Anyway, if I get what you mean, you should have some anchors on top of every div, hook some code to the scroll event, check scrollTop() value on it, and scroll to the anchors when this value is in a desired range. You can check this fiddle and the relevant jQuery code:
$(window).bind('scroll', function(){
if (($(window).scrollTop() > 1300) && ($(window).scrollTop() < 1350)) {
window.scrollTo(0,1500);
}
});
This might be a strange behavior for the user, since scrolling up is pretty messed up. However, we can fix this by checking if the user is going up or down in the page, like in this fiddle, just checking if the last scroll position was higher or lower than the current scroll position:
var currentScroll = 0;
var previousScroll = 0;
$(window).bind('scroll', function(){
currentScroll = $(window).scrollTop();
if (($(window).scrollTop() > 1300) && ($(window).scrollTop() < 1350) && currentScroll > previousScroll) {
window.scrollTo(0,1500);
}
previousScroll = $(window).scrollTop();
});
Obviously, you'd need to add as many if statements as "jumps" you want in your page.
I have a solution as given in the code below. Somehow its not working on jsFiddle but working on my machine. Please try it in your own editor
<HTML>
<HEAD>
<SCRIPT LANGUAGE="JavaScript">
var isWorking = false;
var lastScrollPosition
function adjust(oDiv) {
if(oDiv.scrollTop > lastScrollPosition && !isWorking && oDiv.scrollTop % 400 > 300) {
isWorking = true
scroll(oDiv);
} else
lastScrollPosition = oDiv.scrollTop;
}
function scroll(div) {
if(div.scrollTop % 400 > 10) {
div.scrollTop = div.scrollTop + 10;
lastScrollPosition = div.scrollTop;
setTimeout(function(){scroll(div);}, 10);
} else
isWorking = false;
}
</SCRIPT>
</HEAD>
<BODY>
<div style="height: 440px; border: solid 1px red; overflow-Y: auto" onscroll="adjust(this)">
<div style="height: 400px; border: solid 1px green"></div>
<div style="height: 400px; border: solid 1px green"></div>
<div style="height: 400px; border: solid 1px green"></div>
<div style="height: 400px; border: solid 1px green"></div>
<div style="height: 100px"></div>
</div>
</BODY>
</HTML>
I think this functionality is available with jQuery. I have tried this but I was doing this on OnClick event in Javascript. In your case, onFocus or any other suitable event like mouseover etc should work.
Hope this helps.

Categories