how to scroll the div with the help of button click - javascript

i have created the div , in that i have some multiple buttons when user wants to scroll down he can click on down arrow button for scrolling up he can click up arrow button , my problem is when we click on arrow buttons scroll takes me end of the div , i want to scroll by pixels how to do it ?
// this is for scrolling down
//Require jQuery
function scrollSmoothToBottom (id) {
var div = document.getElementById(id);
$('#' + id).animate({
scrollTop: div.scrollHeight - div.clientHeight
}, 500);
}
//Require jQuery
function scrollSmoothToTop (id) {
var div = document.getElementById(id);
$('#' + id).animate({
scrollTop: 0
}, 500);
}

I looked over your code and tried googling .animate()
https://api.jquery.com/animate/
and scrollTop
https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTop
and came up with this idea:
function scrollSmoothDown (id) {
var div = document.getElementById(id);
var howManyPixelsToScroll = 5; //change to any number
$('#' + id).animate({
scrollTop: div.scrollTop + howManyPixelsToScroll // not sure about this syntax
}, 500);
}
If my syntax inside the animate method is right, then this would work and the complementary scrollSmoothUp function would just use a negative number instead of a positive number for howManyPixelsToScroll.
(If you had been able to post a working snippet I could have copied that code and tested these changes, but I don't work much with jQuery, so this is just my best guess, not tested.)

Related

ScrollTo on click not scrolling to the correct list item

I have an SVG map and a list where if you click on a plot number on the map it highlights on the list.
As there are quite a few items, when you click on a plot number on the map its supposed to scroll the list on the right to the correct item.
However as you start clicking around on all different numbers you can see the scroll breaks and it no longer scrolls to the correct number.
Codepen here.
JS Code below:
$('.plot__list__item').click(function () {
$(this).toggleClass('selected');
$(this).siblings('li').removeClass('selected');
$('#' + $(this).data('map')).toggleClass('selected');
$('#' + $(this).data('map')).siblings('g').removeClass('selected');
});
$('.plot__map__item').click(function () {
$(this).toggleClass('selected');
$(this).siblings('g').removeClass('selected');
$('#' + $(this).data('list')).toggleClass('selected');
$('#' + $(this).data('list')).siblings('li').removeClass('selected');
});
$('.plot__map__item').click(function () {
let id = $(this).data('list');
let scrollPos = $('#' + id).position().top;
$('.plot__list').animate({
scrollTop: scrollPos
}, 400);
});
The scroll position of the list will keep changing when you scroll it. Which is why you're getting irregular scrollpos. For example, when you initially click the 1 plot, the scrollpos will be 0. But when you scroll the list a bit it changes to a negative number and it will keep changing when you're scrolling the list.
To fix this, Calculate the top of your list and add the list's position to it. Change your click's animate function to:
scrollTop: $('.plot__list').scrollTop() + $('#' + id).position().top
Check codepen here.
You should take in consideration your last scroll position. Try this code:
var currentPosition = 0;
$('.plot__map__item').click(function () {
let id = $(this).data('list');
let scrollPos = $('#' + id).position().top + currentPosition;
currentPosition = scrollPos;
$('.plot__list').animate({
scrollTop: scrollPos
}, 400);
});
However, this solution will not work if you do scrolling without clicking on numbers. In that case you will need to recalculate your current position on scroll event.

Scrolling to anchors unpredictable

I am trying to build a simple vertical timeline. You can click up or down to scroll it little by little but I also wanted to have it jump, smooth scroll, to anchors. This somewhat works but the behavior is unpredictable.
This isn't usually difficult but something new for me is that the scrolling behavior is inside a div so the whole page shouldn't be moving.
You can try it in the fiddle. Clicking random buttons will sometimes bring you to the right spot, other times it will just scroll to a random place.
JSFiddle
Here is the basic Jquery.
var step = 280;
var scrolling = false;
$(".scrollUp").bind("click", function (event) {
event.preventDefault();
$("#timeline").animate({
scrollTop: "-=" + step + "px"
});
})
$(".scrollDown").bind("click", function (event) {
event.preventDefault();
$("#timeline").animate({
scrollTop: "+=" + step + "px"
});
})
$('.timelineButton').click(function () {
$('#timeline').animate({
scrollTop: $($(this).attr('href')).offset().top
}, 2000);
return false;
});
A few things need fixing :
Use .position().top (relative to offset parent) instead of .offset().top (relative to document)
Specify the offset parent by styling the #timeline container with position: relative
Because .position() returns dynamically calculated values, .position().top will be the value-you-want minus the current-scrollTop. Therefore you need to add the current-scrollTop back on.
CSS
#timeline {
...
position: relative;
}
Javascript
$('.timelineButton').click(function (event) {
event.preventDefault();
$('#timeline').animate({
scrollTop: $($(this).attr('href')).position().top + $('#timeline').scrollTop()
}, 2000);
});
Demo
Add Ids to each div & use that ID like href="#ID". This will scroll window to that particular section ID given in href
Check this
$('.timelineButton').click(function () {
if($('#timeline').is(':animated')){}else{
$('#timeline').animate({
scrollTop: $($(this).attr('href')).offset().top
}, 2000);
return false;
}
});
.is(':animated') will be tell you if the element is animating, if not, animate it.
It prevent the unpredictable jumps.
EDIT
Best way to prevent this is: .stop().animate
$('.timelineButton').click(function () {
$('#timeline').stop().animate({
scrollTop: $($(this).attr('href')).offset().top
}, 2000);
return false;
});
EDIT V2
Check this Fiddle: https://jsfiddle.net/a489mweh/3/
I have to put the position offset of each elements in an array, becouse every animate in timeline change the offset.top of each element.Check the data-arr="0" over each button, to tell the array what position of the element have to retrieve.Tell me if works.
Cheers

JavaScript Focus() on Element ID with Floating Navigation Bar?

On form validation, to prompt the user to fill out the required fields.
The usual;
document.getElementById("idHere").focus();
When dealing with floating navigation bars at the top of the screen, this doesn't always work, mainly when the element you want to focus on is the first one, it hides behind the floating navigation.
Is there a handy solution to nudge the Focus down a set number of pixels to make sure this takes into account the size of the navigation menu?
You must add a scroll function to your function or the element onFocus.
it could be like this :
window.scrollTo( window.scrollX , document.getElementById("idHere").scrollTop + 80 );
Here is the solution as a jQuery function. You use it by passing a selector by whatever elements you want to have the behavior. For example bindFocusScroll('input, select');
function bindFocusScroll(selector){
var navHeight = 192;
var padding = 25;
$(selector).on('focus', function() {
try {
var elemTop = $(this).offset().top;
var maxVisible = $(document).scrollTop() + navHeight;
if (elemTop < maxVisible) {
$("html, body").animate({ scrollTop: elemTop - navHeight - padding }, 250);
}
} catch (e) {
console.log("Error: " + e);
}
});
}
If you don't need it to animate or be smart you can just use Sasan's answer. I can help you recreate this answer in vanilla JS if needed as well.

Using a jquery slider for text instead of images?

This may be a little too specific, but I have a jquery slider that I am using <p> classes instead of images to cycle through customer quotes. Basically the problem I am running into right now is when it is static and non moving (JS code is commeneted out) they are aligned how I want them to be. As soon as the JS is un commented, they stretch out of view and you just see a white box?
Any ideas?
How I want each panel to look like:
jsfiddle
So I sort of made this my Friday project. I've changed a whole lot of your code, and added a vertical-align to the quotes and authors.
Here's the fiddle http://jsfiddle.net/qLca2fz4/49/
I added a whole lot of variables to the top of the script so you could less typing throughout.
$(document).ready(function () {
//rotation speed and timer
var speed = 5000;
var run = setInterval(rotate, speed);
var slides = $('.slide');
var container = $('#slides ul');
var elm = container.find(':first-child').prop("tagName");
var item_width = container.width();
var previous = 'prev'; //id of previous button
var next = 'next'; //id of next button
Since you used a % based width I'm setting the pixel widths of the elements in case the screen is reszed
slides.width(item_width); //set the slides to the correct pixel width
container.parent().width(item_width);
container.width(slides.length * item_width); //set the slides container to the correct total width
As you had, I'm rearranging the slides in the event the back button is pressed
container.find(elm + ':first').before(container.find(elm + ':last'));
resetSlides();
I combined the prev and next click events into a single function. It checks for the ID of the element targeted in the click event, then runs the proper previous or next functions. If you reset the setInterval after the click event your browser has trouble stopping it on hover.
//if user clicked on prev button
$('#buttons a').click(function (e) {
//slide the item
if (container.is(':animated')) {
return false;
}
if (e.target.id == previous) {
container.stop().animate({
'left': 0
}, 1500, function () {
container.find(elm + ':first').before(container.find(elm + ':last'));
resetSlides();
});
}
if (e.target.id == next) {
container.stop().animate({
'left': item_width * -2
}, 1500, function () {
container.find(elm + ':last').after(container.find(elm + ':first'));
resetSlides();
});
}
//cancel the link behavior
return false;
});
I've found mouseenter and mouseleave to be a little more reliable than hover.
//if mouse hover, pause the auto rotation, otherwise rotate it
container.parent().mouseenter(function () {
clearInterval(run);
}).mouseleave(function () {
run = setInterval(rotate, speed);
});
I broke this in to its own function because it gets called in a number of different places.
function resetSlides() {
//and adjust the container so current is in the frame
container.css({
'left': -1 * item_width
});
}
});
//a simple function to click next link
//a timer will call this function, and the rotation will begin :)
And here's your rotation timer.
function rotate() {
$('#next').click();
}
It took me a little bit, but I think I figured out a few things.
http://jsfiddle.net/qLca2fz4/28/
First off, your console was throwing a few errors: first, that rotate wasn't defined and that an arrow gif didn't exist. Arrow gif was probably something you have stored locally, but I changed the 'rotate' error by changing the strings in the code here to your actual variables.
So, from:
run = setInterval('rotate()', speed);
We get:
run = setInterval(rotate, speed);
(No () based on the examples here: http://www.w3schools.com/jsref/met_win_setinterval.asp)
But I think a more important question is why your text wasn't showing up at all. It's because of the logic found here:
$('#slides ul').css({'left' : left_value});
You even say that this is setting the default placement for the code. But it isn't..."left_vaule" is the amount that you've calculated to push left during a slide. So if you inspect the element, you can see how the whole UL is basically shifted one slide's worth too far left, unable to be seen. So we get rid of 'left_value', and replace it with 0.
$('#slides ul').css({'left' : 0});
Now, there's nothing really handling how the pictures slide in, so that part's still rough, but this should be enough to start on.
Let me know if I misunderstood anything, or if you have any questions.
So, a few things:
1) I believe you are trying to get all of the lis to be side-by-side, not arranged up and down. There are a few ways to do this. I'd just make the ul have a width of 300%, and then make the lis each take up a third of that:
#slides ul {
....
width: 300%;
}
#slides li {
width: calc(100% / 3);
height:250px;
float:left;
}
2) You got this right, but JSFiddle automatically wraps all your JS inside a $(document).ready() handler, and your function, rotate needs to be outside, in the normal DOM. Just change that JSFiddle setting from 'onload' to 'no wrap - in head'
3) Grabbing the CSS value of an element doesn't always work, especially when you're dealing with animating elements. You already know the width of the li elements with your item_width variable. I'd just use that and change your code:
var left_indent = parseInt($('#slides ul').css('left')) - item_width;
$('#slides ul').animate({'left' : left_indent}, 1500, function () {
to:
$('#slides ul').stop().animate({'left' : -item_width * 2}, 1500, function () {
4) Throw in the .stop() as seen in the above line. This prevents your animations from overlapping. An alternative, and perhaps cleaner way to do this, would be to simply return false at the beginning of your 'next' and 'prev' functions if #slides ul is being animated, like so:
if ($('#slides ul').is(':animated')) return false;
And I think that's everything. Here's the JSFiddle. Cheers!
EDIT:
Oh, and you may also want to clearInterval at the beginning of the next and prev functions and then reset it in the animation callback functions:
$('#prev').click(function() {
if ($('#slides ul').is(':animated')) return false;
clearInterval(run);
$('#slides ul').stop().animate({'left' : 0}, 1500,function(){
....
run = setInterval('rotate()', speed);
});
});

Making nav bar effects using scroll AND click in jQuery

I want a nav to highlight (or something similar) once a user clicks on it AND when a user scrolls to the corresponding section.
However, on my computer when one clicks on any of the nav events after3, only nav event 3 changes. I'm guessing this is because after one clicks on 4 or 5, the scroll bar is already at the bottom of the page, so 4 and 5 never reach the top. The only div at the top is post 3, so my code highlights nav event 3 and ignores the click.
Is there any way I can fix this? Ive tried if statements (only highlight nav event if it's at the top AND the scrollbar isn't at the bottom or the top isn't the last item).
Here is a more accurate fiddle, using a fix below showing what I am talking about. The fix now highlights on scroll, but if you click option 5, it will not highlight.
$('.option').children('a').click(function() {
$('.option').css('background-color', '#CCCCCC;');
$(this).css('background-color', 'red');
var postId = $($(this).attr('href'));
var postLocation = postId.offset().top;
$(window).scrollTop(postLocation);
});
$(window).scroll(function() {
var scrollBar = $(this).scrollTop();
var allPosts = [];
var post = $('.content').offset();
var lastPost = allPosts.legnth-1
var windowHeight = $(window).height();
var bottomScroll = windowHeight-scrollBar;
$(".content").each(function(){
allPosts.push($(this).attr('id'));
});
i = 0;
for(i in allPosts){
var currentPost = "#"+allPosts[i];
var postPosition = $(currentPost).offset().top;
if (scrollBar >= postPosition){
$('.option').css('background-color', '#CCCCCC');
$('#nav'+allPosts[i]).css('background-color', 'red');
};
};
});
I think you've overdone your scroll() handler, to keep it simple you just needs to check if the scrollbar/scrollTop reaches the '.contents' offset top value but should not be greater than its offset().top plus its height().
$(window).scroll(function () {
var scrollBar = $(this).scrollTop();
$(".content").each(function (index) {
var elTop = $(this).offset().top;
var elHeight = $(this).height();
if (scrollBar >= elTop - 5 && scrollBar < elTop + elHeight) {
/* $(this) '.content' is the active on the vewport,
get its index to target the corresponding navigation '.option',
like this - $('.Nav li').eq(index)
*/
}
});
});
And you actually don't need to set $(window).scrollTop(postLocation); because of the default <a> tag anchoring on click, you can omit that one and it will work fine. However if you are looking to animate you need first to prevent this default behavior:
$('.option').children('a').click(function (e) {
e.preventDefault();
var postId = $($(this).attr('href'));
var postLocation = postId.offset().top;
$('html, body').animate({scrollTop:postLocation},'slow');
});
See the demo.
What you are trying to implement from scratch, although commendable, has already been done by the nice folks at Bootstrap. It is called a Scrollspy and all you need to do to implement it is include Bootstrap js and css (you also need jquery but you already have that) and make some minor changes to your html.
Scrollspy implementation steps.
And here is a demonstration. Notice only one line of js. :D
$('body').scrollspy({ target: '.navbar-example' });

Categories

Resources