Javascript class events set for an instance fire for all previous instances

I have a class which creates mousedown listeners for each LI. However, a click to the LI of the first instance results in events firing for every LI instance which was created after it. If you create a 3rd instance, the click on the 1st instance will result in all 3 firing and a click on the 2nd results in the 2nd and 3rd firing, etc.

To duplicate, run the jsfiddle and click on the two links (one after the other) which will create two UL elements each containing an LI element. Alerts() are set up to show each event firing. If you continue to click on the links, you will see how the events continue to stack.

I’m new to creating classes in javascript, so I’ve obviously missed something, but can’t see why the events for the multiple instances are not separate. In case you’re wondering, I’ve created my class the way I did to allow for static variables and methods. I am not using jQuery.

I’ve posted a jsfiddle of the below code

UPDATE Fixed errors due to paring complicated code down for SO. I’ve updated to reflect multiple LI elements being created in each UL (the number is dynamic and db driven) and the ID’s being unique.

<div id="outer">
    <a href="#" onclick="edit('g123')">Click here first id=g123</a>
    <br> 
    <a href="#" onclick="edit('g234')">Click here second id=g234</a>
</div>    
    
<script>

listbox = (function (id) {
        var currentul = "";
        var counter = 0;
    
        function listbox(id) {
            this.id = id;
        };
    
        // show or hide once all the properties are set
        listbox.prototype.go = function () {
            this.initlistbox();
            this.addlisteners();
        }
    
        // create the elements for drag and drop between two list boxes
        listbox.prototype.initlistbox = function () {
            var _this = this;
            var divlist = document.createElement('div');
            divlist.style.minHeight = '100px';
            divlist.style.width = '300px'
            divlist.style.outline = '1px solid blue'
    
            // the UL
            var ul = document.createElement('ul');
            ul.setAttribute('id', 'ulchosen-' + this.id);
    
            // track which UL is active for keystrokes
            ul.addEventListener('click', function (e) {
                if (e.stopPropagation) e.stopPropagation();
                currentul = this.id;
            }, false);
    
            // add the ul to the div
            divlist.appendChild(ul);
    
            divouter = document.getElementById("outer");
            // add the div to the body
            divouter.appendChild(divlist);
    
            // The LI
            // create LI elements
            for (i=0; i < 4; i++){
                var li = document.createElement('li');
                counter++;
                li.setAttribute('id', 'lb-li-chosen-' + counter);
                li.innerHTML = "Hello " + counter + " " + this.id;
                ul.appendChild(li);
            }    
        };
    
        listbox.prototype.addlisteners = function () {
            var _this = this;
    
            var lis = document.querySelectorAll("[id^='lb-li-']");
            for (var i = 0; i < lis.length; i++) {
                this.setlilisteners(lis[i]);
            }
        };
    
        listbox.prototype.setlilisteners = function (el) {
            var _this = this;
    
            // click is for non drag, non shift / ctrl
            el.addEventListener('click', function (e) {
                alert("A: " + _this.id);
                e.preventDefault();
                return false;
            }, false);
    
            // mousedown is to select LI elements
            el.addEventListener('mousedown', function (e) {
                e.stopPropagation();
                e.preventDefault();
                alert("B: " + _this.id);
                return false;
            }, false);
    
        };
    
        return listbox;
    })();
    
    function edit(id) {
        var a = new listbox(id);
        a.go();
    } 
</script>

Answer

Each time you use addEventListener a new function is stacked for execution. addEventListener does not removes the older function. So you have to call it just once per element.

The code below will work.

listbox = (function (id) {
    var currentul = "";

    function listbox(id) {
        this.id = id;
    };

    // show or hide once all the properties are set
    listbox.prototype.go = function () {
        this.initlistbox();
    }

    // create the elements for drag and drop between two list boxes
    listbox.prototype.initlistbox = function () {
        var _this = this;
        var divlist = document.createElement('div');
        divlist.style.minHeight = '100px';
        divlist.style.width = '300px'
        divlist.style.outline = '1px solid blue'

        // the UL
        var ul = document.createElement('ul');
        ul.setAttribute('id', 'ulchosen-' + this.id);

        // track which UL is active for keystrokes
        ul.addEventListener('click', function (e) {
            if (e.stopPropagation) e.stopPropagation();
            currentul = this.id;
        }, false);

        // add the ul to the div
        divlist.appendChild(ul);

        divouter = document.getElementById("outer");
        // add the div to the body
        divouter.appendChild(divlist);

        // The LI
        // create LI elements
        var li = document.createElement('li');
        li.setAttribute('id', 'lb-li-chosen-1');
        li.innerHTML = "Hello " + this.id;
        ul.appendChild(li);

        this.setlilisteners(li);

    };

    listbox.prototype.setlilisteners = function (el) {
        var _this = this;

        // click is for non drag, non shift / ctrl
        el.addEventListener('click', function (e) {
            alert("A: " + _this.id);
            e.preventDefault();
            return false;
        }, false);

        // mousedown is to select LI elements
        el.addEventListener('mousedown', function (e) {
            e.stopPropagation();
            e.preventDefault();
            alert("B: " + _this.id);
            return false;
        }, false);

    };

    return listbox;
})();

function edit(id) {
    var a = new listbox(id);
    a.go();
}

Leave a Reply

Your email address will not be published. Required fields are marked *