Make a helper function
One way to simplify this is to use a function to abstract removing the class name from the element. For example, create one like removeInactiveClassToElement
:
removeInactiveClassToElement = (el) => el.classList.remove('inactive');
Then just call that function when necessary. For the case when calling in setTimeout(), use Function.bind() to make a partially-applied function, passing null
as the thisArg argument, and then element
as the first argument.
if (delay) {
setTimeout(removeInactiveClassToElement.bind(null, element), delay * i);
}
else {
removeInactiveClassToElement(element)
}
As you can see above, I switched the logic around so that the delay is added when delay
has a value, and used that instead of this.delay
, though if you wanted to set that property on the instance you could do that...
Functional approach
One could also use Array.forEach() instead of using the for
statement. While it could slow performance (due to an extra function call on each iteration), it could cut the first couple lines out (e.g. assigning const element = this.elements[i];
).
this.elements.forEach((marker, i) => {
if (delay) {
setTimeout(removeInactiveClassToElement.bind(null, marker), delay * i);
}
else {
removeInactiveClassToElement(marker)
}
});
Expand the snippet below for a demonstration, where clicking the image will add marker dots.
//helper functions
addInactiveClassToElement = (el) => el.classList.add('inactive');
removeInactiveClassToElement = (el) => el.classList.remove('inactive');
class MarkerList {
constructor() {
this.elements = [];
}
add(x, y) {
const marker = document.createElement('div');
marker.classList.add('marker');
marker.setAttribute('style', 'left: ' + x + 'px; top: ' + y + 'px;');
document.body.append(marker);
this.elements.push(marker);
}
hideAll() {
this.elements.forEach(addInactiveClassToElement);
}
showAll(delay) {
this.elements.forEach((marker, i) => {
if (delay) {
setTimeout(removeInactiveClassToElement.bind(null, marker), delay * i);
}
else {
removeInactiveClassToElement(marker)
}
});
}
}
document.addEventListener('DOMContentLoaded', function() {
var markers = new MarkerList();
this.addEventListener('click', function(clickEvent) {
if (clickEvent.target.id == 'hide') {
markers.hideAll();
} else if (clickEvent.target.id == 'show') {
markers.showAll(delay.value);
} else if (clickEvent.target.id == 'image') {
markers.add(clickEvent.clientX, clickEvent.clientY);
}
});
});
.marker {
background-color: #f00;
width: 2px;
height: 2px;
position: absolute;
}
.inactive {
display: none;
}
<img src="https://www.gravatar.com/avatar/eb4f74eab7ebf483efaa9de0371cb5f8?s=32&d=identicon&r=PG&f=1" width=80 id="image" />
<button id="hide">
Hide all
</button>
<button id="show">
Show all
</button>
<div>
Delay:
<input id="delay" type="number" value="2000" />
</div>
showAll()
is called? Would it make sense to wrap that in asetTimeout()
call? \$\endgroup\$ – Sᴀᴍ Onᴇᴌᴀ Nov 13 '17 at 20:17