Home > Blockchain >  fire a classLiss.add event only once in a loop in raw JS
fire a classLiss.add event only once in a loop in raw JS

Time:09-26

everybody. I've a problem probably well-know, but I can't find a solution also looking for it in the WEB. I'm working on a progressive bar that shows the parts included in a 'title section' during screen scrolling. Everything works fine except when I try to add a class (and remove it), because I'm not able to fire the event only once in the for-next loop. Here is a part of the HTLM:

  <body>
    <div class="container">
      <section class="onTop">
        <nav>
            <div class="scroll-title">MENU</div>
          <div id="scroll-total">
            <div id="scroll-part"></div>
          </div>
        </nav>
      </section>
      <div class="wrapper">
        <div class="title">FIRST TITLE</div>
        <p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Dolorum, aut quo blanditiis hic numquam, sapiente maiores id,
[etc.]

here is the CSS parts those apply:

.scroll-title{
  text-align: right;
  font-size: 10px;
  width: 15.5vh;
  position: absolute;
  top: 14%;
  left: 50%;
  transform: translateX(-50%) rotate(90deg);
  border: 1px solid red;
  transition: font-size .25s ease-out;
}
.scroll-title.action{
  font-size: 20px;
}

The JS code put titles' heigths refecences in an array, then check if the scroll position is inside a part an move the bar. In that time the code changes the single title's DIV containing "scroll-title" class. My idea is to add a CSS class to animate (with a transition) the title. So, I'm using a addEventListener to add and remove the class, but I'd like to fire this event only once, and I can't find a way to do it. Thisi a part of the code:

let titleScroll = document.querySelector('.scroll-title');
let band = document.getElementById('scroll-total');
let scroll = document.getElementById('scroll-part');
let pageTitlesRif =[], pageTitlesText =[];
let pageTitles = document.querySelectorAll('.wrapper .title');
pageTitlesRif  = [0];
pageTitlesText =['MENU'];
let rect;
let tot = band.offsetWidth;
      let totSide = bandSide.offsetHeight;
      for (var i = 0; i < pageTitles.length; i  ) {
        rect = pageTitles[i].getBoundingClientRect();
        pageTitlesText.push(pageTitles[i].innerText);
        pageTitlesRif.push(rect.bottom   document.documentElement.scrollTop);
      }
      let scrollHeight = Math.max(
        document.body.scrollHeight, document.documentElement.scrollHeight,
        document.body.offsetHeight, document.documentElement.offsetHeight,
        document.body.clientHeight, document.documentElement.clientHeight
      );
      pageTitlesRif.push(scrollHeight);
      console.log(scrollHeight);

      window.onscroll = function() {
        for (var i = 1; i < pageTitlesRif.length; i  ) {
          if (window.pageYOffset > pageTitlesRif[i - 1] && window.pageYOffset < pageTitlesRif[i]) {
            titleScroll.classList.add('action');
            let transitionEnd = whichTransitionEvent();
            titleScroll.addEventListener(transitionEnd, putClass, false);
            titleScroll.innerText = pageTitlesText[i - 1];
            scroll.style.left = (pageTitlesRif[i-1] * tot / scrollHeight).toString()  'px';
            scroll.style.width = ((pageTitlesRif[i] - pageTitlesRif[i - 1])  * tot / 
            scrollHeight).toString()   'px';
          }
        }
      }

      let putClass = function(){
        this.classList.remove('action');
      }

      function whichTransitionEvent(){
          var t;
          var el = document.createElement('fakeelement');
          var transitions = {
            'transition':'transitionend',
            'OTransition':'oTransitionEnd',
            'MozTransition':'transitionend',
            'WebkitTransition':'webkitTransitionEnd'
          }

          for(t in transitions){
              if( el.style[t] !== undefined ){
                  return transitions[t];
              }
          }
      }

Has somebody a suggestion to fix this?

CodePudding user response:

Well, I had the solution under my eyes, and I made a mountain out of a molehill... It's enuogh to control if the existing title is different from the one that comes in the loop, like this:

window.onscroll = function() {
        for (var i = 1; i < pageTitlesRif.length; i  ) {
          if (window.pageYOffset > pageTitlesRif[i - 1] && window.pageYOffset < pageTitlesRif[i]) {
           if (titleScroll.innerText != pageTitlesText[i - 1]){
              titleScroll.innerText = pageTitlesText[i - 1];
              titleScroll.classList.add('action');
              let transitionEnd = whichTransitionEvent();
              titleScroll.addEventListener(transitionEnd, putClass, false);
              scroll.style.left = (pageTitlesRif[i-1] * tot / scrollHeight).toString()  'px';
              scroll.style.width = ((pageTitlesRif[i] - pageTitlesRif[i - 1])  * tot / 
              scrollHeight).toString()   'px';
            }
          }
        }
      }

In this way, the code on the title (and on the other tag elements) in executed once.

  • Related