Home > other >  Can't get JS native animate() to work with height
Can't get JS native animate() to work with height

Time:04-22

I'm trying to do scrollUp and scrollDown with a native JS Element.animate(). I want the element to appear smoothly from the top to the bottom. What I get is an immediate opening and delayed collapsing. If there are currently better ways to do it, I'd like to know, I'm still curious why doesn't this work though.

document.addEventListener('DOMContentLoaded', function() {
  document.getElementById('addNewScriptStep').onclick = function() {
    let list = document.getElementById('collapsibleActionList');
    let newHeight = '100%';
    if (list.dataset.iscollapsed == 'false') {
      newHeight = '0';
    }
    list.dataset.iscollapsed = !eval(list.dataset.iscollapsed);
    list.animate({
      height: newHeight
    }, {
      fill: 'forwards',
      duration: 500
    });
  };
});
#collapsibleActionList {
  overflow: hidden;
  height: 0;
  transition: height 0.5s;
}
<html>

<body>
  <a href="javascript:void(0)" id="addNewScriptStep" > Add an action </a>
  <ul id="collapsibleActionList" data-iscollapsed="true">
    <li data-type="open_url">Open URL</li>
    <li data-type="href_to">Click link</li>
    <li data-type="click_element">Click element</li>
    <li data-type="insert_into">Insert into textbox</li>
    <li data-type="sleep">Sleep</li>
    <li data-type="checked">Check checkbox</li>
    <li data-type="unchecked">Uncheck checkbox</li>
    <li data-type="send_form">Submit form</li>
    <li data-type="if_element_is_defined">Continue if HTML contains element</li>
    <li data-type="if_element_is_not_defined">Continue if HTML doesn't contain element</li>
    <li data-type="if_text_is_defined">Continue if there is text</li>
    <li data-type="if_text_is_not_defined">Continue if there is no text</li>
  </ul>
</body>

</html>

Edit: I noticed that after removing CSS transition property, the list can no longer collapse, though animate function IS being called with {height: '0'}

CodePudding user response:

with useing max-height instead of height you can do it.

document.addEventListener('DOMContentLoaded', function() {
  document.getElementById('addNewScriptStep').onclick = function() {
    let list = document.getElementById('collapsibleActionList');
    let newHeight = '999px';
    if (list.dataset.iscollapsed == 'false') {
      newHeight = '0';
    }
    list.dataset.iscollapsed = !eval(list.dataset.iscollapsed);
    list.animate({
      maxHeight: newHeight
    }, {
      fill: 'forwards',
      duration: 500
    });
  };
});
#collapsibleActionList {
  overflow: hidden;
  max-height: 0;
  transition: max-height 0.5s;
}
<body>
  <a href="javascript:void(0)" id="addNewScriptStep" > Add an action </a>
  <ul id="collapsibleActionList" data-iscollapsed="true">
    <li data-type="open_url">Open URL</li>
    <li data-type="href_to">Click link</li>
    <li data-type="click_element">Click element</li>
    <li data-type="insert_into">Insert into textbox</li>
    <li data-type="sleep">Sleep</li>
    <li data-type="checked">Check checkbox</li>
    <li data-type="unchecked">Uncheck checkbox</li>
    <li data-type="send_form">Submit form</li>
    <li data-type="if_element_is_defined">Continue if HTML contains element</li>
    <li data-type="if_element_is_not_defined">Continue if HTML doesn't contain element</li>
    <li data-type="if_text_is_defined">Continue if there is text</li>
    <li data-type="if_text_is_not_defined">Continue if there is no text</li>
  </ul>
</body>

you can do this in a simpler way. if you want?

const link = document.getElementById('addNewScriptStep')
const list = document.getElementById('collapsibleActionList')
link.addEventListener('click',()=>{
  list.classList.toggle('open')
})
#collapsibleActionList {
  overflow: hidden;
  max-height: 0;
  transition: max-height 0.5s;
}
#collapsibleActionList.open {
  overflow: hidden;
  max-height: 999px;
  transition: max-height 0.5s;
}
<body>
  <a href="javascript:void(0)" id="addNewScriptStep" > Add an action </a>
  <ul id="collapsibleActionList" data-iscollapsed="true">
    <li data-type="open_url">Open URL</li>
    <li data-type="href_to">Click link</li>
    <li data-type="click_element">Click element</li>
    <li data-type="insert_into">Insert into textbox</li>
    <li data-type="sleep">Sleep</li>
    <li data-type="checked">Check checkbox</li>
    <li data-type="unchecked">Uncheck checkbox</li>
    <li data-type="send_form">Submit form</li>
    <li data-type="if_element_is_defined">Continue if HTML contains element</li>
    <li data-type="if_element_is_not_defined">Continue if HTML doesn't contain element</li>
    <li data-type="if_text_is_defined">Continue if there is text</li>
    <li data-type="if_text_is_not_defined">Continue if there is no text</li>
  </ul>
</body>

CodePudding user response:

height: 100% in this context doesn't really bring any meaning: as it's not dependent on a height of some parent element, it's basically the same as height: auto and you can't animate using height:auto. Now, considering that you are already using .js, before animating the element you can first set its innate height in pixels that you want to animate to:

const ul = document.querySelector("ul")
const btn = document.querySelector("button")

//the important part:
ul.style.height = ul.scrollHeight   "px"

btn.addEventListener("click", ()=>ul.classList.toggle("open"))
ul{
  display: block;
  overflow: hidden;
  transition: height 1s;
  background: #ddd;
}

ul:not(.open){
  height: 0 !important;
}
<button>Click</button>
<ul>
  <li>Some elements</li>
  <li>To show</li>
</ul>

  • Related