1

I have few elements I need to slide, but I don't want to attach whole jQ lib. I like jQ a lot, but whole lib is just overkill in this example.

How to convert jq slideUp/slideDown/toggle to vanilla JS with support of multiple elements passed to function?

JQ code:

var $context = getContext(context);

$($context).on('click', '.menu', function () {
    $('.nav').slideToggle();
});

JS code:

var list = document.getElementsByClassName("class1", "class2", "class3");
//or
var list = document.querySelectorAll("class1", "class2", "class3");

var slideUp = function(targets, duration){
    // execution
};

slideUp(list, 500);

SO wizards make it happen! :)

2
  • Since SO isn't a code writing service, I would post your attempts to solve the problem. Right now, you haven't posted any attempt to accomplish the sliding, you just posted the creation of an empty function. Commented Jul 5, 2022 at 18:47
  • You are right. But writing my own ANOTHER vanilla JS toggle is pointless. There are many, I just haven't found one that can use multiple selectors. I'm sure there is one somewhere and some SO wizard can link it. If no I will try to show the solution - ATM it is simply iterating through selectors and slide one by one immediately, after another. One I consider - dev.to/bmsvieira/vanilla-js-slidedown-up-4dkn Commented Jul 5, 2022 at 19:51

3 Answers 3

1

I wasn't happy with the last solution I gave you it was rushed and buggy totally unacceptable, Hope you can forgive me...so this is a better version with the clicks of each item working too

const clicker = document.getElementsByClassName("clicker")[0];
clicker.addEventListener("click", function() {
  process(document.querySelectorAll(".js-toggle"));
});
[...document.querySelectorAll(".js-toggle")].forEach((element) =>
  element.addEventListener("click", function() {
    process(this)
  })
)
const container = [];

function process(linkToggle) {
  container.length = 0
  if (linkToggle.length > 0) {
    for (let i = 0; i < linkToggle.length; i++) {
      container.push(
        document.getElementById(linkToggle[i].dataset.container))
      animate(container[i])
    }
  } else {

    container.push(
      document.getElementById(linkToggle.dataset.container))
    animate(container[0])
  }
}


function animate(element) {
  if (!element.classList.contains("active")) {
    element.classList.add("active");
    element.style.height = "auto";
    let height = parseInt(element.clientHeight || 0)
    element.style.height = "0px";
    setTimeout(function() {
      for (let t = 0; t < container.length; t++) {
        do {
          container[t].style.height =
            parseInt(container[t].style.height || height) +
            1 + 'px'
        } while (parseInt(container[t].style.height || height) < height);
      }
    }, 0);
  } else {
    element.style.height = "0px";
    element.addEventListener(
      "transitionend",
      function() {
        element.classList.remove("active");
      }, {
        once: true
      }
    );
  }
}
.clicker {
  cursor: pointer;
  background: red;
}

.box {
  width: 300px;
  border: 1px solid #000;
  margin: 10px;
  cursor: pointer;
}

.toggle-container {
  transition: height 0.35s ease-in-out;
  overflow: hidden;
}

.toggle-container:not(.active) {
  display: none;
}
<div class="clicker">CLICK ME</div>
<div class="box">
  <div class="js-toggle" data-container="toggle-1">Click1</div>
  <div class="toggle-container" id="toggle-1">I have an accordion and am animating the the height for a show reveal - the issue is the height which i need to set to auto as the information is different lengths.<br><br> I have an accordion and am animating the the height fferent lengths.
  </div>
</div>

<div class="box">
  <div class="js-toggle" data-container="toggle-2">Click2</div>
  <div class="toggle-container open" id="toggle-2">I have an accordion and am animating the the height for a show reveal - the issue is the height which i need to set to auto as the information is different lengths.<br><br> I have an accordion and am animating the the height fferent lengths.
  </div>
</div>

<div class="box">
  <div class="js-toggle" data-container="toggle-3">Click3</div>
  <div class="toggle-container" id="toggle-3">I have an accordion and am animating the the height for a show reveal - the issue is the height which i need to set to auto as the information is different lengths.<br><br> I have an accordion and am animating the the height fferent lengths.
  </div>
</div>

I hope this helps

Sign up to request clarification or add additional context in comments.

Comments

0

you could just use css like so ( wasn't sure witch way you wanted to slid but this gives you an idea of how to do it):

var $slider = document.getElementById('slider');
var $toggle = document.getElementById('toggle');

$toggle.addEventListener('click', function() {
  var isOpen = $slider.classList.contains('slide-in');

  $slider.setAttribute('class', isOpen ? 'slide-out' : 'slide-in');
});
#slider {
  position: absolute;
  width: 100px;
  height: 100px;
  background: blue;
  transform: translateX(-100%);
  -webkit-transform: translateX(-100%);
}

.slide-in {
  animation: slide-in 0.5s forwards;
  -webkit-animation: slide-in 0.5s forwards;
}

.slide-out {
  animation: slide-out 0.5s forwards;
  -webkit-animation: slide-out 0.5s forwards;
}

@keyframes slide-in {
  100% {
    transform: translateX(0%);
  }
}

@-webkit-keyframes slide-in {
  100% {
    -webkit-transform: translateX(0%);
  }
}

@keyframes slide-out {
  0% {
    transform: translateX(0%);
  }
  100% {
    transform: translateX(-100%);
  }
}

@-webkit-keyframes slide-out {
  0% {
    -webkit-transform: translateX(0%);
  }
  100% {
    -webkit-transform: translateX(-100%);
  }
}
<div id="slider" class="slide-in">
  <ul>
    <li>Lorem</li>
    <li>Ipsum</li>
    <li>Dolor</li>
  </ul>
</div>

<button id="toggle" style="position:absolute; top: 120px;">Toggle</button>

I can't take credit for this its lifted from:

CSS 3 slide-in from left transition

I hope this helps

1 Comment

Nice! But I need full JS code. Can't edit any css stylesheets.
0

Could you not simply include the css in the page header so wouldn't need to edit any style sheets, well in any case then how about this:

function SlideDown() {
  const element = document.getElementById("slider");
  let top = 0;
  const up = setInterval(MoveDown, 10);

  function MoveDown() {
    if (top == 50) {
      clearInterval(up);
    } else {
      top++;
      element.style.top = top + '%';
    }
  }
}

function SlideUp() {
  const element = document.getElementById("slider");
  let top = parseInt(element.style.top);
  const down = setInterval(MoveUp, 10);

  function MoveUp() {

    if (top == -100) {
      clearInterval(down);
    } else {
      top--;
      element.style.top = top + '%';
    }
  }
}
<!DOCTYPE html>
<html>
  <body>
    <div id="slider" style="position:absolute; top: -100px;">
      <ul>
        <li>Lorem</li>
        <li>Ipsum</li>
        <li>Dolor</li>
      </ul>
    </div>
    <button onclick="SlideDown()">Slide Down</button>
    <button onclick="SlideUp()">Slide Up</button>
  </body>
</html>

I hope this helps

6 Comments

Way better for my specific needs! However I was thinking about something like this - jsfiddle.net/spamator1212/7495Lv80/11 - be able to toggle many elements at once.
Are you wanting each "cl" to slide to move together or one after the other like a cascade effect?
Hi Patrick! Together with option of the cascade :) - codepen.io/spamator12/pen/abYdoVz I have almost done it, just need some more time cause of work.
posted an update to give you what you wanted, hope it helps
I'm sorry, I didn't have time t update it, I will try your new version ASAP and let you know how it goes. Sorry but it is a crazy week at work!
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.