У меня есть 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, но, очевидно, я ошибаюсь и не работает.






Я бы предложил следующий подход с пояснительными комментариями в коде:
// 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>Поскольку 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>Использованная литература:
«Я хотел бы сохранить это в jQuery» - почему? jQuery - в большинстве случаев - не нужен, хотя, очевидно, вы можете использовать его, если хотите. Что касается «что, если у меня есть около 10 кнопок ...» - в моем ответе нет утверждений if, а связанная демонстрация показывает большее количество используемых элементов <button>, опять же: без утверждений if. Итак, нет: вам не нужно их использовать.
Я согласен с вами. Но я привык к jQuery и мне нравится с ним работать. Это мое предпочтение, так сказать. Я не пытаюсь быть грубым или что-то в этом роде, я ценю вашу помощь и ваше время, потраченное на этот код. Если бы я мог проголосовать за это, я бы это сделал. Я вижу, что вы очень заинтересованы в помощи другим в stackoverflow. Так держать!!! Мне снова очень жаль :(
Наверняка другие будут использовать ваш код при поиске чего-то похожего на меня.
И, честно говоря. Не буду врать, я не так легко понимаю этот код с jQuery. В jQuery код выглядит намного чище, но в js он выглядит как беспорядок :P Вот почему я сказал: «Это мое предпочтение».
@AlexandruMiclea: все в порядке! Я делаю это, потому что мне это нравится, а не потому, что я хочу, чтобы все уступили моему предпочтительному способу ведения дел :) Я отредактировал ответ, добавив подход jQuery. Надеюсь, это должно ответить на ваш вопрос?
Спасибо. Я использовал ваш код. Я сделал $(this).closest(document.documentElement) это вместо ближайшего раздела. Это работает, но я надеюсь, что не ошибся, как я его использовал: D
Не за что, рад был помочь! Что касается использования другого элемента-предка, это абсолютно нормально.
$("html").attr("data-accent", accentChoice); Делал так. Но ваш код помог мне в 50/60% проблем. Так что большое спасибо.
Так что спасибо @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)
Хорошо. Спасибо. Но я хотел бы сохранить его в jQuery и в том же коде. Только одна вещь беспокоит меня прямо сейчас, @BahrulRozak дал мне довольно хорошее решение, но теперь меня беспокоит это: «Что, если у меня есть около 10 кнопок? Нужно ли мне всегда добавлять оператор else-if?»