Get Element on Scroll using Jquery - javascript

i have been trying to get Element when i scroll . basically my aim is to get Element while scrolling
e.g i have
<div id='ParentDiv' style="overflow-x:auto">
<div id="1" style="height:50px"> 1 <div>
<div id="2" style="height:100px">2</div>
<div id="3" style="height:20px>3<div>
</div>
is there any way to get id of Div when i scroll to element as ids are dynamic
regards

I don't know if it's what you are looking for :
$("div").on('mousewheel DOMMouseScroll', function(e) {
var id = $(this).attr("id");
console.log(id);
})

You can use this code. On #parent scroll, id of element that is in screen, written in console.
$("#parent").scroll(function() {
var winHeight = $(this).height();
var scrollTop = $(this).scrollTop();
$(".child").each(function(index){
var elemHeight = $(this).height();
var elementTop = $(this).position().top;
if (elementTop < scrollTop + winHeight && scrollTop < elementTop + elemHeight)
console.log($(this).attr("id"));
});
});
#parent {
height: 150px;
overflow: auto;
}
.child {
height: 300px;
}
#child1 {
background: red;
}
#child2 {
background: blue;
}
#child3 {
background: green;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="parent">
<div id="child1" class="child"></div>
<div id="child2" class="child"></div>
<div id="child3" class="child"></div>
</div>

Related

How to make auto slideshow of Divs stop when target link to one of the slide is clicked

I have a slideshow of divs that automatically cycles through but how do i make it so that when i click on a target link, it leads me there and stops the cycling of the slideshow. Moreover, after a few cycles, the slides start to clog up and aggregate on top of one another, can someone please help tp rectify this error thanks.
This is my current code:
parent div {
display: none;
position: absolute;
}
#parent div:first-child {
display: block;
}
#parent > div {
width: 400px;
height: 250px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="slideshow-container" id="parent">
<script>
function Divs() {
var divs = $("#parent div"),
now = divs.filter(":visible"),
next = now.next().length ? now.next() : divs.first(),
speed = 1000;
now.fadeOut(speed);
next.fadeIn(speed);
}
$(function () {
setInterval(Divs, 1400);
});
</script>
<div class="box" id="food">
<h2>hi</h2>
</div>
<div class="box" id="infrastructure">
<h2>bye</h2>
</div>
<div class="box" id="culture">
<h2>hi</h2>
</div>
<div class="box" id="nature">
<h2>bye</h2>
</div>
</div>
If you set your interval to a variable you can point an event-listener to the parent div and on click you can reset the timer.
here is a solutuion:
const interval= setInterval(divs, 1400)
const parentContainer = document.querySelector('#parent')
parentContainer.addEventListener('click', event => {
clearInterval(interval)
console.log(event.target.parentNode)
})
divs(interval)
function divs() {
var divs= $('#parent div'),
now = divs.filter(':visible'),
next = now.next().length ? now.next() : divs.first(),
speed = 1000;
now.fadeOut(speed);
next.fadeIn(speed);
}
#parent div {
display: none;
position: absolute;
}
#parent div:first-child {
display: block;
}
#parent > div {
width: 400px;
height: 250px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="slideshow-container" id="parent">
<div class='box' id='food'>
<h2>food</h2>
</div>
<div class='box' id='infrastructure'>
<h2>infrastructure</h2>
</div>
<div class='box' id='culture'>
<h2>culture</h2>
</div>
<div class='box' id='nature'>
<h2>nature</h2>
</div>
</div>

How detect which child element is visible after scrolling the parent div?

I would like to emulate something like "current page" using divs (like a PDF reader)
document.addEventListener("DOMContentLoaded", function(event) {
var container = document.getElementById("container");
container.onscroll = function() {
let position = container.scrollTop;
let divs = document.querySelectorAll('.page');
for (div of divs) {
//???
}
}
});
#container {
width: 400px;
height: 600px;
overflow: auto;
}
.page {
width: 400px;
}
.red {
background-color: red;
height: 600px;
}
.blue {
background-color: blue;
height: 400px;
}
Current page: <span id="page-counter">1</span>
<div id='container'>
<div id="div-1" class="page red"></div>
<div id="div-2" class="page blue"></div>
<div id="div-3" class="page red"></div>
<div id="div-4" class="page blue"></div>
</div>
So, I would like to know the best way to, for example, change span page-counter text to "3" when the third div "appears".
Something like this: https://i.imgur.com/rXQ2Bw8.png
Thanks in advance
Celso
Since this question never tagged jQuery, here's a pure Javascript solution that simulates the behavior you're looking for to the best of my knowledge. The solution calculates the amount of pixels of each child element currently visible within the container. If the amount is bigger or equal to half the size of the container, it assumes this is the page your visitor is looking at.
function getVisibleHeight(element){
const container = document.getElementById("container");
let scrollTop = container.scrollTop;
let scrollBot = scrollTop + container.clientHeight;
let containerRect = container.getBoundingClientRect();
let eleRect = element.getBoundingClientRect();
let rect = {};
rect.top = eleRect.top - containerRect.top,
rect.right = eleRect.right - containerRect.right,
rect.bottom = eleRect.bottom - containerRect.bottom,
rect.left = eleRect.left - containerRect.left;
let eleTop = rect.top + scrollTop;
let eleBot = eleTop + element.offsetHeight;
let visibleTop = eleTop < scrollTop ? scrollTop : eleTop;
let visibleBot = eleBot > scrollBot ? scrollBot : eleBot;
return visibleBot - visibleTop;
}
document.addEventListener("DOMContentLoaded", function(event) {
const container = document.getElementById("container");
const divs = document.querySelectorAll('.page');
container.addEventListener("scroll", () => {
for(let i=0; i<divs.length; i++){
const containerHeight = container.clientHeight;
// Gets the amount of pixels currently visible within the container
let visiblePageHeight = getVisibleHeight(divs[i]);
// If the amount of visible pixels is bigger or equal to half the container size, set page
if(visiblePageHeight >= containerHeight / 2){
document.getElementById('page-counter').innerText = i+1;
}
}
}, false);
});
#container {
width: 400px;
height: 300px;
overflow: auto;
}
.page {
width: 380px;
}
.red {
background-color: red;
height: 300px;
}
.blue {
background-color: blue;
height: 200px;
}
Current page: <span id="page-counter">1</span>
<div id='container'>
<div id="div-1" class="page red"></div>
<div id="div-2" class="page blue"></div>
<div id="div-3" class="page red"></div>
<div id="div-4" class="page blue"></div>
</div>
The general approach here would be to write a function that determines if a given HTML element is in the viewport. You could run the check as the user scrolls. See the snippet below for an example with jQuery. I'm not necessarily saying this is the best way to do this, but it seems to be working. Start scrolling to see the IDs appear.
function isInViewPort(element) {
// Function will determine if any part of the element is in the viewport.
let $el = $("#" + element);
let windowScrollTop = $(window).scrollTop();
let windowHeight = $(window).height();
let windowBottom = windowScrollTop + windowHeight;
let elementTop = $el.offset().top;
let elementOuterHeight = $el.outerHeight();
let elementBottom = elementTop + elementOuterHeight;
let isAboveViewPort = elementBottom < windowScrollTop;
let isBelowViewPort = windowBottom < elementTop;
return !(isAboveViewPort || isBelowViewPort);
}
let currentDiv;
$("#container").on("scroll", function() {
$("#container").find("div").each(function() {
if (isInViewPort(this.id) && currentDiv !== this.id) {
$("#page").html("Current ID is " + this.id)
currentDiv = this.id;
}
});
});
#container {
overflow: auto;
height: 300px;
}
.red {
background-color: red;
height: 600px;
}
.blue {
background-color: blue;
height: 400px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<span id="page"></span>
<div id='container'>
<div id="div-1" class="page red"></div>
<div id="div-2" class="page blue"></div>
<div id="div-3" class="page red"></div>
<div id="div-4" class="page blue"></div>
</div>
you can use the is visible feature in jQuery. Just give each div a unique ID or class.
if( $("#uniqueIdHere").is(':visible'))
$(".page3Selector").addClass('active');
and then to remove the active class you could pair it up with an else statement to remove the class of the inactive div.

Freeze selected item when scrolling

I have a requirement, where I need to freeze the selected item from list of items in a container to top, when the selected item is in top fold of the container. and when the selected item is in bottom fold of the container, I need to stick it to the bottom.
If the selected item is in visible fold, nothing should happen. I mean the selected item should be in normal flow with other adjacent items.
I somehow managed to solve this to some extent. But when I scroll up, when the selected item is sticked above of the container, the selected item is hiding. This behavior is happening even when I scroll down, when the selected item is sticked to the bottom of the container.
Here is the Fiddle
$('.item').click(function () {
$('.item').removeClass('select').removeClass('pAbsolute');
$(this).addClass('select');
});
$('.parent').scroll(function () {
var $selected = $('.item.select');
var cTop = $selected.offset().top;
var cHeight = $selected.height();
var pHeight = $(this).height();
if (cTop < 0) {
$selected.css({
'top': $(this).scrollTop(),
'bottom': ''
}).addClass('pAbsolute');
} else if (cTop > pHeight - cHeight) {
$selected.css({
'bottom': -$(this).scrollTop(),
'top': ''
}).addClass('pAbsolute');
} else {
$selected.css({
'top': '',
'bottom': ''
}).removeClass('pAbsolute');
}
});
You have to use a consistent value to keep the initial offset relative to the container when you select it.
Then, calculate the offset and scroll value,
If cTop < 0, which means its top out of box, stick to top.
If cTop + cHeight > pHeight, which means its view is out of bottom block, set to bottom.
Else stay in position.
Edit:
When selecting a new Item, as the previous item may have .pAbsolute attr, the relative position of current item may change, but we can get the offset change by track the offset before and after those class add/remove actions.
Then we can add the missing height by change the scrollTop of the container manually.
var offset;
$('.item').click(function () {
// This is the offset in container before class change.
offset = this.offsetTop;
$('.item').removeClass('select').removeClass('pAbsolute');
$(this).addClass('select');
// Calculate the difference
var distortion = offset - this.offsetTop;
// Remove the distortion by manual scroll.
var $parent = $(this).parent();
$parent.scrollTop($parent.scrollTop() - distortion);
offset = this.offsetTop;
});
$('.parent').scroll(function () {
var $selected = $('.item.select');
var cTop = offset - $(this).scrollTop();
var cHeight = $selected.height();
var pHeight = $(this).height();
if (cTop < 0) {
$selected.css({
'top': $(this).scrollTop(),
'bottom': ''
}).addClass('pAbsolute');
} else if (cTop + cHeight > pHeight) {
$selected.css({
'bottom': -$(this).scrollTop(),
'top': ''
}).addClass('pAbsolute');
} else {
$selected.css({
'top': '',
'bottom': ''
}).removeClass('pAbsolute');
}
});
body, html {
padding: 0;
margin: 0;
}
.parent {
overflow: auto;
height: 200px;
position: relative;
}
.item {
padding: 10px 15px;
background-color: tomato;
width: 100%;
}
.item.select {
background-color: beige;
}
.pAbsolute {
position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="parent">
<div class="item select">1</div>
<div class="item">2</div>
<div class="item">3</div>
<div class="item">4</div>
<div class="item">5</div>
<div class="item">6</div>
<div class="item">7</div>
<div class="item">8</div>
<div class="item">9</div>
<div class="item">10</div>
<div class="item">11</div>
<div class="item">12</div>
<div class="item">13</div>
<div class="item">14</div>
<div class="item">15</div>
<div class="item">16</div>
<div class="item">17</div>
<div class="item">18</div>
<div class="item">19</div>
<div class="item">20</div>
<div class="item">21</div>
<div class="item">22</div>
<div class="item">23</div>
<div class="item">24</div>
<div class="item">25</div>
<div class="item">26</div>
<div class="item">27</div>
<div class="item">28</div>
<div class="item">29</div>
<div class="item">30</div>
<div class="item">31</div>
<div class="item">32</div>
<div class="item">33</div>
<div class="item">34</div>
<div class="item">35</div>
<div class="item">36</div>
<div class="item">37</div>
<div class="item">38</div>
<div class="item">39</div>
<div class="item">40</div>
<div class="item">41</div>
</div>
This solution uses a bottom and top header who are filled in with the selected values and showed/hidden when necessary:
Working Fiddle
Javascript:
function stickItems($parent, itemClass, selectClass) {
// Attach dummy element items
$parent.prepend('<div class="' + itemClass + ' sticky top"></div>');
$parent.append('<div class="' + itemClass + ' sticky bottom"></div>');
var $items = $('.' + itemClass),
$stickyTop = $('.' + itemClass + '.sticky.top'),
$stickyBottom = $('.' + itemClass + '.sticky.bottom');
// Click event registering
$items.click(function (e) {
if (!$(e.target).hasClass('sticky')) {
$items.removeClass(selectClass);
$stickyTop.css('display', 'none');
$stickyBottom.css('display', 'none');
$(this).addClass(selectClass);
}
});
// Scroll event
$parent.scroll(function () {
var $self = $(this);
var $selected = $('.' + itemClass + '.' + selectClass);
var cTop = $selected.offset().top;
var pTop = $self.offset().top;
var cHeight = $selected.height();
var pHeight = $self.height();
if (cTop - pTop <= 0) {
$stickyTop.html($selected.html()).css({
'display': 'block',
'top': $(this).scrollTop()
});
$stickyBottom.css('display', 'none');
} else if (cTop > pTop && cTop < pTop + pHeight) {
$stickyTop.css('display', 'none');
$stickyBottom.css('display', 'none');
} else {
$stickyTop.css('display', 'none');
$stickyBottom.html($selected.html()).css({
'display': 'block',
'bottom': -$(this).scrollTop()
});
}
});
}
stickItems($('.parent'), 'item', 'select');
Css:
body, html {
padding: 0;
margin: 0;
}
body {
padding-top: 200px;
}
.parent {
overflow-x: hidden;
overflow-y: auto;
height: 200px;
position: relative;
}
.item {
padding: 10px 15px;
background-color: tomato;
}
.item.select {
background-color: beige;
}
.item.sticky {
background-color: beige;
display: none;
position: absolute;
left: 0;
right: 0;
z-index: 1;
}
Html:
<div class="parent">
<div class="item sticky top"></div>
<div class="item select">1</div>
<div class="item">2</div>
<!-- ... -->
<div class="item">39</div>
<div class="item">40</div>
<div class="item">41</div>
<div class="item sticky bottom"></div>
</div>

How to find current div element's id on scrolling container

We have a div with fixed size with scroll auto, inside it we have another div bigger than the parent (wrapper) and inside it, more div elements(See example)
Is there a ready solution to find the div element's id in the position we scrolled to?
<div id="main">
<div id="content">
<div id="1" class="inner-content">1</div>
<div id="2" class="inner-content">2</div>
<div id="3" class="inner-content">3</div>
<div id="4" class="inner-content">4</div>
<div id="5" class="inner-content">5</div>
<div id="6" class="inner-content">6</div>
<div id="7" class="inner-content">7</div>
<div id="8" class="inner-content">8</div>
</div>
</div>
#main {
width: 700px;
height: 400px;
border: 1px solid black;
overflow: auto;
}
#content {
width: 10000px;
height: 10000px;
overflow: hidden;
}
.inner-content {
width: 900px;
height: 300px;
border: 1px solid black;
display: inline-block;
}
jsfiddle.net/VJ3QC/4/
For example I scrolled right on div element with id 4, is it possible to return, with JavaScript or JQuery, the id of this element? After that I scrolled left on element with id 7 can I return this element's id?
Thx!
If each of your inner-content divs are always going to be the same width you could work out which one is visible using the offset() property/function when the user scrolls the element.
Something like this..
var prev_id;
$('#main').scroll(function(){
var element_width = 400;
var offset = $('#content').offset();
var positive = Math.abs(offset.left)
var divided = positive / element_width;
var round = Math.round(divided);
var current_element = $('#content').children().eq(round);
var id = current_element.attr('id');
if(id != prev_id){
prev_id = id;
alert(id);
}
});
The little prev_id var and the if statement just make it so that it only alerts once when the id changes.
The example isn't perfect as there are margins and borders which mean the id changes before the element is completely visible. but the logic is there - http://jsfiddle.net/VJ3QC/9/
It is easy. Just use my code. When you will scroll each element will be determined and then will set class "active" to current element .
scrollspy = function(settings) {
var That = this;
elS = [];
Options = {
class: "scrollspy",
classActive: "active",
paddingTop: 0,
infinity: false
};
Options.paddingTop = window.innerHeight - Options.paddingTop;
Object.assign(Options, settings);
$(document).find('.'+Options.class).each(function(e) {
elS.push($(this)[0]);
});
$(document).on('scroll', function(){
if(Options.infinity){
$('.'+Options.class+'.'+Options.classActive).removeClass(Options.classActive);
}
for(var i=0; i<elS.length; i++){
if($(this).scrollTop() + Options.paddingTop >= That.elS[i].offsetTop && $(this).scrollTop() <= (That.elS[i].offsetTop + That.elS[i].offsetHeight)){
if(!$(That.elS[i]).hasClass(Options.classActive)){
$(That.elS[i]).addClass(Options.classActive);
}
}
}
});
}
scrollspy();

Sticky div on scroll

See this: http://jsfiddle.net/3yx5C/1/
I am trying to make a DIV(the green DIV) from the right column:
1. to be fixed when it meets the HEADER;
2. to be NOT-fixed when you scroll to the top and it meets the other DIVs above(*the grey DIVs);
What I can't achieve is the second part. Any ideas?
I have to mention that the grey DIVs on the right might be more than two, with flexible heights, and they can't be wrapped.
<div id="HEADER"></div>
<div id="WRAPPER">
<div class="layout_right">
<div style="height: 80px; background: gray;"></div>
<div style="height: 80px; background: gray;"></div>
<div id="right_ads">I am sticky!</div>
</div>
<div class="layout_middle">
<div style="width: 300px; height: 200px; background: beige;"></div>
<div style="width: 300px; height: 200px; background: pink;"></div>
<div style="width: 300px; height: 200px; background: blue;"></div>
</div>
</div>
<script type='text/javascript'>
window.addEvent('domready', function() {
function sticky_AD() {
var headerHeight2 = $('HEADER').getSize().y;
var window_top = $(window).getScroll().y + headerHeight2 + 20;
var div_top = $('right_ads').getPosition().y;
if (window_top > div_top){
$('right_ads').addClass('fixed_AD').setStyles({'top': headerHeight2 + 20});
} else {
$('right_ads').removeClass('fixed_AD').setStyles({'top':'auto'});
}
}
$(window).addEvent('scroll', function(){
sticky_AD();
});
sticky_AD();
});
</script>
Check this:
Demo here
I added a new variable var dist = $('right_ads').getPosition().y; to store the original position and use it later and changed your else to a new if : if (window_top < dist) {
Code:
function sticky_AD() {
var headerHeight2 = $('HEADER').getSize().y;
var window_top = $(window).getScroll().y + headerHeight2 + 20;
var div_top = $('right_ads').getPosition().y;
if (window_top > div_top) {
$('right_ads').addClass('fixed_AD').setStyles({
'top': headerHeight2 + 20
});
}
if (window_top < dist) {
$('right_ads').removeClass('fixed_AD').setStyles({
'top': 'auto'
});
}
}
$(window).addEvent('scroll', function () {
sticky_AD();
});
var dist = $('right_ads').getPosition().y;
sticky_AD();

Categories

Resources