Onclick для каждой кнопки добавить/удалить класс из атрибута в документ HTML

У меня есть 2 кнопки на данный момент в качестве примера. Проблема здесь в том, что когда я нажимаю кнопку A, например, он меняет класс в html-документе со значением из «data-accent-switcher», которое в данном случае является СИНИМ, но когда я снова нажимаю кнопку A, он меняется с значение с кнопки B, то же самое происходит с кнопкой b. Теперь, даже если я нажму около 20 раз на кнопку A, я всегда хочу получить это значение из атрибута данных (data-accent-switcher).

Как я могу сделать это возможным?

<button class='ipsButton accentSwitcher' data-accent-switcher = "blue">Button A</button>
<button class='ipsButton accentSwitcher' data-accent-switcher = "yellow">Button B</button>
<script type = "text/javascript">
  $(document).ready(function() {
    $('.accentSwitcher').on("click", function() {
      var accentValue = $(this).data('accent-switcher');
      if (document['documentElement']['classList']['contains']('accent-blue')) {
        document['documentElement']['classList']['remove']('accent-blue');
        document['documentElement']['classList']['add']('accent-yellow');
      } else {
        if (document['documentElement']['classList']['contains']('accent-yellow')) {
          document['documentElement']['classList']['remove']('accent-yellow');
          document['documentElement']['classList']['add']('accent-blue');
        }
      }
      ips['utils']['cookie']['set']('ipsTheme_type', accentValue, true)
    });
  });
</script>

Я пробовал с операторами if, но, очевидно, я ошибаюсь и не работает.

Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Введение в CSS
Введение в CSS
CSS является неотъемлемой частью трех основных составляющих front-end веб-разработки.
Как выровнять Div по центру?
Как выровнять Div по центру?
Чтобы выровнять элемент <div>по горизонтали и вертикали с помощью CSS, можно использовать комбинацию свойств и значений CSS. Вот несколько методов,...
Навигация по приложениям React: Исчерпывающее руководство по React Router
Навигация по приложениям React: Исчерпывающее руководство по React Router
React Router стала незаменимой библиотекой для создания одностраничных приложений с навигацией в React. В этой статье блога мы подробно рассмотрим...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Ангулярный шаблон для бронирования путешествий
Toor - Travel Booking Angular Template один из лучших Travel & Tour booking template in the world. 30+ валидированных HTML5 страниц, которые помогут...
0
0
58
2
Перейти к ответу Данный вопрос помечен как решенный

Ответы 2

Ответ принят как подходящий

Я бы предложил следующий подход с пояснительными комментариями в коде:

// a named function to handle the 'accent-switching', declared using
// Arrow function syntax, and taking one argument 'evt', a reference
// to the Event object passed automatically from the later use of
// EventTarget.addEventListener():
const accentSwitch = (evt) => {
    // we use destructuring assignment to retrieve the
    // currentTarget node (the node to which the function
    // was bound) from the Event Object:
    let {
      currentTarget
    } = evt,
    // we cache the data-accent-switcher attribute-value,
    // using the HTMLElement.dataset API:
    value = currentTarget.dataset.accentSwitcher,
    // we cache a reference to the element we wish to
    // affect (obviously, this could be changed to select
    // the appropriate ancestor element of your choice,
    // up to, and including, the <html> element):
    targetElement = currentTarget.closest('section');
    // if we have a variable called 'accentChoices', and
    // it holds a truthy value:
    if (accentChoices) {
      // we take the targetElement, and use the Element.classList
      // API to remove the list of classes from the element:
      targetElement.classList.remove(...accentChoices);
    }
    // here we again use the Element.classList API, this
    // time to add a class-name:
    currentTarget.closest('section').classList.add(value);
  },
  // using document.querySelectorAll() to retrieve a NodeList of
  // all elements that have the class of 'accentSwitcher'
  // and also have a 'data-accent-switcher' attribute:
  accentButtons = document.querySelectorAll('.accentSwitcher[data-accent-switcher]'),

  // here we convert that iterable NodeList to an Array and then
  // use Array.prototype.map() to create a new Array based upon
  // the first:
  accentChoices = Array.from(accentButtons).map(
    // using an Arrow function, we use the
    // HTMLElement.dataset API to retrieve
    // the attribute-value of the data-*
    // attribute:
    (el) => el.dataset.accentSwitcher
  );

// iterating over the NodeList of elements we found,
// using NodeList.prototype.forEach():
accentButtons.forEach(
  // using an Arrow function to bind the accentSwitch()
  // function - note the deliberate lack of parentheses -
  // as the event-handler for the 'click' event:
  (el) => el.addEventListener('click', accentSwitch)
);
:root {
  --blue: hsl(200deg 90% 70% / 1);
  --purple: hsl(300deg 90% 70% / 1);
  --yellow: hsl(60deg 90% 70% / 1);
}

*,
::before,
::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  min-block-size: 100vh;
}

main {
  block-size: 100vh;
  display: grid;
  place-content: center;
}

.wrapper {
  background-image:
    linear-gradient(
      135deg,
      #ffff,
      #fff7
    ),
    repeating-linear-gradient(
      45deg,
      transparent 0 0.75rem,
      var(--colorChoice, var(--purple)) 0.75rem 1rem
    );
  box-shadow:
    0.75rem 0.75rem 1.5rem var(--colorChoice, var(--purple)),
    -0.75rem -0.75rem 1.5rem var(--colorChoice, var(--purple));
  display: flex;
  inline-size: clamp(15rem, 40%, 800px);
  justify-content: space-between;
  outline: 3px solid var(--purple);
  padding-block: 1em;
  padding-inline: 2em;
}

section.blue {
  --colorChoice: var(--blue);
}

section.yellow {
  --colorChoice: var(--yellow);
}

button {
  padding-block: 0.5rem;
  padding-inline: 0.75rem;
}
<!-- your HTML was adjusted primarily to wrap the <button> elements,
     and show an ancestor element that could be easily targeted via
     JavaScript, while providing some aesthetic hooks for the CSS: -->
<main>
  <section class = "wrapper">
    <button class='ipsButton accentSwitcher' data-accent-switcher = "blue">Button A</button>
    <button class='ipsButton accentSwitcher' data-accent-switcher = "yellow">Button B</button>
  </section>
</main>

Демонстрация JS Fiddle.

Поскольку OP хочет продолжать использовать jQuery, я добавил параметр jQuery ниже, опять же, в коде есть пояснительные комментарии:

// creating a const variable to hold the collection of
// <button> elements:
const buttons = $('.accentSwitcher[data-accent-switcher]'),
            // creating an Array from the <button> collection:
          accentSwitches = buttons.map(function() {
        // returning the data-accent-switcher attribute-
        // value, using the data() method:
        return $(this).data('accent-switcher');
      // converting the modified collection into
      // a plain JavaScript Array with get():
      }).get();

// using on() to bind the anonymous function of the
// method as the event-handler for 'clicke' events:
buttons.on('click', function() {
    // caching the attribute-value of the
  // data-accent-switcher value:
    let accentChoice = $(this).data('accent-switcher')
  // navigating to the closest ancestor <section>
  // element:
  $(this).closest('section')
    // removing all the classes that are featured
    // in the Array of accentSwitches:
    .removeClass(accentSwitches)
    // adding the data-accent-switcher attribute-
    // value to the current element:
    .addClass(accentChoice)
    // using the css() method to update the
    // --colorChoice css custom property:
    .css('--colorChoice',
        // we're setting the above property to
      // the value held in the current <button>
      // element's own --colorChoice
      // custom property:
        $(this).css(`--colorChoice`)
    );
});
:root {
  --purple: hsl(300deg 90% 70% / 1);
}

*,
::before,
::after {
  box-sizing: border-box;
  margin: 0;
  padding: 0;
}

body {
  min-block-size: 100vh;
}

main {
  block-size: 100vh;
  display: grid;
  place-items: center;
}

.wrapper {
  background-image:
    linear-gradient(
      135deg,
        #ffff,
        #fff7
    ),
    repeating-linear-gradient(
      45deg,
        transparent 0 0.75rem,
        var(--colorChoice, var(--purple)) 0.75rem 1rem
    );
  box-shadow:
    0.75rem 0.75rem 1.5rem var(--colorChoice, var(--purple)),
    -0.75rem -0.75rem 1.5rem var(--colorChoice, var(--purple));
  display: flex;
  flex-flow: row wrap;
  gap: 0.5rem;
  inline-size: clamp(15rem, 40%, 800px);
  justify-content: space-between;
  outline: 3px solid var(--purple);
  padding-block: 1em;
  padding-inline: 2em;
}

button {
  flex-grow: 1;
  padding-block: 0.5rem;
  padding-inline: 0.75rem;
}
<!-- your HTML was adjusted primarily to wrap the <button> elements,
     and show an ancestor element that could be easily targeted via
     JavaScript, while providing some aesthetic hooks for the CSS: -->
<main>
  <section class = "wrapper">
    <button class='ipsButton accentSwitcher' data-accent-switcher = "blue" style = "--colorChoice: hsl(200deg 90% 70% / 1);">Button A</button>
    <button class='ipsButton accentSwitcher' data-accent-switcher = "yellow" style = "--colorChoice: hsl(60deg 100% 50% / 1);">Button B</button>
    <button class='ipsButton accentSwitcher' data-accent-switcher = "green" style = "--colorChoice: hsl(100deg 90% 70% / 1);">Button C</button>
    <button class='ipsButton accentSwitcher' data-accent-switcher = "pink" style = "--colorChoice: hsl(330deg 95% 70% / 1);">Button D</button>
    <button class='ipsButton accentSwitcher' data-accent-switcher = "orange" style = "--colorChoice: hsl(25deg 100% 50% / 1);">Button E</button>
    <button class='ipsButton accentSwitcher' data-accent-switcher = "red" style = "--colorChoice: hsl(355deg 90% 70% / 1);">Button F</button>
  </section>
</main>

Демонстрация JS Fiddle.

Использованная литература:

Хорошо. Спасибо. Но я хотел бы сохранить его в jQuery и в том же коде. Только одна вещь беспокоит меня прямо сейчас, @BahrulRozak дал мне довольно хорошее решение, но теперь меня беспокоит это: «Что, если у меня есть около 10 кнопок? Нужно ли мне всегда добавлять оператор else-if?»

Alexandru Miclea 18.04.2023 12:20

«Я хотел бы сохранить это в jQuery» - почему? jQuery - в большинстве случаев - не нужен, хотя, очевидно, вы можете использовать его, если хотите. Что касается «что, если у меня есть около 10 кнопок ...» - в моем ответе нет утверждений if, а связанная демонстрация показывает большее количество используемых элементов <button>, опять же: без утверждений if. Итак, нет: вам не нужно их использовать.

David Thomas 18.04.2023 12:25

Я согласен с вами. Но я привык к jQuery и мне нравится с ним работать. Это мое предпочтение, так сказать. Я не пытаюсь быть грубым или что-то в этом роде, я ценю вашу помощь и ваше время, потраченное на этот код. Если бы я мог проголосовать за это, я бы это сделал. Я вижу, что вы очень заинтересованы в помощи другим в stackoverflow. Так держать!!! Мне снова очень жаль :(

Alexandru Miclea 18.04.2023 12:31

Наверняка другие будут использовать ваш код при поиске чего-то похожего на меня.

Alexandru Miclea 18.04.2023 12:33

И, честно говоря. Не буду врать, я не так легко понимаю этот код с jQuery. В jQuery код выглядит намного чище, но в js он выглядит как беспорядок :P Вот почему я сказал: «Это мое предпочтение».

Alexandru Miclea 18.04.2023 12:46

@AlexandruMiclea: все в порядке! Я делаю это, потому что мне это нравится, а не потому, что я хочу, чтобы все уступили моему предпочтительному способу ведения дел :) Я отредактировал ответ, добавив подход jQuery. Надеюсь, это должно ответить на ваш вопрос?

David Thomas 18.04.2023 13:36

Спасибо. Я использовал ваш код. Я сделал $(this).closest(document.documentElement) это вместо ближайшего раздела. Это работает, но я надеюсь, что не ошибся, как я его использовал: D

Alexandru Miclea 19.04.2023 10:03

Не за что, рад был помочь! Что касается использования другого элемента-предка, это абсолютно нормально.

David Thomas 19.04.2023 10:13
$("html").attr("data-accent", accentChoice); Делал так. Но ваш код помог мне в 50/60% проблем. Так что большое спасибо.
Alexandru Miclea 24.04.2023 00:44

Так что спасибо @DavidThomas Я использовал его код и придумал это

<script>
  $(document).ready(function() {
    const accentButtons = $('.accentSwitcher[data-accent-switcher]'),
          accentSwitches = accentButtons.map(function() {
            return $(this).data('accent-switcher');
          }).get();
    accentButtons.on('click', function() {
      let accentChoice = $(this).data('accent-switcher')
      $(this).closest(document.documentElement)
        .removeClass(accentSwitches)
        .addClass(accentChoice)
      ips.utils.cookie.set('ipsTheme_type', accentChoice, true);
    });
  });
</script>

Я надеюсь, что это правильно. Но я не уверен в этом $(this).closest(document.documentElement)

Другие вопросы по теме