Delete event associated with an anonymous function

1

I have the following function that associates events with a series of elements:

function colorCeldasActivo(color)
{

  //Damos eventos a todas las celdas
    var celdas = document.getElementsByClassName("celdadibujo");
    for (var i = 0; i < celdas.length; i++) {        
        celdas[i].addEventListener("mouseover", function(){this.id = color; 
        document.body.style.cursor = "pointer"; });
        celdas[i].addEventListener("mouseout", function(){ 
        document.body.style.cursor = "auto"; });
        celdas[i].addEventListener("click",
        colorCeldasInactivo);
    }      
 }

In another function I want to remove the mouse events associated with the cells:

function colorCeldasInactivo(){   

var celdas = document.getElementsByClassName("celdadibujo");
 for (var i = 0; i < celdas.length; i++) {            
      celdas[i].removeEventListener("mouseover", function(){this.id = color; 
   document.body.style.cursor = "pointer"; });
        celdas[i].removeEventListener("mouseout", function(){ 
  document.body.style.cursor = "auto"; });
   }   
 }

The question is that with removeEventListener it is not valid because it does not erase events with anonymous functions according to what I have looked at. So what would be the way to deactivate these events? Possibly it is easy but I do not give with it. Greetings and thanks

    
asked by Carlos Rayón Álvarez 09.02.2018 в 04:40
source

2 answers

3

The best solution is to clone the element and replace the original in the DOM: the new one will not have the events:

function colorCeldasInactivo() {
   var celdas = document.getElementsByClassName("celdadibujo");
   for (let i=0; i<celdas.length; i++) {
     let clon=celdas[0].cloneNode(true); //true es copia en profundidad
     celdas[0].parentNode.replaceChild(clon,celdas[0]);
   }

 }

But you could add the behavior by CSS and not need as many event listeners

    
answered by 09.02.2018 в 10:28
3

Do not you think it would be better to manage it with CSS?

.celdadibujo {
  cursor: auto;
}
.celdadibujo:hover {
  cursor: pointer;
}

That would work so that when you move the mouse over, the cursor changes. But you also want to suppress that behavior on certain occasions. Then let's say that the behavior only occurs when the elements .celdadibujo have also the class cursorpointer .

.celdadibujo {
  cursor: auto;
}
.cursorpointer:hover {
  cursor: pointer;
}

So you can add the class (and therefore the hover) by invoking:

function activar() {
    var celdas = document.querySelectorAll('.celdadibujo');
    celdas.forEach(function (celda) {
        celda.classList.add('cursorpointer');
    });
}

And remove the class by invoking

function desactivar() {
    var celdas = document.querySelectorAll('.celdadibujo');
    celdas.forEach(function (celda) {
        celda.classList.remove('cursorpointer');
    });
}

The function that you put in the question assigns to each cell the id defined by the variable color . You can not ( do not ) have more than one node with the same id. But if you want to change the color of the cell and also make a click on one of them deactivate the color, the pointer and delete the listener on the event click :

function desactivar() {
	var celdas = document.querySelectorAll('.celdadibujo');
	celdas.forEach(function (celda) {
		celda.className = 'celdadibujo';
    celda.removeEventListener('click', desactivar);    
	});
}

function activar(color) {
	var celdas = document.querySelectorAll('.celdadibujo');
	celdas.forEach(function (celda) {
		celda.className = 'celdadibujo';
		celda.classList.add('cursorpointer');
		celda.classList.add(color);
    celda.addEventListener("click", desactivar);
	});
}
table {
	border: 1px solid;
}

td {
	border: 1px solid;
	padding: 2px 5px;
}

.celdadibujo {
	cursor: auto;
}

.cursorpointer:hover {
	cursor: pointer;
}

.buttoncolor {
	padding: 7px 7px;
	margin: 0 3px;
	vertical-align: super;
}

.cursorpointer.red {
	border: 1px solid red;
}

.cursorpointer.blue {
	border: 1px solid blue;
}

.cursorpointer.green {
	border: 1px solid green;
}

#red {
	background-color: red;
}

#blue {
	background-color: blue;
}

#green {
	background-color: green;
}
<button class="buttoncolor" id="red" onclick="activar(this.id)"></button>
<button class="buttoncolor" id="blue" onclick="activar(this.id)"></button>
<button class="buttoncolor" id="green" onclick="activar(this.id)"></button>
<button onclick="desactivar()">Desactivar cursor pointer</button>
<table border="1">
    <tr>
        <td class="celdadibujo">Texto A</td>
        <td class="celdadibujo">Texto B</td>
        <td class="celdadibujo">Texto C</td>
    </tr>
    <tr>
        <td class="celdadibujo">Texto D</td>
        <td class="celdadibujo">Texto E</td>
        <td class="celdadibujo">Texto F</td>
    </tr>
    <tr>
        <td class="celdadibujo">Texto G</td>
        <td class="celdadibujo">Texto H</td>
        <td class="celdadibujo">Texto I</td>
    </tr>
</table>

In case you want to add the behavior to the whole body, the function is simpler. You just have to add and remove the class of the body element instead of iterating every .celdadibujo

    
answered by 09.02.2018 в 11:58