简体   繁体   中英

How to reattach eventListeners?

Function prepareMapEventListener() adds 256 EventListeners ( el.addEventListener("click", function (e) { B_modeWindow('1', cords) }); )

After I hange code with outerHTML in document.getElementById(XxY).outerHTML=xmlhttp.responseText; I have to redo adding EventListener for that element, which I tried to acomplish with:

// refresh clicable map after it's edited
function refreshMapEventListener() {
    var el = document.getElementById(position);
    el.addEventListener("click", function (e) { B_modeWindow('1', position) });
}

but it does half of its job: it updates Listeners but only for last element clicked - If I click 10 elements and than want to alter 5th of them - 10th element will be changed.

So I tried reapplaying Listeners to every element with deleting and replacing refreshMapEventListener(); with prepareMapEventListener() in:

    xmlhttp.onreadystatechange=function() {
        if (xmlhttp.readyState==4 && xmlhttp.status==200) {
            document.getElementById(XxY).outerHTML=xmlhttp.responseText;  
            refreshMapEventListener();
            hideloading();
        }
    }

and it works! But each try doubles output - so after 2 click I have 3 AJAX calls, after 3 clicks I have 6, than 12.

How to solve that?

Live example (make sure to watch console/firebug):

http://xn--wiadomesny-37b.pl/stackoverflow/

Full code below:

// prepare clicable map
function prepareMapEventListener() {
    for (x = 1; x <= 16; x++) {
    for (y = 1; y <= 16; y++) {
        (function prepareClickableMap() {
            var cords = x + "x" + y;
            var el = document.getElementById(cords);
            el.addEventListener("click", function (e) { B_modeWindow('1', cords) });
        })();
    }
    }
}

// selection mode
var s;
function selectionMade(e) {
    selection = e.currentTarget.id.split("_"); 
    s = selection[1];
}

// send edited map info to DB
var position;
function B_modeWindow (id,XxY) {  
    if (s !== undefined) {    
        loading();

        var xmlhttp;
        position = XxY;

        if (window.XMLHttpRequest) {
            xmlhttp=new XMLHttpRequest();
        } else {
            xmlhttp=new ActiveXObject("Microsoft.XMLHTTP");
        }

        var xy = position.split("x"); 

        xmlhttp.onreadystatechange=function() {
            if (xmlhttp.readyState==4 && xmlhttp.status==200) {
                document.getElementById(XxY).outerHTML=xmlhttp.responseText;  
                prepareMapEventListener();
                hideloading();
            }
        }

        xmlhttp.open("GET","processMapEdit.php?id="+id+"&x="+xy[0]+"&y="+xy[1]+"&s="+s,true);
        xmlhttp.send();
    }
}

From your comment (and your live example) we learnt that all you want is just a new class for HTML element. That's much easier...

Change your

xmlhttp.onreadystatechange=function() {
            if (xmlhttp.readyState==4 && xmlhttp.status==200) {
                document.getElementById(XxY).outerHTML=xmlhttp.responseText;  
                prepareMapEventListener();
                hideloading();
            }
        }

to

xmlhttp.onreadystatechange=function() {
            if (xmlhttp.readyState==4 && xmlhttp.status==200) {
                document.getElementById(XxY).className=xmlhttp.responseText;
                hideloading(); //I don't know what this is, so I leave it here
            }
        }

And modify your processMapEdit.php to return only the desired class name instead of a whole DIV element.

Also, there might be some browser that doesn't work well when XMLHttpRequest fetched plain text instead of valid XML text, so you may want to add

xmlhttp.overrideMimeType("text/plain")

before send() .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM