0

I'm changing document language from Arabic to English by setting the dir attribute to rtl, with that happening I'm hiding the parent div date-and-language and adding it to another place in the document using insertAdjacentHTML, the problem with this is that the event listener doesn't work on its child .language anymore ( after insertion with same classes names ), why doesn't it ?

const language = document.querySelector(".language");
const languageOptions = document.querySelector(".language-options");
const mainHeaderOptions = document.querySelector(".main-header-options");
const dateAndLanguage = document.querySelector(".date-and-language");


const changeLanguage = (e) => {
  languageOptions.classList.toggle("hide");
};

language.addEventListener("click", (e) => changeLanguage(e));

const toEnglish = () => {

  document.documentElement.setAttribute("dir", "ltr");
  dateAndLanguage.style.display = "none";

  const html = `
    <div class="language">
      <i class="fa-solid fa-earth-europe icon"></i>
      Language
      <i class="fa-solid fa-angle-down icon"></i>
      <div class="language-options hide">
        <p class="arabic">عربي</p>
        <p class="english">English</p>
      </div>
    </div>
  `;
  mainHeaderOptions.insertAdjacentHTML("beforeend", html);
};

english.addEventListener("click", () => toEnglish());

I tried to attach the listener on document like this :

const changeLanguage = (e) => {
  if(e.target.classList.contains("language"){
    languageOptions.classList.toggle("hide"); // doesn't work
}

};

document.addEventListener("click", (e) => changeLanguage(e));
  • 2
    Your attempt at event delegation is very close! Just use `if(e.target.closest(".language"))` instead; the `target` might be some element _inside_ your `class="language"` element. See [`closest`](//developer.mozilla.org/en/docs/Web/API/Element/closest). – Sebastian Simon Nov 07 '22 at 02:46
  • both approaches don't work, i think both ways are event delegation, ```.closest``` and ```.contains``` do the same job isn't it – aasem shoshari Nov 07 '22 at 02:53
  • No, not really. Don’t confuse [`e.target.classList.contains`](//developer.mozilla.org/en/docs/Web/API/DOMTokenList/contains) with [`e.target.contains`](//developer.mozilla.org/en/docs/Web/API/Node/contains)! If the `.closest` approach doesn’t work, there’s something else going wrong in the code… – Sebastian Simon Nov 07 '22 at 02:55
  • Are you sure `languageOptions` is the correct element to toggle the `hide` class of? You have multiple elements matching `".language-options"`. Did you mean `e.target.closest(".language").querySelector(".language-options").classList.toggle("hide");`? – Sebastian Simon Nov 07 '22 at 02:59
  • yeah, it worked fine before i set ```display:none:``` on the element and add the ```div``` again in another place, the html variable is literally copy paste the element, just inserting it to different place – aasem shoshari Nov 07 '22 at 03:04
  • i used ```if (e.target.closest(".language"))```, but still doesn't work on inserted element – aasem shoshari Nov 07 '22 at 03:04
  • maybe because ```display:none``` doesn't remove element from the dom, therefore i really do have multiple elements matching ```.language-options``` therefore the listener only works on the first one – aasem shoshari Nov 07 '22 at 03:06
  • Yes, of course, `display: none;` doesn’t remove anything from the DOM, it just prevents the element from rendering. – Sebastian Simon Nov 07 '22 at 03:08

0 Answers0