I have a page with two areas. There are boxes in each area. If the user clicks on a box in the top area, it gets moved to the bottom and vice versa. This works fine for the first movement. Theoretically, I should be able to move them back and forth between sections as I please.
Box HTML:
<div id="top-area">
<div class="top-box" id="blue-box"></div>
<div class="top-box" id="yellow-box"></div>
<div class="top-box" id="green-box"></div>
</div>
<hr/>
<div id="bottom-area">
<div class="bottom-box" id="red-box"></div>
<div class="bottom-box" id="gray-box"></div>
</div>
I use jQuery.remove() to take it out of the top section and jQuery.append() to add it to the other. However, when I try to move a box back to its original position, the event that I have created to move them doesn't even fire.
jQuery/JavaScript:
$(".top-box").on('click', function ()
{
var item = $(this);
item.remove();
$(this).removeClass("top-box").addClass("bottom-box");
$("#bottom-area").append(item);
});
$(".bottom-box").on('click', function ()
{
var item = $(this);
item.remove();
$(this).removeClass("bottom-box").addClass("top-box");
$("#top-area").append(item);
});
I have verified that the classes I am using as jQuery selectors are getting added/removed properly. I am even using $(document).on() to handle my event. How come my boxes are not triggering the jQuery events after they are moved once?
Please see the Fiddle: http://jsfiddle.net/r6tw9sgL/
Your code attaches the events on the page load to the elements that match the selector right then.
If you attach the listener to #top-area and #bottom-area and then use delegated events to restrict the click events to the boxes, it should work like you expect. See .on: Direct and Delegated Events for more information.
Use the below JavaScript:
$("#top-area").on('click', '.top-box', function ()
{
var item = $(this);
item.remove();
$(this).removeClass("top-box").addClass("bottom-box");
$("#bottom-area").append(item);
});
$("#bottom-area").on('click', '.bottom-box', function ()
{
var item = $(this);
item.remove();
$(this).removeClass("bottom-box").addClass("top-box");
$("#top-area").append(item);
});
Alternatively:
You could also change .on() to .live(), which works for "all elements which match the current selector, now and in the future." (JSFiddle)
JSFiddle
Here's another way you could work it:
function toBottom ()
{
var item = $(this);
item.remove();
item.off('click', toBottom);
item.on('click', toTop);
$(this).removeClass("top-box").addClass("bottom-box");
$("#bottom-area").append(item);
}
function toTop ()
{
var item = $(this);
item.remove();
item.off('click', toTop);
item.on('click', toBottom);
$(this).removeClass("bottom-box").addClass("top-box");
$("#top-area").append(item);
}
$(".top-box").on('click', toBottom);
$(".bottom-box").on('click', toTop);
#top-area, #bottom-area {
height: 100px;
border: 1px solid black;
padding: 10px;
}
.top-box::before {
content: "Top";
}
.bottom-box::before {
content: "Bottom";
}
#blue-box, #red-box, #yellow-box, #green-box, #gray-box {
width: 100px;
cursor: pointer;
float: left;
margin: 0 5px;
text-align: center;
padding: 35px 0;
}
#blue-box {
background-color: blue;
}
#red-box {
background-color: red;
}
#yellow-box {
background-color: yellow;
}
#green-box {
background-color: green;
}
#gray-box {
background-color: gray;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="top-area">
<div class="top-box" id="blue-box"></div>
<div class="top-box" id="yellow-box"></div>
<div class="top-box" id="green-box"></div>
</div>
<hr/>
<div id="bottom-area">
<div class="bottom-box" id="red-box"></div>
<div class="bottom-box" id="gray-box"></div>
</div>
This basically removes the listener that switched the object to bottom to a listener that switches the object to the top and viceversa.
I would like to have a scroll to top arrow fixed in my page using angular bootstrap.
Currently I have
<div class="col-md-1">
<div class="affix">
<div>
<a th:href="#{/}" href="#" target="_self"><img id="image" src="source" alt="yoli" width="50px" /></a>
</div>
Scroll to top
</div>
</div>
<div class="col-md-6">
<div id="search-bar" ng-include="blabla"></div>
<li ng-repeat="something"></li>
</div>
However when the "Scroll to top" is click it only works first time since the url changes to ...#search-bar and when you click it again nothing happens. So how do I scroll to top without changing the url?
And also question how do I make the "Scroll to top" only show when the search-bar is not showing?
I was thinking about using $anchorScroll and using id'ed numbers on li and if it's higher then "element-3" then show the button, however not sure if that would work.
UPDATE:
I am thinking of following this example, that is using navigation bars that is #search and #results and make the #search href visible on #results active and #results one hidden.
You can do this without jQuery as well:
function filterPath(string) {
return string
.replace(/^\//, '')
.replace(/(index|default).[a-zA-Z]{3,4}$/, '')
.replace(/\/$/, '');
}
const locationPath = filterPath(location.pathname);
document.querySelectorAll('a[href*="#"]').forEach(link => {
let thisPath = filterPath(link.pathname) || locationPath;
if ((location.hostname == link.hostname || !link.hostname)
&& (locationPath == thisPath)
) {
let hashName = link.hash.replace(/#/, '');
if (hashName) {
let targetEl = document.getElementById(hashName);
if (targetEl) {
link.addEventListener('click', () => {
event.preventDefault();
targetEl.scrollIntoView({
top: 50,
left: 0,
behavior: "smooth"
});
});
}
}
}
});
Here is how you can do it. Create a button:
Scroll To Top
CSS:
.scrollToTop{
width:100px;
height:130px;
padding:10px;
text-align:center;
background: whiteSmoke;
font-weight: bold;
color: #444;
text-decoration: none;
position:fixed;
top:75px;
right:40px;
display:none;
background: url('arrow_up.png') no-repeat 0px 20px;
}
.scrollToTop:hover{
text-decoration:none;
}
JavaScript:
$(document).ready(function(){
//Check to see if the window is top if not then display button
$(window).scroll(function(){
if ($(this).scrollTop() > 100) {
$('.scrollToTop').fadeIn();
} else {
$('.scrollToTop').fadeOut();
}
});
//Click event to scroll to top
$('.scrollToTop').click(function(){
$('html, body').animate({scrollTop : 0},800);
return false;
});
});
You can find a demo here. The source presented is taken from here.
Let's say this is my html:
<div class="picture_holder_thumb">
<div class="picture"> <img></div>
<div class="captioning"><div class="title" display: none; ">TITLE</div></div>
</div>
This creates a visual Index of Thumbnails as can be seen here:
www.cyrill-kuhlmann.de/index.php/projects
I have a JS that shows the title of each thumbnail according to the cursors position:
script type='text/javascript'>
var mouseX;
var mouseY;
$(document).mousemove( function(e) {
mouseX = e.pageX;
mouseY = e.pageY;
});
$(".picture_holder_thumb").mouseover(function(){
$(".title").css({'top':mouseY,'left':mouseX}).fadeIn('slow');
});
$(".picture_holder_thumb").mouseout(function(){
$(".title").fadeOut('slow');
});
</script>
This is the CSS:
.captioning .title {
position: relative;
z-index:1;
color: #FFF;
display: none;
}
And it works, but the problem is that it shows ALL Titles at once! How can I achieve that it only shows this ".title" that "lies in" the .picture_holder_thumb that I am hovering?
Is that possible? Unfortunately I can't change the classes in to ID's because of the CMS structure…
Use this as the context to the selector.
Try,
$(".title", this)
instead of
$(".title")
Full code would be,
$(".picture_holder_thumb").mouseover(function(){
$(".title", this).css({'top':mouseY,'left':mouseX}).fadeIn('slow');
});
$(".picture_holder_thumb").mouseout(function(){
$(".title", this).fadeOut('slow');
});
try this -
$(".picture_holder_thumb").mouseover(function(){
$(this).children(".title").css({'top':mouseY,'left':mouseX}).fadeIn('slow');
});
see this Fiddle
What i have is few button and div of same class.
When i click a button of a class the div of same class gets scrollIntoView and the .log appears beside the div on its right side.
PROBLEMS
OnClick button the scroll does not happen
The .log does not appear beside div
The small triangle pointer does not appear beside .log
Additions(The thing i want but dont know how do i do it!)
Whenever the .log appears i want it to shake little upand down
which continues to do untill mouseover
After mouseout i want the .log to fadeOut(2000)
FOR downvoters
<button class="a1">Div1</button>
<button class="a2">Div2</button>
<button class="a3">Div3</button>
<button class="a4">Div4</button>
<button class="a5">Div5</button>
<button class="a6">Div6</button>
<div id="container">
<div class="a1">This is div1</div>
<div class="a2">This is div2</div>
<div class="a3">This is div3</div>
<div class="a4">This is div4</div>
<div class="a5">This is div5</div>
</div>
<div class="log">Your have a fatal error.</div>
#container div {
height:250px;
width:250px;
border:2px solid #000;
margin:15px;
}
#container {
margin:20px;
}
.log {
z-index: 1;
display: none;
color: #fff;
background-color: #c04848;
text-align: left;
box-shadow: 0 2px 5px rgba(0, 0, 0, 0.3);
max-width:270px;
font-size:15px;
padding:10px;
position: absolute;
}
.log:after {
top: 0;
left: -9px;
border-top: 9px solid #c04848;
border-left: 9px solid transparent;
}
$('button').click(function(){
var c = $(this).attr('class');
var div = $('#container div.'+c);
$(document).scrollTo(div, 1000);
log.css({
top : div.position().top + div.height()/2,
left : div.position().left + 20
}).show();
});
Fixed it
$('button').click(function(){
var c = $(this).attr('class');
var div = $('#container div.'+c);
$(document).scrollTop(div.offset().top);
$('.log').css({
top : div.position().top + div.height()/2,
left : div.position().left + 20
}).show();
});
What I did is changed the scrollTo to scrollTop. I have added a selector to log class because most likely you forgot it.
Shaky effect
var inter;
function bounceOn(){
var pos = $('.log').position().left;
$('.log').animate({left: pos+50},500, function(){$('.log').animate({left: pos},500)})
setTimeout(bounceOn, 1000);
}
Try and make something out it maybe?
http://jsfiddle.net/h76jg/6/
All parts of my answer are shown in this JFiddle
In terms of scrollTo, you were probably looking for scrollTop. Try something like this:
scrollTop: div.offset().top
instead of:
$(document).scrollTo(div, 1000);
Although, Just going by what your writing there, I am going to assume you wanted some sort of smooth transition to the div, correct? Try this instead:
$('html, body').animate({
scrollTop: div.offset().top
}, 1000);
This will create a smooth scroll to the div instead of just moving to it.
For the log section, you forgot to reference the log class. Instead, you tried to reference it like a variable, so the interpreter got confused. Try putting the log css call in a reference, like this:
$('.log').css({...
Hope these help!
Edit: Were you intending something like This for the bounce? (up and down?). Either Case, #Dharman has the right idea with his code. You would just want to add another animation (similar to the scrolling), but put a timeout on the end (so the method will continually repeat)
Since i cannot accept anyone's answer coz i dont like em but thanks for an idea of bounce animation that did worked...
now i have created my own Fiddle And it worked perfetly!
$('button').click(function () {
var c = $(this).attr('class');
var div = $('div.' + c);
$('html, body').animate({
scrollTop: div.offset().top
}, 1000); //thanks to Dylan Corriveau
console.log(div.position().left);
$('.log').css({
top: div.position().top + div.height() / 2,
left: div.position().left + div.width() + 50
}).show();
clearTimeout(inter);
setTimeout(bounceOn, 500);
});
$('.log').mouseover(function () {
clearTimeout(inter);
}).mouseout(function () {
$(this).fadeOut(3500);
});
var inter;
//here is the magic!
function bounceOn() {
var pos = $('.log').position().left;
$('.log').animate({
left: pos + 15
}, 50, function () {
$('.log').animate({
left: pos
}, 50)
})
inter = setTimeout(bounceOn, 215);
}
I have a scrolled div and I want to have an event when I click on it, it will force this div to scroll to view an element inside.
I wrote its JavasSript like this:
document.getElementById(chr).scrollIntoView(true);
but this scrolls all the page while scrolling the div itself.
How to fix that?
I want to say it like this:
MyContainerDiv.getElementById(chr).scrollIntoView(true);
You need to get the top offset of the element you'd like to scroll into view, relative to its parent (the scrolling div container):
var myElement = document.getElementById('element_within_div');
var topPos = myElement.offsetTop;
The variable topPos is now set to the distance between the top of the scrolling div and the element you wish to have visible (in pixels).
Now we tell the div to scroll to that position using scrollTop:
document.getElementById('scrolling_div').scrollTop = topPos;
If you're using the prototype JS framework, you'd do the same thing like this:
var posArray = $('element_within_div').positionedOffset();
$('scrolling_div').scrollTop = posArray[1];
Again, this will scroll the div so that the element you wish to see is exactly at the top (or if that's not possible, scrolled as far down as it can so it's visible).
You would have to find the position of the element in the DIV you want to scroll to, and set the scrollTop property.
divElem.scrollTop = 0;
Update:
Sample code to move up or down
function move_up() {
document.getElementById('divElem').scrollTop += 10;
}
function move_down() {
document.getElementById('divElem').scrollTop -= 10;
}
Method 1 - Smooth scrolling to an element inside an element
var box = document.querySelector('.box'),
targetElm = document.querySelector('.boxChild'); // <-- Scroll to here within ".box"
document.querySelector('button').addEventListener('click', function(){
scrollToElm( box, targetElm , 600 );
});
/////////////
function scrollToElm(container, elm, duration){
var pos = getRelativePos(elm);
scrollTo( container, pos.top , 2); // duration in seconds
}
function getRelativePos(elm){
var pPos = elm.parentNode.getBoundingClientRect(), // parent pos
cPos = elm.getBoundingClientRect(), // target pos
pos = {};
pos.top = cPos.top - pPos.top + elm.parentNode.scrollTop,
pos.right = cPos.right - pPos.right,
pos.bottom = cPos.bottom - pPos.bottom,
pos.left = cPos.left - pPos.left;
return pos;
}
function scrollTo(element, to, duration, onDone) {
var start = element.scrollTop,
change = to - start,
startTime = performance.now(),
val, now, elapsed, t;
function animateScroll(){
now = performance.now();
elapsed = (now - startTime)/1000;
t = (elapsed/duration);
element.scrollTop = start + change * easeInOutQuad(t);
if( t < 1 )
window.requestAnimationFrame(animateScroll);
else
onDone && onDone();
};
animateScroll();
}
function easeInOutQuad(t){ return t<.5 ? 2*t*t : -1+(4-2*t)*t };
.box{ width:80%; border:2px dashed; height:180px; overflow:auto; }
.boxChild{
margin:600px 0 300px;
width: 40px;
height:40px;
background:green;
}
<button>Scroll to element</button>
<div class='box'>
<div class='boxChild'></div>
</div>
Method 2 - Using Element.scrollIntoView:
Note that browser support isn't great for this one
var targetElm = document.querySelector('.boxChild'), // reference to scroll target
button = document.querySelector('button'); // button that triggers the scroll
// bind "click" event to a button
button.addEventListener('click', function(){
targetElm.scrollIntoView()
})
.box {
width: 80%;
border: 2px dashed;
height: 180px;
overflow: auto;
scroll-behavior: smooth; /* <-- for smooth scroll */
}
.boxChild {
margin: 600px 0 300px;
width: 40px;
height: 40px;
background: green;
}
<button>Scroll to element</button>
<div class='box'>
<div class='boxChild'></div>
</div>
Method 3 - Using CSS scroll-behavior:
.box {
width: 80%;
border: 2px dashed;
height: 180px;
overflow-y: scroll;
scroll-behavior: smooth; /* <--- */
}
#boxChild {
margin: 600px 0 300px;
width: 40px;
height: 40px;
background: green;
}
<a href='#boxChild'>Scroll to element</a>
<div class='box'>
<div id='boxChild'></div>
</div>
Native JS, Cross Browser, Smooth Scroll (Update 2020)
Setting ScrollTop does give the desired result but the scroll is very abrupt. Using jquery to have smooth scroll was not an option. So here's a native way to get the job done that supports all major browsers. Reference - caniuse
// get the "Div" inside which you wish to scroll (i.e. the container element)
const El = document.getElementById('xyz');
// Lets say you wish to scroll by 100px,
El.scrollTo({top: 100, behavior: 'smooth'});
// If you wish to scroll until the end of the container
El.scrollTo({top: El.scrollHeight, behavior: 'smooth'});
That's it!
And here's a working snippet for the doubtful -
document.getElementById('btn').addEventListener('click', e => {
e.preventDefault();
// smooth scroll
document.getElementById('container').scrollTo({top: 175, behavior: 'smooth'});
});
/* just some styling for you to ignore */
.scrollContainer {
overflow-y: auto;
max-height: 100px;
position: relative;
border: 1px solid red;
width: 120px;
}
body {
padding: 10px;
}
.box {
margin: 5px;
background-color: yellow;
height: 25px;
display: flex;
align-items: center;
justify-content: center;
}
#goose {
background-color: lime;
}
<!-- Dummy html to be ignored -->
<div id="container" class="scrollContainer">
<div class="box">duck</div>
<div class="box">duck</div>
<div class="box">duck</div>
<div class="box">duck</div>
<div class="box">duck</div>
<div class="box">duck</div>
<div class="box">duck</div>
<div class="box">duck</div>
<div id="goose" class="box">goose</div>
<div class="box">duck</div>
<div class="box">duck</div>
<div class="box">duck</div>
<div class="box">duck</div>
</div>
<button id="btn">goose</button>
Update: As you can perceive in the comments, it seems that Element.scrollTo() is not supported in IE11. So if you don't care about IE11 (you really shouldn't, Microsoft is retiring IE11 in June 2022), feel free to use this in all your projects. Note that support exists for Edge! So you're not really leaving your Edge/Windows users behind ;)
Reference
To scroll an element into view of a div, only if needed, you can use this scrollIfNeeded function:
function scrollIfNeeded(element, container) {
if (element.offsetTop < container.scrollTop) {
container.scrollTop = element.offsetTop;
} else {
const offsetBottom = element.offsetTop + element.offsetHeight;
const scrollBottom = container.scrollTop + container.offsetHeight;
if (offsetBottom > scrollBottom) {
container.scrollTop = offsetBottom - container.offsetHeight;
}
}
}
document.getElementById('btn').addEventListener('click', ev => {
ev.preventDefault();
scrollIfNeeded(document.getElementById('goose'), document.getElementById('container'));
});
.scrollContainer {
overflow-y: auto;
max-height: 100px;
position: relative;
border: 1px solid red;
width: 120px;
}
body {
padding: 10px;
}
.box {
margin: 5px;
background-color: yellow;
height: 25px;
display: flex;
align-items: center;
justify-content: center;
}
#goose {
background-color: lime;
}
<div id="container" class="scrollContainer">
<div class="box">duck</div>
<div class="box">duck</div>
<div class="box">duck</div>
<div class="box">duck</div>
<div class="box">duck</div>
<div class="box">duck</div>
<div class="box">duck</div>
<div class="box">duck</div>
<div id="goose" class="box">goose</div>
<div class="box">duck</div>
<div class="box">duck</div>
<div class="box">duck</div>
<div class="box">duck</div>
</div>
<button id="btn">scroll to goose</button>
Code should be:
var divElem = document.getElementById('scrolling_div');
var chElem = document.getElementById('element_within_div');
var topPos = divElem.offsetTop;
divElem.scrollTop = topPos - chElem.offsetTop;
You want to scroll the difference between child top position and div's top position.
Get access to child elements using:
var divElem = document.getElementById('scrolling_div');
var numChildren = divElem.childNodes.length;
and so on....
If you are using jQuery, you could scroll with an animation using the following:
$(MyContainerDiv).animate({scrollTop: $(MyContainerDiv).scrollTop() + ($('element_within_div').offset().top - $(MyContainerDiv).offset().top)});
The animation is optional: you could also take the scrollTop value calculated above and put it directly in the container's scrollTop property.
We can resolve this problem without using JQuery and other libs.
I wrote following code for this purpose:
You have similar structure ->
<div class="parent">
<div class="child-one">
</div>
<div class="child-two">
</div>
</div>
JS:
scrollToElement() {
var parentElement = document.querySelector('.parent');
var childElement = document.querySelector('.child-two');
parentElement.scrollTop = childElement.offsetTop - parentElement.offsetTop;
}
We can easily rewrite this method for passing parent and child as an arguments
Another example of using jQuery and animate.
var container = $('#container');
var element = $('#element');
container.animate({
scrollTop: container.scrollTop = container.scrollTop() + element.offset().top - container.offset().top
}, {
duration: 1000,
specialEasing: {
width: 'linear',
height: 'easeOutBounce'
},
complete: function (e) {
console.log("animation completed");
}
});
None of other answer fixed my issue.
I played around with scrollIntoView arguments and managed to found a solution. Setting inline to start and block to nearest prevents parent element (or entire page) to scroll:
document.getElementById(chr).scrollIntoView({
behavior: 'smooth',
block: 'nearest',
inline: 'start'
});
There are two facts :
1) Component scrollIntoView is not supported by safari.
2) JS framework jQuery can do the job like this:
parent = 'some parent div has css position==="fixed"' || 'html, body';
$(parent).animate({scrollTop: $(child).offset().top}, duration)
Here's a simple pure JavaScript solution that works for a target Number (value for scrollTop), target DOM element, or some special String cases:
/**
* target - target to scroll to (DOM element, scrollTop Number, 'top', or 'bottom'
* containerEl - DOM element for the container with scrollbars
*/
var scrollToTarget = function(target, containerEl) {
// Moved up here for readability:
var isElement = target && target.nodeType === 1,
isNumber = Object.prototype.toString.call(target) === '[object Number]';
if (isElement) {
containerEl.scrollTop = target.offsetTop;
} else if (isNumber) {
containerEl.scrollTop = target;
} else if (target === 'bottom') {
containerEl.scrollTop = containerEl.scrollHeight - containerEl.offsetHeight;
} else if (target === 'top') {
containerEl.scrollTop = 0;
}
};
And here are some examples of usage:
// Scroll to the top
var scrollableDiv = document.getElementById('scrollable_div');
scrollToTarget('top', scrollableDiv);
or
// Scroll to 200px from the top
var scrollableDiv = document.getElementById('scrollable_div');
scrollToTarget(200, scrollableDiv);
or
// Scroll to targetElement
var scrollableDiv = document.getElementById('scrollable_div');
var targetElement= document.getElementById('target_element');
scrollToTarget(targetElement, scrollableDiv);
given you have a div element you need to scroll inside, try this piece of code
document.querySelector('div').scroll(x,y)
this works with me inside a div with a scroll, this should work with you in case you pointed the mouse over this element and then tried to scroll down or up. If it manually works, it should work too
User Animated Scrolling
Here's an example of how to programmatically scroll a <div> horizontally, without JQuery. To scroll vertically, you would replace JavaScript's writes to scrollLeft with scrollTop, instead.
JSFiddle
https://jsfiddle.net/fNPvf/38536/
HTML
<!-- Left Button. -->
<div style="float:left;">
<!-- (1) Whilst it's pressed, increment the scroll. When we release, clear the timer to stop recursive scroll calls. -->
<input type="button" value="«" style="height: 100px;" onmousedown="scroll('scroller',3, 10);" onmouseup="clearTimeout(TIMER_SCROLL);"/>
</div>
<!-- Contents to scroll. -->
<div id="scroller" style="float: left; width: 100px; height: 100px; overflow: hidden;">
<!-- <3 -->
<img src="https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-logo.png?v=9c558ec15d8a" alt="image large" style="height: 100px" />
</div>
<!-- Right Button. -->
<div style="float:left;">
<!-- As (1). (Use a negative value of 'd' to decrease the scroll.) -->
<input type="button" value="»" style="height: 100px;" onmousedown="scroll('scroller',-3, 10);" onmouseup="clearTimeout(TIMER_SCROLL);"/>
</div>
JavaScript
// Declare the Shared Timer.
var TIMER_SCROLL;
/**
Scroll function.
#param id Unique id of element to scroll.
#param d Amount of pixels to scroll per sleep.
#param del Size of the sleep (ms).*/
function scroll(id, d, del){
// Scroll the element.
document.getElementById(id).scrollLeft += d;
// Perform a delay before recursing this function again.
TIMER_SCROLL = setTimeout("scroll('"+id+"',"+d+", "+del+");", del);
}
Credit to Dux.
Auto Animated Scrolling
In addition, here are functions for scrolling a <div> fully to the left and right. The only thing we change here is we make a check to see if the full extension of the scroll has been utilised before making a recursive call to scroll again.
JSFiddle
https://jsfiddle.net/0nLc2fhh/1/
HTML
<!-- Left Button. -->
<div style="float:left;">
<!-- (1) Whilst it's pressed, increment the scroll. When we release, clear the timer to stop recursive scroll calls. -->
<input type="button" value="«" style="height: 100px;" onclick="scrollFullyLeft('scroller',3, 10);"/>
</div>
<!-- Contents to scroll. -->
<div id="scroller" style="float: left; width: 100px; height: 100px; overflow: hidden;">
<!-- <3 -->
<img src="https://cdn.sstatic.net/Sites/stackoverflow/company/img/logos/so/so-logo.png?v=9c558ec15d8a" alt="image large" style="height: 100px" />
</div>
<!-- Right Button. -->
<div style="float:left;">
<!-- As (1). (Use a negative value of 'd' to decrease the scroll.) -->
<input type="button" value="»" style="height: 100px;" onclick="scrollFullyRight('scroller',3, 10);"/>
</div>
JavaScript
// Declare the Shared Timer.
var TIMER_SCROLL;
/**
Scroll fully left function; completely scrolls a <div> to the left, as far as it will go.
#param id Unique id of element to scroll.
#param d Amount of pixels to scroll per sleep.
#param del Size of the sleep (ms).*/
function scrollFullyLeft(id, d, del){
// Fetch the element.
var el = document.getElementById(id);
// Scroll the element.
el.scrollLeft += d;
// Have we not finished scrolling yet?
if(el.scrollLeft < (el.scrollWidth - el.clientWidth)) {
TIMER_SCROLL = setTimeout("scrollFullyLeft('"+id+"',"+d+", "+del+");", del);
}
}
/**
Scroll fully right function; completely scrolls a <div> to the right, as far as it will go.
#param id Unique id of element to scroll.
#param d Amount of pixels to scroll per sleep.
#param del Size of the sleep (ms).*/
function scrollFullyRight(id, d, del){
// Fetch the element.
var el = document.getElementById(id);
// Scroll the element.
el.scrollLeft -= d;
// Have we not finished scrolling yet?
if(el.scrollLeft > 0) {
TIMER_SCROLL = setTimeout("scrollFullyRight('"+id+"',"+d+", "+del+");", del);
}
}
This is what has finally served me
/** Set parent scroll to show element
* #param element {object} The HTML object to show
* #param parent {object} The HTML object where the element is shown */
var scrollToView = function(element, parent) {
//Algorithm: Accumulate the height of the previous elements and add half the height of the parent
var offsetAccumulator = 0;
parent = $(parent);
parent.children().each(function() {
if(this == element) {
return false; //brake each loop
}
offsetAccumulator += $(this).innerHeight();
});
parent.scrollTop(offsetAccumulator - parent.innerHeight()/2);
}
I needed to scroll a dynamically loading element on a page so my solution was a little more involved.
This will work on static elements that are not lazy loading data and data being dynamically loaded.
const smoothScrollElement = async (selector: string, scrollBy = 12, prevCurrPos = 0) => {
const wait = (timeout: number) => new Promise(resolve => setTimeout(resolve, timeout));
const el = document.querySelector(selector) as HTMLElement;
let positionToScrollTo = el.scrollHeight;
let currentPosition = Math.floor(el.scrollTop) || 0;
let pageYOffset = (el.clientHeight + currentPosition);
if (positionToScrollTo == pageYOffset) {
await wait(1000);
}
if ((prevCurrPos > 0 && currentPosition <= prevCurrPos) !== true) {
setTimeout(async () => {
el.scrollBy(0, scrollBy);
await smoothScrollElement(selector, scrollBy, currentPosition);
}, scrollBy);
}
};
browser does scrolling automatically to an element that gets focus, so what you can also do it to wrap the element that you need to be scrolled to into <a>...</a> and then when you need scroll just set the focus on that a