0

I am trying to create a box that expands and collapses using regular JavaScript (No jQuery). The problem I'm running into is detecting how to properly detect dynamically created elements or classes that are added to elements after pageload.

Here's an example JS fiddle page: http://jsfiddle.net/1a518a4t/3/

As you can see, it works when you collapse and then expand once, but then it won't collapse again.

JS code:

function test() {

    var badge = document.getElementById('test');
    var close_button = document.querySelector('.test-close');

    close_button.addEventListener("click", close_box);

    function close_box() {
        badge.style.bottom = '-70px';
        close_button.classList.add("test-open");
        close_button.classList.remove("test-close");
        var open_button = document.querySelector('.test-open');
        open_button.addEventListener("click", open_box);
    }

    function open_box() {
        badge.style.bottom = '0';
        close_button.classList.remove("test-open");
        close_button.classList.add("test-close");
    }

}
window.onload = test;

I think I really just want to learn how to replicate jQuery's on method in JavaScript. That works for elements that are dynamically created after pageload.

zen
  • 1,115
  • 3
  • 28
  • 54
  • 1
    Possible duplicate of [Event binding on dynamically created elements?](http://stackoverflow.com/questions/203198/event-binding-on-dynamically-created-elements) – Software Engineer Oct 25 '15 at 23:19
  • is this a test for something else? you could just have the one function and use a attribute to determine if to close or open? but for what you asked, you are not removing the closebox action or open box action after use, so both run...http://jsfiddle.net/1a518a4t/6/ check the console, close runs and then open runs so its always open, – David Oct 25 '15 at 23:32

2 Answers2

2

Use a single event listener. And don't modify inline styles, just switch classes:

var badge = document.getElementById('test');
var button = document.querySelector('.button');
button.addEventListener("click", function toggle_box() {
  badge.classList.toggle('opened');
  badge.classList.toggle('closed');
});
#test {
  width: 300px;
  height: 100px;
  background-color: #ccc;
  position: fixed;
  bottom: 0;
  right: 20px;
  transition: all 0.2s;
}
#test.closed {
  bottom: -70px;
}
#test > .button {
  position: absolute;
  top: 10px;
  right: 10px;
  width: 10px;
  height: 10px;
  text-indent: -9999px;
  cursor: pointer;
  background-color: #000;
}
#test.closed > .button {
  background-color: #CE312F; 
}
<div id="test" class="opened">
  <div class="button">Test</div>
</div>
RobG
  • 142,382
  • 31
  • 172
  • 209
Oriol
  • 274,082
  • 63
  • 437
  • 513
  • Yea this works great. Although it's kind of doing a different thing than I originally wanted. i.e. it's changing the class of parent element rather than the clicked element. It will work though since I understand event listening a little better now. – zen Oct 25 '15 at 23:48
1

As mentioned in the comments, this is because the created element is added dynamically and as such you need to delegate so event handler can bind it to the created element. To do that you can look at @Ramswaroop solution to do this in native JavaScript. Although I don't think it's even nessisary to change class and re-bind the different functions. Simply use the same <div> and have a toggle function:

var button = document.querySelector('#test div');
button.addEventListener("click", toggle_box);
...
function toggle_box() {
    if(badge.style.bottom == '-70px') {
        badge.style.bottom = '-0';
        toggleClass("test-close", "test-open");
    } else {
        badge.style.bottom = '-70px';
        toggleClass("test-open", "test-close");
    }
}

Fiddle Example

Community
  • 1
  • 1
Spencer Wieczorek
  • 21,229
  • 7
  • 44
  • 54
  • Yea that works great. I edited my answer to clarify more. I'm trying to understand how jQuery's `on` works in a pure javascript. For example, you can just add `on` method on a parent element, and it will work for any future dynamically created element. – zen Oct 25 '15 at 23:43
  • Adding and removing a class is preferred so that hard coded values like `'-70px'` are replaced by a class, then the offset can be changed in the CSS to whatever, without having to modify the script as well (or worry about direct properties vs computed properties, etc.). – RobG Oct 25 '15 at 23:48