On many sites (example VKontakte, Habr, Peekaboo) I see how when you click on a button, we first go up, and when we click again, we go back to the position we were in when we clicked the first time on the button, and when scrolling her new position. And when you repeat the operation, the function will return us to a new position, but the first click from the current position always raises us to the top.

I tried to write the following script, where the current position of the element with each click is recorded in the data-effset , and everything almost works, but if you interrupt the function by scrolling with the mouse wheel or simply by clicking the button, without waiting for the scrolling to end, the function will work with an error (moves us between the current position and where we started to turn the wheel). Perhaps you need to put a flag, but not at all think how ...

 $('#button').click(function() { scrtop = $(window).scrollTop() offsetnow = $(this).attr('data-effset'); $(this).attr('data-effset', scrtop); $("body").animate({ "scrollTop": offsetnow }, "slow"); }); 
 .folder { display: block; position: relative; width: 80%; margin: 0 auto; height: 25000px; background: #80CBC4; } #yack { display: block; position: fixed; top: 0; } #button { display: block; position: fixed; top: 33%; background: #E65100; color: #fff; padding: 8px 25px; cursor: pointer; } 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script> <div class='folder'></div> <div id='button' data-effset='0'>Π’Π²Π΅Ρ€Ρ…/Π²Π½ΠΈΠ·</div> 

    2 answers 2

     $(function(){ // Π‘Ρ‚Π°Π²ΠΈΠΌ Ρ„Π»Π°Π³, Ссли true - ΠΈΠ΄Ρ‘Ρ‚ ΠΏΡ€ΠΎΠΊΡ€ΡƒΡ‚ΠΊΠ°, Π±Π»ΠΎΠΊΠΈΡ€ΡƒΠ΅ΠΌ ΠΏΠΎΠ±ΠΎΡ‡Π½Ρ‹Π΅ дСйствия let isWork = false; $('#button').click(function(e){ // Если Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚ анимация, Π²Ρ‹Ρ…ΠΎΠ΄ΠΈΠΌ Π½ΠΈΡ‡Π΅Π³ΠΎ Π½Π΅ мСняя if(isWork) return; isWork = true; // АктивируСм Ρ„Π»Π°Π³ let scroll = window.pageYOffset, // Π’Π΅ΠΊΡƒΡ‰ΠΈΠΉ отступ ΠΏΡ€ΠΎΠΊΡ€ΡƒΡ‚ΠΊΠΈ old = +this.dataset.offset; // Π‘Ρ‚Π°Ρ€Ρ‹ΠΉ отступ ΠΊ ΠΊΠΎΡ‚ΠΎΡ€ΠΎΠΌΡƒ Π±ΡƒΠ΄Π΅ΠΌ ΠΊΡ€ΡƒΡ‚ΠΈΡ‚ΡŒ Π±Π°Ρ€Π°Π±Π°Π½ :) this.dataset.offset = scroll; // БохраняСм Π½ΠΎΠ²ΡƒΡŽ ΠΏΠΎΠ·ΠΈΡ†ΠΈΡŽ // Π‘Π°ΠΌΠΎΠ΅ вкусноС: запускаСм Π°Π½ΠΈΠΌΠ°Ρ†ΠΈΡŽ ΠΏΠΎ старому Π·Π½Π°Ρ‡Π΅Π½ΠΈΡŽ ΠΈ ΠΏΠΎ ΠΎΠΊΠΎΠ½Ρ‡Π°Π½ΠΈΠΈ ΠΎΠ½Π½ΠΎΠΉ, // мСняСм Ρ„Π»Π°Π³ Π² Π½Π΅Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎΠ΅ состояниС, Ρ‡Ρ‚ΠΎΠ±Ρ‹ функция снова стала Π°ΠΊΡ‚ΠΈΠ²Π½ΠΎΠΉ $("html, body").animate({ scrollTop: scroll > 0 ? 0 : old }, 'slow', () => isWork = false); }); $(window).scroll(e => { // Если наша ΠΏΡ€ΠΎΠΊΡ€ΡƒΡ‚ΠΊΠ° Ρ€Π°Π±ΠΎΡ‚Π°Π΅Ρ‚, отмСняСм стандартноС дСйствиС if(isWork) e.preventDefault(); }); }); 
     .folder { display: block; position: relative; width: 80%; margin: 0 auto; height: 25000px; background: #80CBC4; } #yack { display: block; position: fixed; top: 0; } #button { display: block; position: fixed; top: 33%; background: #E65100; color: #fff; padding: 8px 25px; cursor: pointer; } 
     <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script> <div class='folder'></div> <div id='button' data-offset=0>Π’Π²Π΅Ρ€Ρ…/Π²Π½ΠΈΠ·</div> 

    • And for it you need it () =>? (after the completion of the animation) - Evgeny Shevtsov
    • one
      @ EvgenyShevtsov, this is a new notation for functions in JS . Solves painful, but old browsers do not understand this; since there is support for quite some time. - user207618 5:09
    • yes no, I do not understand what it is for, where you can read it) it is clear that after the animation is completed, the variable becomes false, and () => what does it mean, like starting the function?)) (I don’t understand at all here, so don't laugh at assumptions)) that is, it isWork = false simply could be thrust into a function and everything would also work, right?) - Evgeny Shevtsov
    • one
      @ EvgenyShevtsov, in this case, () => {...} can be replaced by function(){...} (here the features of the pointer functions are not used). That is, the animate function can take a function that it will perform after the completion of the animation, which is what we need. If you put the cancellation of the flag just next line, and not an argument, then the flag will immediately turn off, without waiting for the end of the animation. Read about the arrows: developer.mozilla.org/ru/docs/Web/JavaScript/Reference/… - user207618
    • one
      @DimXenon, always please, I strongly recommend to look at all the news, start at least from here: learn.javascript.ru/es-modern - user207618
    1. Add a variable storing the user's last position on the page (offset).
    2. Add the "move" flag.
    3. Put the scrolling event listener on the document. While the flag "moving" is active - ignore the scroll. You can, instead of ignoring the scroll, make stubborn following to the point of destination or interrupting the movement - as it is more convenient and more like it.
    4. When you click on the button, save the offset to the variable (you can add the condition "offset does not equal 0" - I think you should not store the zero offset, but the position on the page can be useful, provided that we have only two options for moving to the beginning and at the last point of stay), set the flag "move".
    5. Move to the top or to the target position at the offset.
    6. After moving - remove the flag "move".