2

i had a problem with Laravel 10. I need to scroll to next element by pressing a button. I have already tried with myelement.scrollIntoView() and window.scrollTo() functions with no success, what is wrong?

My js:

    import {polyfill, scrollIntoView} from "seamless-scroll-polyfill";
    polyfill();

var Controls = {
    questions: document.getElementsByClassName('question'),
    center_questions: document.getElementsByClassName('center-question'),
    nextbuttons: document.getElementsByClassName('next'),
    prevbuttons: document.getElementsByClassName('prev'),
    header: document.getElementById('header'),

    init: function (){
        for (let button of this.nextbuttons) {
            button.addEventListener("click", e => {
                this.nextslide(e);
            } );
        }
        for (let button of this.prevbuttons) {
            button.addEventListener("click", e => {
                this.prevslide(e);
            } );
        }
    },
    nextslide: function (e) {
        let id = e.target.closest(".question").firstElementChild.id;
        var question = document.getElementById(parseInt(id) + 1);
        window.scrollTo( 0, window.innerHeight );
    },
    prevslide: function (e) {
        let id = e.target.closest(".question").firstElementChild.id;
        document.getElementById(parseInt(id) - 1).scrollIntoView({ behavior: "smooth", block: "center"});
    },
}
window.onload = Controls.init();

2 Answers2

1

I cannot see exactly why your snippet doesn't work as you don't have a working example, but please use this example which I created as close to your code as possible as a reference to make it work :)

var Controls = {
  questions: document.getElementsByClassName('question'),
  nextbuttons: document.getElementsByClassName('next'),
  prevbuttons: document.getElementsByClassName('prev'),
  header: document.getElementById('header'),

  init: function() {
    for (let button of this.nextbuttons) {
      button.addEventListener("click", e => {
        this.nextslide(e);
      });
    }
    for (let button of this.prevbuttons) {
      button.addEventListener("click", e => {
        this.prevslide(e);
      });
    }
  },
  nextslide: function(e) {
    let id = e.target.closest(".question").firstElementChild.id;
    var question = document.getElementById(parseInt(id) + 1);
    question.scrollIntoView({ behavior: "smooth", block: "center"});
  },
  prevslide: function(e) {
    let id = e.target.closest(".question").firstElementChild.id;
    document.getElementById(parseInt(id) - 1).scrollIntoView({ behavior: "smooth", block: "center"});
  },
};

Controls.init();
#container {
  height: 200px;
  overflow: scroll;
}

#header {
  background-color: #f2f2f2;
  padding: 10px;
}

.question {
  padding: 20px;
  border: 1px solid #ccc;
  margin-bottom: 20px;
}

h2 {
  margin: 0;
  margin-bottom: 10px;
}

button {
  padding: 10px 20px;
  background-color: #007bff;
  color: #fff;
  border: none;
  cursor: pointer;
  margin-right: 10px;
}

button:hover {
  background-color: #0056b3;
}

button:disabled {
  background-color: #ccc;
  cursor: not-allowed;
}
<div id="container">
  <div id="header">Header</div>

  <div class="question">
    <h2 id="1">Question 1</h2>
    <button class="prev">Previous</button>
    <button class="next">Next</button>
  </div>

  <div class="question">
    <h2 id="2">Question 2</h2>
    <button class="prev">Previous</button>
    <button class="next">Next</button>
  </div>

  <div class="question">
    <h2 id="3">Question 3</h2>
    <button class="prev">Previous</button>
    <button class="next">Next</button>
  </div>
</div>
Randy
  • 9,419
  • 5
  • 39
  • 56
  • Thanks @Randy, your example is very close to mine, and it works. However, it is impossible to use { behavior: "smooth", block: "center"}, it always scroll to top and instantly. – Luca Scandroglio Jun 24 '23 at 12:44
  • @LucaScandroglio I just added those as parameters in the snippet I provided and the snippet still works. Can you possibly share a working snippet somehow I can work from? Or a URL where you have a test setup? – Randy Jun 24 '23 at 13:52
  • Unfortunately i'm working on a dockerized local environment. But now i have discovered that maybe the problem is in the sass file (more than 1000+ lines), because without it, everything works fine. – Luca Scandroglio Jun 24 '23 at 14:03
1

Solved.

According to this answer, window.scrollTo() function must be invoked on a element with "overflow: auto" property, typically "window". In my case "overflow: auto;" was on an element child. I have solved with:

my_child_element.scrollTo({behavior: 'smooth', left: 0, top: window.innerHeight});

Strange but true.