1

I got the following simple page.

<style>
    #notifier {
        position: fixed;
        width: 320px;
        bottom: 0;
        left: 0;
        padding: 10px;
    }

    #notification-silo {
        width: 300px;
        height: 100%;
        position: relative;
    }

        #notification-silo .notification {
            position: absolute;
            bottom: 0;
            width: 300px;
            background-color: #fff;
            box-shadow: 2px 2px 8px 2px #666;
        }

        #notification-silo .header {
            background-color: #1266AB;
            color: #fff;
            padding: 5px;
        }

        #notification-silo .error .header {
            background-color: #1266AB;
        }

        #notification-silo .warning .header {
            background-color: #ff8f5f;
        }

        #notification-silo .header .title {
            width: 260px;
            display: inline-block;
        }

        #notification-silo .header .close-wrapper {
            display: inline-block;
        }

            #notification-silo .header .close-wrapper button {
                height: 25px;
                width: 25px;
                background-color: #2277bb;
                border: 0;
                color: #ff8f5f;
                border-radius: 50%;
            }

        #notification-silo .warning .header .close-wrapper button {
            background-color: #ffaa77;
            color: #2277bb;
        }

    #notifier .body {
        padding: 5px;
        border: 1px solid lightgray;
    }
</style>

<div id="notifier">
    <div id="notification-silo">
    </div>
</div>

<script>
    function show(html) {
        let notification, notificationArray, body, closeButton, existingNotificationHeights, sum, bottom, notification_template, siloElement, marginBetweenNotifications;

        siloElement = document.querySelector("#notification-silo");
        notification_template = `<div class="notification">
                                    <div class="header">
                                        <div class="title">Message</div>
                                        <div class="close-wrapper">
                                            <button>X</button>
                                        </div>
                                    </div>
                                    <div class="body"></div>
                                </div>`;
        marginBetweenNotifications = 10;

        // calculate position
        existingNotificationHeights = [...siloElement.children].map(notification => notification.offsetHeight);
        sum = existingNotificationHeights.length ? existingNotificationHeights.reduce((a, b) => a + b) : 0;
        bottom = sum + existingNotificationHeights.length * marginBetweenNotifications;

        // creat elements by update innerHTML
        siloElement.innerHTML += notification_template.trim();
        notificationArray = [...siloElement.querySelectorAll(".notification")];
        notification = notificationArray[notificationArray.length - 1];
        notification.style.bottom = bottom + "px";
        body = notification.querySelector(".body");
        body.innerHTML += html;

        // add event listener to close button
        closeButton = notification.querySelector(".close-wrapper button");
        closeButton.addEventListener("click", (ev) => {
            console.log("click is fired");
        });
    };
    
    show("System message 1");
    show("System message 2");
    show("System message 3");
    show("System message 4");
    show("System message 5");
</script>

It meant to create simple notification messages through show(msg) function. Here is the interesting part - when create few messages and try to add event listener to their close buttons, only the last button get a listener and actually listen for click event. All other close buttons do not react to mouse click. Can you please help me to understand why?

2
  • 1
    I guess siloElement.innerHTML += notification_template.trim() wipes off the html content and re-assigned again, so previous events are removed. Commented Oct 10, 2021 at 11:44
  • You are 100% right - I missed that aspect. This is the true reason for my pain. Thanks! Commented Oct 10, 2021 at 12:02

2 Answers 2

1

only you have to get close button reference object

    show("System message 1");
    show("System message 2");
    show("System message 3");
    show("System message 4");
    show("System message 5");

[].forEach.call(document.querySelectorAll("#notification-silo button.close-wrapper"),function(el){
      el.addEventListener("click",function(ev){
            var targetElement = ev.target || ev.srcElement;
            console.log(targetElement); //reference of button... 
      });
    });

OR

<div class="close-wrapper">
     <button onClick="Close(this)">X</button>
</div>

OR Perfect as One Standard Way don't use static html template string use dynamic pure JavaScript based element create method

example :

let mainDiv = document.querySelector("#notification-silo");
let aTag = document.createElement('a');
aTag.innerHTML = "CLOSE TEXT....";
aTag.addEventListener("click", (ev) => {
        console.log("click is fired");
});
mainDiv.appendChild(aTag);
Sign up to request clarification or add additional context in comments.

4 Comments

Try to replace your patch in the page and then click on close buttons. Only the last created will be firing this console.log. The other buttons are silenced.
@P.Petkov i updated some thing this answer
please recheck the answer
Аlthough, your answer is very detailed, the real question is "Why" and ProGu answered it first under my question. However, thanks for the efforts!
0

Quoting ProGu:

I guess siloElement.innerHTML += notification_template.trim() wipes off the html content and re-assigned again, so previous events are removed.

Comments

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.