guy49987
guy49987

Reputation: 104

jQuery animate scrollTop goes up then back down

I have a function that checks if there are any errors on the page and auto scrolls to them. The problem that I'm having is it scrolls up to them but then comes back down to where it was before. I'd like it to scroll up and stay there.

$(".submit_button").click(function (event) {
        event.preventDefault();
        var errorElements = $(".error").filter(":visible");

        if (errorElements.size() > 0) {
            target_top = $(errorElements).offset().top;
            $('html, body').animate({
                scrollTop: target_top
            }, 800);
        }
        return false;
    });

Upvotes: 1

Views: 2087

Answers (1)

SpYk3HH
SpYk3HH

Reputation: 22570

The problem is in your selector. I know why it's done. Any web dev that's been in this long enough has been using that for as much cross browser compat as possible, and yet still encountered this issue. The problem is, you're calling animate:scroll on 2 items consecutively using this selector.

The better way, in short, would be to check if it is a WebKit browser or not. Reason being is that non-WebKit tend to use html whereas WebKit browsers tend to use body (and sometime html). This can cause such confusion as you face now.

The simple short term solution is to use something like /WebKit/i.test(navigator.userAgent) in your click callback. This will help you assign only one selector to the animate call.

Example

var selector = /WebKit/i.test(navigator.userAgent) ? 'body' : 'html';
$(selector).animate( // ...

Test Snippet

$(function() {
	//	simply to make filler divs for scrolling
	for (var i=0;i<10;i++) $('<div />', { 'id': 'div'+i, 'style': 'background-color: '+String.randColorHex()+';' }).append($('.temp').clone().removeClass('temp')).height($(window).height()).appendTo($('body'));
	/*------------------------------------------*/
	
	/***S*O*L*U*T*I*O*N***/
	var divID = 0;
	function btnCheck() {	//	IGNORE, simply to turn buttons on and off when reaching end
		$('#btnScrollDown').prop('disabled', divID>=9);
		$('#btnScrollUp').prop('disabled', divID<=0);
	}
	
	$(document)
		.on('click', '#btnScrollDown', function() {
			if (divID < 10) {
				divID++;
				//	broke everything down so it's easy to see. You can shorten this in a few ways.
/*THIS HERE-> */var selector = /WebKit/i.test(navigator.userAgent) ? 'body' : 'html',
					scrollSelector = '#div' + (divID),
					scrollTop = $(scrollSelector).offset().top
					props = { scrollTop: scrollTop },
					time = 800;
				$(selector).animate(props, time);
				//	simply to turn buttons on and off when reaching end
				btnCheck();
			}
		})
		.on('click', '#btnScrollUp', function() {
			if (divID > 0) {
				divID--
				//	broke everything down so it's easy to see. You can shorten this in a few ways.
/*THIS HERE-> */var selector = /WebKit/i.test(navigator.userAgent) ? 'body' : 'html',
					scrollSelector = '#div' + (divID),
					scrollTop = $(scrollSelector).offset().top
					props = { scrollTop: scrollTop },
					time = 800;
				$(selector).animate(props, time);
				//	simply to turn buttons on and off when reaching end
				btnCheck();
			}
		});
	
});
html, body, div { margin: 0; padding: 0; width: 100%; }
.buttons { display: inline-block; left: 1em; position: fixed; text-align: center; top: 1em; }
button { margin: .25em; padding: .1em .3em; width: 100%; }
.temp { dislpay: none; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<script src="https://cdn.rawgit.com/JDMcKinstry/String.randColorHex/0c9bb2ff/String.randColorHex.js"></script>
<section class="buttons">
  <button id="btnScrollUp" disabled>Scroll To Next Div Up</button><br />
  <button id="btnScrollDown">Scroll To Next Down</button>
  <sub><i>this isn't fully managed, only use buttons to scroll!</i></sub>
</section>
<table class="temp"><tr><td></td></tr></table>

Upvotes: 2

Related Questions