Проблема с изменением текста в span элементе при использовании JavaScript

У меня возникла проблема при использовании JavaScript для изменения текста в элементе <span>. У меня есть несколько блоков <a>, в каждом из которых содержится span с уникальным id. Когда я пытаюсь изменить текст на странице, он меняется везде кроме содержимого блоков <span>.

Дополнительно при смене текста появляются ошибки в консоли:

Uncaught TypeError: Cannot set properties of null (setting 'textContent')
    at changeLanguage (main.js:25:38)
    at HTMLButtonElement.onclick (index.html:21:52)

const changeLanguage = function(language) {
  const greetingElement = document.getElementById('main-menu__greeting');
  const aboutMeElement = document.getElementById('about-me');
  const contactElement = document.getElementById('contact');
  const mySpecialtyElement = document.getElementById('my-specialty');
  const aboutMeSFElement = document.getElementById('about-me__small-font');
  const contactSFElement = document.getElementById('contact__small-font');
  const mySpecialtySFElement = document.getElementById('my-specialty__small-font');

  if (language === 'en') {
    greetingElement.textContent = 'Hello, world!';
    aboutMeElement.textContent = 'About me';
    contactElement.textContent = 'Contact';
    mySpecialtyElement.textContent = 'My specialty';
    aboutMeSFElement.textContent = 'A little about myself';
    contactSFElement.textContent = 'How to contact me';
    mySpecialtySFElement.textContent = 'What I do';
  } else if (language === 'ru') {
    greetingElement.textContent = 'Привет, мир!';
    aboutMeElement.textContent = 'О себе';
    contactElement.textContent = 'Контакты';
    mySpecialtyElement.textContent = 'Моя специальность';
    aboutMeSFElement.textContent = 'Немного о себе';
    contactSFElement.textContent = 'Как со мной связаться';
    mySpecialtySFElement.textContent = 'Чем я занимаюсь';
  }
}
<body>
  <header>
    <div id="language-buttons" class="language-buttons">
      <button onclick="changeLanguage('en')">eng</button>
      <button onclick="changeLanguage('ru')">ru</button>
    </div>
  </header>
  <div class="main-menu">
    <h1 id="main-menu__greeting">Hello, world!</h1>
    <div class="main-menu__navigation-buttons">
      <nav>
        <ul>
          <li><a id="about-me" href="#about-me">About me <span id="about-me__small-font" class="navigation-buttons__small-font">A little about myself</span></a></li>
          <li><a id="contact" href="#contact">Contact <span id="contact__small-font" class="navigation-buttons__small-font">How to contact me</span></a></li>
          <li><a id="my-specialty" href="#my-specialty">My specialty <span id="my-specialty__small-font" class="navigation-buttons__small-font">What I do</span></a></li>
        </ul>
      </nav>
    </div>
  </div>
</body>

Изначальная цель: дать дополнительное описание блокам <a>, и что бы этот дополнительный текст имел другой класс с другими стилями.


Ответы (2 шт):

Автор решения: ksa

У меня возникла проблема при использовании JavaScript для изменения текста в элементе .

Предложу тебе вот такой вариант решения...

const ot = {
  'about-me': {
    en: ['About me', 'A little about myself'], 
    ru: ['Привет, мир!', 'О себе']
  },
  contact: {
    en: ['Contact', 'How to contact me'], 
    ru: ['Контакты', 'Как со мной связаться']
  },
  'my-specialty': {
    en: ['My specialty', 'What I do'], 
    ru: ['Моя специальность', 'Чем я занимаюсь']
  },
}
document.querySelector('#language-buttons').addEventListener('click', e => {
  const lng = e.target.dataset.lng
  if (!lng) return
  document.querySelectorAll('nav a').forEach(o => {
    const t = o.dataset.txt
    o.querySelectorAll('span').forEach((o, i) => {
      o.textContent = ot[t][lng][i]
    })
  })
})
<body>
  <header>
    <div id="language-buttons" class="language-buttons">
      <button data-lng='en'>eng</button>
      <button data-lng='ru'>ru</button>
    </div>
  </header>
  <div class="main-menu">
    <h1 id="main-menu__greeting">Hello, world!</h1>
    <div class="main-menu__navigation-buttons">
      <nav>
        <ul>
          <li>
            <a data-txt="about-me" href="#about-me">
              <span>About me</span>
              <span id="about-me__small-font" class="navigation-buttons__small-font">A little about myself
              </span>
            </a>
          </li>
          <li>
            <a data-txt="contact" href="#contact">
              <span>Contact</span>
              <span id="contact__small-font" class="navigation-buttons__small-font">How to contact me
              </span>
            </a>
          </li>
          <li>
            <a data-txt="my-specialty" href="#my-specialty">
              <span>My specialty</span>
              <span id="my-specialty__small-font" class="navigation-buttons__small-font">What I do
              </span>
            </a>
          </li>
        </ul>
      </nav>
    </div>
  </div>
</body>

→ Ссылка
Автор решения: Grundy

После того как ты изменил textContent в элементе - весь html который в не был пропадает.

Поэтому на следующем вызове при попытке получить span элемент ты получишь null и ошибку, когда попытаешься установить значение у null.

для решения нужно либо добавить второй span для оставшегося текста, либо получать текстовый элемент и менять именно его, либо добавить потерянный span заново. Добавить элемент в конец можно с помощью метода .appendChild

const changeLanguage = function(language) {
  const greetingElement = document.getElementById('main-menu__greeting');
  const aboutMeElement = document.getElementById('about-me');
  const contactElement = document.getElementById('contact');
  const mySpecialtyElement = document.getElementById('my-specialty');
  const aboutMeSFElement = document.getElementById('about-me__small-font');
  const contactSFElement = document.getElementById('contact__small-font');
  const mySpecialtySFElement = document.getElementById('my-specialty__small-font');

  if (language === 'en') {
    greetingElement.textContent = 'Hello, world!';
    aboutMeElement.textContent = 'About me';
    contactElement.textContent = 'Contact';
    mySpecialtyElement.textContent = 'My specialty';
    aboutMeSFElement.textContent = 'A little about myself';
    contactSFElement.textContent = 'How to contact me';
    mySpecialtySFElement.textContent = 'What I do';
  } else if (language === 'ru') {
    greetingElement.textContent = 'Привет, мир!';
    aboutMeElement.textContent = 'О себе';
    contactElement.textContent = 'Контакты';
    mySpecialtyElement.textContent = 'Моя специальность';
    aboutMeSFElement.textContent = 'Немного о себе';
    contactSFElement.textContent = 'Как со мной связаться';
    mySpecialtySFElement.textContent = 'Чем я занимаюсь';
  }

  // возвращаем span назад
  aboutMeElement.appendChild(aboutMeSFElement);
  contactElement.appendChild(contactSFElement);
  mySpecialtyElement.appendChild(mySpecialtySFElement);
}
<body>
  <header>
    <div id="language-buttons" class="language-buttons">
      <button onclick="changeLanguage('en')">eng</button>
      <button onclick="changeLanguage('ru')">ru</button>
    </div>
  </header>
  <div class="main-menu">
    <h1 id="main-menu__greeting">Hello, world!</h1>
    <div class="main-menu__navigation-buttons">
      <nav>
        <ul>
          <li><a id="about-me" href="#about-me">About me <span id="about-me__small-font" class="navigation-buttons__small-font">A little about myself</span></a></li>
          <li><a id="contact" href="#contact">Contact <span id="contact__small-font" class="navigation-buttons__small-font">How to contact me</span></a></li>
          <li><a id="my-specialty" href="#my-specialty">My specialty <span id="my-specialty__small-font" class="navigation-buttons__small-font">What I do</span></a></li>
        </ul>
      </nav>
    </div>
  </div>
</body>

→ Ссылка