Search code examples
javascriptjquerycssdraggablegsap

jQuery .each update automatically and create global variable?


I'm very new to code. I'm trying to create a scrolling effect using greensock draggable. I'd like my div to drag only if my content of another div exceeds the height value of it's parent's height. Here is the codepen I'm working on - https://codepen.io/kbeats/pen/vVYGOX

So far, I have for my dragging and scrolling code:

Draggable.create("#scrollIcon", {
  type: "y",
  bounds: "#toc", 
  onDrag: scroll
});

$(".tile").each(function(){
 var height = $(this).height();
 });

function scroll(){
    if(height > $(toc).height()){
    TweenMax.set(".tile", {y: this.y * -1})
    }
 }

The console.log is saying 'height' is undefined, so I'm guessing it's only being stored as a local variable? Is there a way to iterate through each .tile class and create a global variable of the sum total height that will update automatically when the height changes? (Or maybe just update each time a .tile element is clicked?)

Ultimately, I'm trying to have my 'scroll' div only scroll when the .tile class content exceeds the parent (#toc) height and then somehow create an equation where the scroll amount will adjust depending on the total height of the .tile class. (So it will always be able to scroll through all the content, but not overshoot).


Solution

  • The problem is that in this section:

    $(".tile").each(function(){
     var height = $(this).height();
     });
    

    height is only available in that scope. Also, you want to sum up the heights, not just the height of one of the .tiles. Instead, you should do the each inside of the scroll function, and sum up the heights.

    Also, you will want to scale the tween by the height ratio between the tile total and the toc, because the amount you'll want to scroll is not only based on the absolute height of the scrollbar. Instead of this.y * -1, you probably want something more like this.y * height / $(toc).height() * -1.

    function scroll(){
        var height= 0;
        $('.tile').each(function() {
          height += $(this).height();
        });
        if(height > $(toc).height()) {
          TweenMax.set(".tile", {
            y: this.y * height / $(toc).height() * -1
          });
        }
    

    var base = document.getElementById("Base");
    var tab = document.getElementById("Tab");
    var arrows = document.getElementById("tocArrows");
    var content = document.getElementsByClassName("tile");
    var toc = document.getElementById("toc");
    
    //
    
    
    // variables for slides
    
    var oneSlideOne = document.getElementById("oneSlideOne");
    var oneSlideTwo = document.getElementById("oneSlideTwo");
    
    var twoSlideOne = document.getElementById("twoSlideOne");
    var twoSlideTwo = document.getElementById("twoSlideTwo");
    
    // menu open and close timeline
    
    var tl = new TimelineMax({
      paused: true,
      reversed: true
    });
    tl.to(base, .5, {
      x: 280,
      ease: Sine.easeInOut
    });
    tl.to("#start1", 0.8, {
      morphSVG: "#end1",
      ease: Back.easeInOut
    }, 0);
    tl.to("#start2", 0.8, {
      morphSVG: "#end2",
      ease: Back.easeInOut
    }, 0);
    
    
    arrows.addEventListener("mousedown", openMenu);
    
    function openMenu() {
      tl.reversed() ? tl.play() : tl.reverse();
    }
    
    // making the accordion menu
    
    var acc = document.getElementsByClassName("tile");
    var i;
    
    for (i = 0; i < acc.length; i++) {
      acc[i].addEventListener('click', function() {
        this.classList.toggle("active");
    
        var $panel = $("ul, li", this);
        this.classList.contains("active") ? $panel.show() : $panel.hide();
      })
    }
    
    
    // gsap for custom scroll bar? 
    
    Draggable.create("#scrollIcon", {
      type: "y",
      bounds: "#toc",
      onDrag: scroll
    });
    
    
    function scroll() {
      var height = 0;
      $('.tile').each(function() {
        height += $(this).height();
      });
      if (height > $(toc).height()) {
        TweenMax.set(".tile", {
          y: this.y * height / $(toc).height() * -1
        })
      }
    }
    .base {
      height: 250px;
      width: 280px;
      background-color: #17307F;
      position: absolute;
      left: -280px;
      top: 0px;
    }
    
    .tab {
      background-color: #17307F;
      position: absolute;
      width: 80px;
      height: 80px;
      left: 280px;
      border-radius: 0px 0px 20px 0px;
    }
    
    #scrollIcon {
      background-color: white;
      width: 25px;
      height: 50px;
      position: relative;
      float: right;
      margin-top: 20px;
      margin-right: 15px;
      border-radius: 30px;
      cursor: pointer;
    }
    
    #tocArrows {
      width: 50px;
      height: 50px;
      display: inline;
      margin: 0 auto;
      padding-top: 15px;
      padding-left: 15px;
      cursor: pointer;
    }
    
    #tocReverse {
      width: 50px;
      height: 50px;
      display: inline;
      margin: 0 auto;
      cursor: pointer;
      position: relative;
      top: -52px;
      visibility: hidden;
    }
    
    ul#toc {
      list-style: none;
      display: block;
      height: 200px;
      overflow: hidden;
      /*overflow-y: scroll;
      overflow-x: hidden;*/
    }
    
    li {
      position: relative;
      left: -40px;
      text-decoration: none;
      display: block;
    }
    
    li .subTile {
      display: none;
    }
    
    .tile {
      background-color: #74A3EB;
      width: 220px;
      padding-top: 10px;
      padding-bottom: 10px;
      border-radius: 10px;
      color: white;
      font-family: lato;
      font-weight: 700;
      font-size: 24px;
      line-height: 40px;
      text-align: center;
      cursor: pointer;
      margin: 10px 2px 0px 10px;
      transition: 0.4s ease-in-out;
      display: block;
      top: 0px;
      left: -40px;
    }
    
    .active,
    .tile:hover {
      background-color: #3C72F0;
      /* change this color */
    }
    
    .subTile {
      display: none;
      position: relative;
      background-color: #99B4FF;
      width: 200px;
      height: 40px;
      border-radius: 10px;
      display: none;
      overflow: hidden;
      max-height: 100%;
      color: white;
      font-family: lato;
      text-align: center;
      line-height: 40px;
      font-size: 20px;
      margin: 0px 10px 6px 10px;
      cursor: default;
      transition: background-color 0.2s ease-in-out;
    }
    
    .subTile:hover {
      background-color: #F2BB22;
    }
    
    #twoSlideTwo {
      font-size: 16px;
      height: 60px;
      line-height: 30px;
    }
    
    #twoSlideThree {
      font-size: 16px;
    }
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.0.2/TweenMax.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/gsap/2.0.1/utils/Draggable.min.js"></script>
    <div class=base id="Base">
      <div class=tab id="Tab">
        <svg id="tocArrows" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 47.95 63.28"><title>tocArrows</title><polyline id="start1" points="15.07 3 43.71 31.64 15.07 60.28" fill="none" stroke="#fff" stroke-linecap="round" stroke-miterlimit="10" stroke-width="6"/><polyline id="start2" points="3 9.96 24.68 31.64 3 53.32" fill="none" stroke="#fff" stroke-linecap="round" stroke-miterlimit="10" stroke-width="6"/></svg>
        <svg id="tocReverse" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 47.95 63.28"><title>tocReverse</title><polyline id="end1" points="32.88 60.28 4.24 31.64 32.88 3" fill="none" stroke="#fff" stroke-linecap="round" stroke-miterlimit="10" stroke-width="6"/><polyline id="end2" points="44.95 53.32 23.27 31.64 44.95 9.96" fill="none" stroke="#fff" stroke-linecap="round" stroke-miterlimit="10" stroke-width="6"/></svg>
      </div>
      <div class="scrollPane" id="scrollIcon"> </div>
    
    
      <ul id="toc">
        <li class="tile" id="moduleOneTitle"> Module One
          <ul>
            <li class="subTile modOne" id="oneSlideOne"> Title Slide </li>
            <li class="subTile modOne" id="oneSlideTwo"> References </li>
            <li class="subTile modOne" id="oneSlideThree"> Introduction </li>
            <li class="subTile modOne" id="oneSlideFour"> Next Slide </li>
          </ul>
        </li>
        <li class=tile id="moduleTwoTitle"> Module Two
          <ul>
            <li class="subTile modTwo" id="twoSlideOne"> Title Slide </li>
            <li class="subTile modTwo" id="twoSlideTwo"> Third Slide Long Name </li>
            <li class="subTile modTwo" id="twoSlideThree"> Fourth Slide Long </li>
          </ul>
        </li>
      </ul>
    
    </div>