Calculate offset top of elements inside of a scrollable div - javascript

How can I calculate offset top inside a scrollable div? I have two divs that I want scroll inside my content div, and I want to set 2 variables to true/false, depending on where they are positioned inside that content div.
I tried something like this but I guess it calculates the entire page offset, it doesn't really work. I bind scroll to that content div, and I want to calculate their positon:
angular.element(slideContent).bind("scroll", function () {
var contentScrollTop = angular.element(slideContent).scrollTop();
var slideOneOffset = slideOne.offset().top;
var slideTwoOffset = slideTwo.offset().top;
var firstSlideDistance = (contentScrollTop - slideOneOffset);
var secondSlideDistance = (contentScrollTop - slideTwoOffset);
});

I think this should get you most of the way there:
// Position of first element relative to container top
var scrollTop = $(".container .element").offset().top - $(".container").offset().top;
// Position of selected element relative to container top
var targetTop = $(".container > *").offset().top - $(".container").offset().top;
// The offset of a scrollable container
var scrollOffset = scrollTop - targetTop;
// Scroll untill target element is at the top of its container
$(".container").scrollTop(scrollOffset);
———————————
EDIT (May 31 2018)
I guess this is better:
var scrollOffset = $(".container .element")[0].offsetTop - $(".container")[0].offsetTop

Related

why doesn't my JS function fire on the onresize event?

function getCentralPosition() {
// This script verticaly centers the heading you see on the main home page video //
// First save the parent div that houses the heading element into a variable named parentDiv.
var parentDiv = document.getElementById('home-section-1');
// Now obtain the total height (including padding, borders etc) of this parentDiv
var parentDivHeight = parentDiv.offsetHeight;
// Save the child div element that houses the heading into a variable named childDiv
var childDiv = document.getElementById('home-first-overlay');
// Now obtain the total height (including padding, borders etc) of this childDiv
var childDivHeight = childDiv.offsetHeight;
// Calculate the height difference between the parentDiv and childDiv by subtracting their heights and storing them
// in a variable named heightDiff
var heightDiff = parentDivHeight - childDivHeight;
// Obtain the precise position required from the top of the parentDiv by dividing heightDiff by 2
var pos_from_top = heightDiff / 2;
// assign pos_from_top as the value for 'top' on childDiv using "px"
childDiv.style.top = pos_from_top + "px";
}
window.addEventListener("onresize", getCentralPosition);
without the window resize eventlistener, I used the code as is - but the idea is that it also stays in the center when one trys to resize the browser window etc. Thought not necessary, i just wanted to achieve this. Any ideas as to what I should be trying ?
I believe you are looking for the "resize" event
Here is the updated snippet (it errors without the proper HTML, but shows the event firing).
function getCentralPosition() {
// This script verticaly centers the heading you see on the main home page video //
// First save the parent div that houses the heading element into a variable named parentDiv.
var parentDiv = document.getElementById('home-section-1');
// Now obtain the total height (including padding, borders etc) of this parentDiv
var parentDivHeight = parentDiv.offsetHeight;
// Save the child div element that houses the heading into a variable named childDiv
var childDiv = document.getElementById('home-first-overlay');
// Now obtain the total height (including padding, borders etc) of this childDiv
var childDivHeight = childDiv.offsetHeight;
// Calculate the height difference between the parentDiv and childDiv by subtracting their heights and storing them
// in a variable named heightDiff
var heightDiff = parentDivHeight - childDivHeight;
// Obtain the precise position required from the top of the parentDiv by dividing heightDiff by 2
var pos_from_top = heightDiff / 2;
// assign pos_from_top as the value for 'top' on childDiv using "px"
childDiv.style.top = pos_from_top + "px";
}
window.addEventListener("resize", getCentralPosition);
I use a similar function to adjust a dynamic svg graph based screen size.
I just place the onresize="function()" code in the tag and it works out of the box.

Erratic scrollbar using Jquery

This is the fiddle. https://jsfiddle.net/igor_g/ksjkpg0t/16/
My intention is to build a scrollbar on a strip of colors. The colors are taken from the text it is supposed to scroll. Basically, the strip is an overview of all the colors that are used in the text fonts. The text is generated dynamically and can be very large and very small. My intention is to make the scroller's size proportional and at the same time scroll properly. I have tried various combinations using jquery but I just can not seem to get the scroller to work the way I want. Sometimes, the scroller doesnt seem to point to the right text passage. How can this be fixed?
The jquery code is as follows:
/// here is our plugin declaration
(function ( $ ) {
$.fn.colorScroller = function( options ) {
var settings = $.extend({
replaceBlack: 'rgb(83, 84, 72)',
colorScrollClass: "color-map",
overlayClass: "overlay",
scrollSectionClass: "mapSection",
coloredTextClass: "passage"
}, options );
// assign this(the selector that is calling this function) to container
var container = this;
// getting the height of container
var containerHeight = container.outerHeight(true);
// creating overlay scrolling element
var $overlay = $('<div class="'+settings.overlayClass+'" ></div>')
//creating container for colored parts
var $colorScroll=$('<div class="'+settings.colorScrollClass+'" ></div>')
// appending colormap element after container in DOM
container.after($colorScroll);
// approximate total height of browser vertical scroll buttons
var browserScrollButtons = 26;
// setting height of colorscroll element to the height of container
$colorScroll.outerHeight(container.outerHeight()-browserScrollButtons );
var scrollerHandleMin = 31
// here we are calculating the total height of text elements of container
var totalHeight = 0;
container.children('.'+ settings.coloredTextClass).each(function(){
totalHeight = totalHeight + $(this).outerHeight(true);
});
// calculate height of text empty elements like br or <p></p>
var emptyHeight = 0;
container.children().not('.'+ settings.coloredTextClass).each(function(){
emptyHeight = emptyHeight + $(this).outerHeight(true);
});
// here we are calculating the ratio b/n total height of children of container and the height of color-scroll element
var ratio = totalHeight/$colorScroll.outerHeight();
// here we create a jquery object containing of small divs which will be colored, and associated with each passage div in container
var $mini = $('.'+settings.coloredTextClass, container).map(function(){
// getting the height of passage, setting the height of small div element by dividing by ratio
var heightPassage=$(this).outerHeight(true)/ratio+'px';
// getting the color of passage
var colorPassage=$(this).css('color');
// color change if color is black
if (colorPassage=='rgb(0, 0, 0)')
colorPassage = settings.replaceBlack;
var elem = $('<div class="'+settings.scrollSectionClass+'" style="height:'+heightPassage+'; background-color:'+colorPassage+'" ></div>').get(0)
// returning a jquery object element with class, height and color associated according to previous calculations
return elem
});
// get approximate height of browser scroll bar handle
var browserScrollBarHeight = (containerHeight*(containerHeight-browserScrollButtons ))/(totalHeight + emptyHeight )
browserScrollBarHeight = browserScrollBarHeight > scrollerHandleMin ? browserScrollBarHeight : scrollerHandleMin
// set overlay scroller height to browser scroll handle height
$overlay.outerHeight(browserScrollBarHeight);
var overlayHeight = $overlay.outerHeight();
// appending the minified elements into colorscroll element
$($mini).appendTo($colorScroll);
// appending overlay element into color-scroll element
$colorScroll.append($overlay);
// getting top position of container related to document top
var colorScrollTop = $colorScroll.offset().top+1+parseInt($colorScroll.css('margin-top').replace('px', ''))
// getting multiple to create algorithm for converting top positions
var k = (totalHeight + emptyHeight - containerHeight)/($colorScroll.innerHeight()-overlayHeight)
// attaching draggable to overlay scrolling element, so that it can be moved along color scroll element
$overlay.draggable({
// constrain movement to color-scroll element only
containment: "."+settings.colorScrollClass,
// what to do when overlay is dragged
drag: function() {
// getting top position of overlay related to document top
var top = $(this).offset().top;
container.animate({
// scroll container vertically to the point of overlay top (related to color-scroll element ) associated with text in container
scrollTop: (top-colorScrollTop)*k +'px'
}, 2)
},
});
/// when mouse on color-scroller unbind container scroll and enble draggable
/// when mouse leaves color-scroller bind container scroll and disable draggable
$colorScroll
.mouseenter(function() {
$overlay.draggable('enable')
container.off('scroll', scrollText)
})
.mouseleave(function() {
$overlay.draggable('disable')
container.on('scroll', scrollText)
});
// function triggered when container scrolled, basically scroll the overlay
function scrollText(){
$overlay.animate({
top: container.scrollTop()/k + 'px'
}, 1)
}
container.on('scroll', scrollText)
// when the color-scroll element is clicked
$colorScroll.on('click',function(e){
// calculate the position of click related to color-scroll itself
var topPosition = e.pageY-$(this).offset().top;
// and move overlay top to that position
$overlay.animate({
top: topPosition+'px'
}, 200)
// and scroll container to text associated with overlay top
container.animate({
scrollTop: (topPosition+overlayHeight)*ratio-containerHeight+'px'
}, 10)
})
return container;
};
}( jQuery ));
/// end plugin
$(document).ready(function() {
var passes = [0, 1, 2, 3, 4, 5, 6]
for (var i in passes) {
col = document.getElementById('pass' + i).style.color;
var element = document.createElement("section");
element.style.background = col;
document.getElementById("left").appendChild(element);
}
canvas = document.createElement("canvas");
canvas.id = 'canvas';
canvas.style = 'height:700px;width:50px;';
/// here we init plugin function
$('#document_content').colorScroller({replaceBlack: 'rgb(0,0,0)'});
/// the other option with defaults are :
// colorScrollClass: "color-map", css class of colored scrollbar
// overlayClass: "overlay", css class of the custom scrollbar
// scrollSectionClass: "mapSection", css class of the small colored sections in colored scroll bar
// coloredTextClass: "passage" css class of the original text part
///
});

Find div closest to the bottom of the page

I am working on a project and I have an array of elements that are displayed one under each other.
When I press an arrow, I want to find the div closest to the bottom and scroll up to the top of that div.
This is what I have when I click the arrow:
$(".my-elements").each(function(i){
var divTopPosition = $(this).offset().top;
var scrollTop = $(window).scrollTop();
var difference = -Math.abs(scrollTop - divTopPosition);
if(/* this is the div closest to the bottom */)
{
$("body").animate({scrollTop: difference}, 2000);
return false;
}
});
if you know parent, you can use this selector:
$( "<parent>:last-child" )

Binding a jquery value to a specific DIVs height

Sorry, I'm a jquery/js apprentice. I have a jquery sticky nav setup with skrollr set to "stick" at a top offset of 590px. This seemed okay but I came to find I need that offset to be unique on some pages and instead of having to manually apply the unique offset I wanted to know if I can bind the offset value to a specific DIVs height? This would help make things easier to manage in the future.
Here is my codez:
$(document).ready(function() {
var stickyNavTop = $('#navmenu').offset().top+590;
var stickyNav = function(){
var scrollTop = $(window).scrollTop();
if (scrollTop > stickyNavTop) {
$('#navmenu').addClass('sticky');
} else {
$('#navmenu').removeClass('sticky');
}};
stickyNav();
$(window).scroll(function() {
stickyNav();
});
});
The DIV in question with the height value I need to bind it to has a class of .custom-hero-background
It has a global height applied of 600px but on some pages I override this with unique heights.
Just add this in your script, outside of all the other functions, except for $(document).ready(function(
var theHeight = $('.custom-hero-background').height();
and then instead of having a fixed +590 for the offeset, just do + theHeight. If you need it to be 10 pixels less than theHeight, just do theHeight - 10
var stickyNavTop = $('#navmenu').offset().top+theHeight;

how to re-calculate variables in javascript

function scrollContent(){
var div = $('#scrolling-content'),
ul = $('ul.image'),
// unordered list's left margin
ulPadding = 0;
//Get menu width
var divWidth = div.width();
//Remove scrollbars
div.css({overflow: 'hidden'});
//Find last image container
var lastLi = ul.find('li:last-child');
//When user move mouse over menu
div.mousemove(function(e){
//As images are loaded ul width increases,
//so we recalculate it each time
var ulWidth = lastLi[0].offsetLeft + lastLi.outerWidth() + ulPadding;
var left = (e.pageX - div.offset().left) * (ulWidth-divWidth) / divWidth;
div.scrollLeft(left);
});
}
This is how I scroll my image list. The problem is that #scrolling-content element's size is dynamic. It changes on window resize. Here;
$(window).resize(function() {
$("#scrolling-content").css("width",$(window).width() + "px");
$("#scrolling-content").css("height",($(window).height()-400) + "px");
});
So it has to recalculate the left value when user changes windows size. How sould I change script to do that? Recalling scrollContent() function with window.resize function is a noob solution I guess. And it creates conflict for IE.
You could set the width on resize and make your function call the variable like so. This method turns your function into a js object and the window update resets the width var inside that object. Course now you call the function like this: scrollContent.scroll();
var scrollContent = {
width: 0,
scroll:function(){
var div = $('#scrolling-content'),
ul = $('ul.image'),
// unordered list's left margin
ulPadding = 0;
//Get menu width
scrollContent.width = div.width();
//Remove scrollbars
div.css({overflow: 'hidden'});
//Find last image container
var lastLi = ul.find('li:last-child');
//When user move mouse over menu
div.mousemove(function(e){
//As images are loaded ul width increases,
//so we recalculate it each time
var left = (e.pageX - div.offset().left) * (ulWidth-scrollContent.width) / scrollContent.width;
div.scrollLeft(left);
});
}
};
$(window).resize(function() {
$("#scrolling-content").css("width",$(window).width() + "px");
$("#scrolling-content").css("height",($(window).height()-400) + "px");
scrollContent.width = $(window).width();
});
You can also just declare a standard js var and use that to keep things simple. I just prefer working with js objects to eliminate possible var interference.

Categories

Resources