https://prnt.sc/21vc411 As you can see on the link when i click one letter in left side or in right side, that letter should disappear and should go to the opposite side. For example, when i click "A" letter on the left it goes to right. I created one letter on each side, and as default the right one's display is 'none'. So when i click the one on the left the following function starts;
function myFunction() {
document.getElementById("aLetterLeftSide").style.display="none";
document.getElementById("aLetterRigtSide").style.display="inline-block";
}
It works but i have to do it for every letter with different id's. So there is approximately 50 functions :( Is there a way to shorten it to less functions ? Thank you for your answers :)
CodePudding user response:
You are binding your functions to your elements using Element id
s (MDN Webdocs Link). When you have a bunch of elements that need the same function, just bind them use Element ClassName
(MDN Webdocs Link) instead.
In the following example, I simple have letters with class
defined as letter-span
, and then I set the onclick
(MDN Webdocs Link) property iteratively...
var letterspans = document.getElementsByClassName("letter-span");
var onclickfunc = function(e) {
if(this.style.float) {
this.style.float = '';
} else {
this.style.float = 'right';
}
};
for(i = 0; i < letterspans.length; i ) {
letterspans[i].onclick = onclickfunc;
}
<span data-letter="a" class="letter-span">A</span> |
<span data-letter="b" class="letter-span">B</span> |
<span data-letter="c" class="letter-span">C</span> |
<span data-letter="d" class="letter-span">D</span>
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>
Note
The above is a full, working, stand-alone demo (please note: Minimal Reproducible Code). In this case, I did if(this.style.float){
and this.style.float = ''
; you may need a different condition and setter, perhaps, if(this.classList.contains('rightside')) {..
, and this.classList.add('rightside')
along with this.classList.remove('rightside')
. I didn't do it this way, because, I wanted something fully reprocudible in a demo.
CodePudding user response:
Event delegation allows you to use a single event listener for an unlimited number of elements.
Add the event listener on a parent element that contains all of the elements you want to click:
document.querySelector(Parent).onclick = clickHandler;
In the clickHandler(event)
use event.target
to get the clicked element:
const clicked = event.target
Check to see if it's the correct element:
if (clicked.matches('.node')) {...
Get in the habit of using class
instead of #id
The example below allows you to move items from and to both containers.
const moveNode = event => {
const clicked = event.target;
const from = clicked.parentElement;
const toB = document.querySelector('.B');
const toA = document.querySelector('.A');
if (clicked.matches('.node')) {
const node = from.removeChild(clicked);
if (from.matches('.A')) {
toB.appendChild(node);
} else {
toA.appendChild(node);
}
} else {
return false;
}
}
const main = document.querySelector('main');
main.onclick = moveNode;
main {
display: flex;
justify-content: space-around;
}
section {
display: flex;
justify-content: space-between;
align-items: center;
width: 45vw;
min-height: 20vh;
border: 1px solid black;
}
.node {
font-size: 3ch;
border: 1px solid black;
width: 3ch;
height: 2ch;
text-align: center;
cursor: pointer;
}
<main>
<section class='A'>
<div class='node'>A</div>
<div class='node'>B</div>
<div class='node'>C</div>
<div class='node'>D</div>
<div class='node'>E</div>
<div class='node'>F</div>
<div class='node'>G</div>
</section>
<section class='B'></section>
</main>
<iframe name="sif2" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>