单击其他后,javascript删除元素样式
我尝试在单击其他 span 元素(不是同一个 div)时从 span 元素中删除属性“selected”
和
如何在 div1 选择了另一个 span 时删除 div_bottom1 中 span 元素的属性“selected”?
window.addEventListener('DOMContentLoaded', () => {
const div1 = document.getElementById('div1');
div1.addEventListener('click', (e) => {
const div1span = e.target.closest('span.swatch');
if (!div1span) return;
const dj = document.getElementById('div_bottom1');
const djp = document.getElementById('div_bottom2');
const dd = document.getElementById('div_bottom3');
if (div1span.matches('.div1swatch')) {
const clodj = dj.closest('span.selected');
const clodd = dd.closest('span.selected');
clodj.removeProperty('selected');
clodd.removeProperty('selected');
}
});
<div id="attribute_pa_wersja-okleiny" class="tawcvs-swatches oss-" data-attribute_name="attribute_pa_wersja-okleiny">
<span class="swatch swatch-image swatch-dekor-jednobarwny selected" data-value="dekor-jednobarwny">
<span class="swatch__tooltip"></span>
<span class="swatches_image-container"><img src="standard.jpg" alt="dekory jednobarwne"></span>
</span>
<span class="swatch swatch-image swatch-dekor-jednobarwny-premium" data-value="dekor-jednobarwny-premium">
<span class="swatch__tooltip"></span>
<span class="swatches_image-container"><img src="premium.jpg" alt="dekory jednobarwne premium"></span>
</span><span class="swatch swatch-image swatch-dekor-drewnopodobny" data-value="dekor-drewnopodobny">
<span class="swatch__tooltip"></span>
<span class="swatches_image-container"><img src="orzech-nicea.jpg" alt="dekory drewnopodobne"></span>
</span>
</div>
<div id="attribute_pa_dekor-jednobarwny" class="tawcvs-swatches oss-" data-attribute_name="attribute_pa_dekor-jednobarwny">
<span class="swatch swatch-image swatch-bialy selected" data-value="bialy">
<span class="swatch__tooltip"></span>
<span class="swatches_image-container"><img src="bialy-150x150-2.jpg" alt="biały"></span>
</span><span class="swatch swatch-image swatch-czarny" data-value="czarny">
<span class="swatch__tooltip"></span>
<span class="swatches_image-container"><img src="AR_16_9-150x150-1.webp" alt="czarny"></span>
</span>
</div>
<div id="attribute_pa_dekor-jednobarwny-premium" class="tawcvs-swatches oss-" data-attribute_name="attribute_pa_dekor-jednobarwny-premium">
<span class="swatch swatch-image swatch-bialy-polysk" data-value="bialy-polysk">
<span class="swatch__tooltip"></span>
<span class="swatches_image-container"><img src="bialy-150x150-1.jpg" alt="biały połysk"></span>
</span>
<span class="swatch swatch-image swatch-burgundowy selected" data-value="burgundowy">
<span class="swatch__tooltip"></span>
<span class="swatches_image-container"><img src="burgundowy-150x150-1.webp" alt="burgundowy"></span>
</span>
<span class="swatch swatch-image swatch-czarny" data-value="czarny">
<span class="swatch__tooltip"></span>
<span class="swatches_image-container"><img src="czarny-polysk-150x150-1.webp" alt="czarny połysk"></span>
</span>
<span class="swatch swatch-image swatch-kaszmir-matowy" data-value="kaszmir-matowy">
<span class="swatch__tooltip"></span>
<span class="swatches_image-container"><img src="kaszmir-matowy-150x150-1.webp" alt="kaszmir matowy"></span>
</span>
</div>
<script type="text/javascript">
window.addEventListener('DOMContentLoaded',() => {
const div1 = document.getElementById('div1');
div1.addEventListener('click', (e) => {
const div1span = e.target.closest('span.swatch');
if (!div1span) return;
const dj = document.getElementById('div_bottom1');
const djp = document.getElementById('div_bottom2');
const dd = document.getElementById('div_bottom3');
if (div1span.matches('.div1swatch')) {
const clodj = dj.closest('span.selected');
const clodd = dd.closest('span.selected');
clodj.removeProperty('selected');
clodd.removeProperty('selected');
}
});
</script>
它有效直到获取
div1span.matches('.div1swatch')
然后:
"Uncaught TypeError: Cannot read properties of null" error
div 2-4 是 div1 之外的单独 div,并且具有
style.display =在切换
div1span
时设置
style.display = "none";
单击
div1span
会将
style.display = "none";
设置为
div_bottom2
和
div_bottom3
。
单击
div2span
会将
style.display = "none";
设置为
div_bottom1
和
div_bottom3
单击
div3span
会将
style.display = "none";
设置为
div_bottom1
和
div_bottom2
这有关系吗?
我做错了什么?我是 javascript 新手,目前使用 php + html 编码
无需任何 JavaScript,仅需纯 HTML/CSS 即可实现全部功能。它只需要一些标记更改和应用一些合适的 css 规则。
<label/>
/
<input type="radio"/>
关系与功能性
:has()
CSS 伪类以及
content
CSS 属性与
attr
CSS 函数一起主要完成了这个任务。
并且回退到表单控件 也可以启用键盘导航 。
.item-overview {
.row {
display: flex;
gap: .25rem;
margin-bottom: .25rem;
}
label {
position: relative;
display: inline-flex;
aspect-ratio: 1;
width: 4rem;
border: 2px solid #a4a4a4;
cursor: pointer;
&:focus-within {
border-style: dashed;
border-color: red!important;
}
&::before {
width: 100%;
height: 100%;
content: attr(data-name);
background-color: #e0feff;
align-content: center;
text-align: center;
}/*
&::after {
background-color: red;
}*/
&:has(:checked) {
border-color: #0bf;
&::after {
position: absolute;
top: 3px;
width: 100%;
content: "✓";
text-align: center;
}
}
> [type="radio"] {
position: absolute;
z-index: -1;
}
}
}
#rolex {
label {
border-color: #ccc;
&::before {
background-color: #ffccf1;
}
&:has(:checked) {
border-color: #f0b;
}
}
<div id="swatch" class="item-overview">
<div class="row">
<label data-name="Swatch 1">
<input type="radio" name="swatch" value="swatch-1" />
</label>
<label data-name="Swatch 2">
<input type="radio" name="swatch" value="swatch-2" />
</label>
<label data-name="Swatch 3">
<input type="radio" name="swatch" value="swatch-3" />
</label>
<label data-name="Swatch 4">
<input type="radio" name="swatch" value="swatch-4" />
</label>
</div>
<div class="row">
<label data-name="Swatch 5">
<input type="radio" name="swatch" value="swatch-5" />
</label>
<label data-name="Swatch 6">
<input type="radio" name="swatch" value="swatch-6" />
</label>
<label data-name="Swatch 7">
<input type="radio" name="swatch" value="swatch-7" />
</label>
<label data-name="Swatch 8">
<input type="radio" name="swatch" value="swatch-8" />
</label>
</div>
</div>
<div id="rolex" class="item-overview">
<div class="row">
<label data-name="Rolex 1">
<input type="radio" name="rolex" value="rolex-1" />
</label>
<label data-name="Rolex 2">
<input type="radio" name="rolex" value="rolex-2" />
</label>
<label data-name="Rolex 3">
<input type="radio" name="rolex" value="rolex-3" />
</label>
</div>
<div class="row">
<label data-name="Rolex 4">
<input type="radio" name="rolex" value="rolex-4" />
</label>
<label data-name="Rolex 5">
<input type="radio" name="rolex" value="rolex-5" />
</label>
<label data-name="Rolex 6">
<input type="radio" name="rolex" value="rolex-6" />
</label>
</div>
</div>
编辑 ...关于 Roko C. Buljan 的评论...
Yes, as said in comments, RADIO buttons is indeed a viable solutions - it depends only if one needs the ability to at some point deselect all the items - which in this specific case is not possible ... – Roko C. Buljan
取消选择单选按钮组中当前选中的单选按钮是一项非常简单的任务。必要的代码片段只会增强已经运行的无 JavaScript 解决方案。
方法如下。
确实结合了
event-delegation
、
WeakMap
用于查找 radio-group 的最后一个(选定的)值,以及选择 radio-control 的正确/相关 radio-group/
RadioNodeList
通过
命名项目
控件的相关
HTMLFormControlsCollection
例如使用 ...
target.form.elements[target.name]
... 顺便说一下,这相当于使用称为
“DOM Level 0”
API
的东西,尽管已经证明了自己超过 25 年,但不幸的是,这是一种很少使用的技术。
function enableOverviewItemUncheckBehavior() {
const lastRadioGroupValues = new WeakMap;
function handleUncheckControl({ target }) {
target = target.closest('[type="radio"]');
if (target) {
const nodeList = target.form.elements[target.name];
if (
lastRadioGroupValues.get(nodeList) !== nodeList.value
) {
lastRadioGroupValues.set(nodeList, nodeList.value);
} else {
target.checked = false;
}
}
}
document
.querySelectorAll('form:has(.item-overview)')
.forEach(elm => {
elm.addEventListener('click', handleUncheckControl)
});
}
enableOverviewItemUncheckBehavior();
fieldset {
margin: 0;
padding: 0;
border: none;
}
.item-overview {
.row {
display: flex;
gap: .25rem;
margin-bottom: .25rem;
}
label {
position: relative;
display: inline-flex;
aspect-ratio: 1;
width: 4rem;
border: 2px solid #a4a4a4;
cursor: pointer;
&:focus-within {
border-style: dashed;
border-color: red!important;
}
&::before {
width: 100%;
height: 100%;
content: attr(data-name);
background-color: #e0feff;
align-content: center;
text-align: center;
}/*
&::after {
background-color: red;
}*/
&:has(:checked) {
border-color: #0bf;
&::after {
position: absolute;
top: 3px;
width: 100%;
content: "✓";
text-align: center;
}
}
> [type="radio"] {
position: absolute;
z-index: -1;
}
}
}
#rolex {
label {
border-color: #ccc;
&::before {
background-color: #ffccf1;
}
&:has(:checked) {
border-color: #f0b;
}
}
<form>
<fieldset id="swatch" class="item-overview">
<div class="row">
<label data-name="Swatch 1">
<input type="radio" name="swatch" value="swatch-1" />
</label>
<label data-name="Swatch 2">
<input type="radio" name="swatch" value="swatch-2" />
</label>
<label data-name="Swatch 3">
<input type="radio" name="swatch" value="swatch-3" />
</label>
<label data-name="Swatch 4">
<input type="radio" name="swatch" value="swatch-4" />
</label>
</div>
<div class="row">
<label data-name="Swatch 5">
<input type="radio" name="swatch" value="swatch-5" />
</label>
<label data-name="Swatch 6">
<input type="radio" name="swatch" value="swatch-6" />
</label>
<label data-name="Swatch 7">
<input type="radio" name="swatch" value="swatch-7" />
</label>
<label data-name="Swatch 8">
<input type="radio" name="swatch" value="swatch-8" />
</label>
</div>
</fieldset>
<fieldset id="rolex" class="item-overview">
<div class="row">
<label data-name="Rolex 1">
<input type="radio" name="rolex" value="rolex-1" />
</label>
<label data-name="Rolex 2">
<input type="radio" name="rolex" value="rolex-2" />
</label>
<label data-name="Rolex 3">
<input type="radio" name="rolex" value="rolex-3" />
</label>
</div>
<div class="row">
<label data-name="Rolex 4">
<input type="radio" name="rolex" value="rolex-4" />
</label>
<label data-name="Rolex 5">
<input type="radio" name="rolex" value="rolex-5" />
</label>
<label data-name="Rolex 6">
<input type="radio" name="rolex" value="rolex-6" />
</label>
</div>
</fieldset>
</form>
将选定的
item
(元素) 存储在变量
let elBoxSelected;
中
为所有 (!) 框分配点击 (不仅仅是
#div1
中的框)
let elSwatchSelected;
document.querySelector("#swatches").addEventListener("click", (ev) => {
const elSwatch = ev.target.closest(".swatch");
if (!elSwatch) return; // Not a swatch box. Do nothing.
if (elSwatch !== elSwatchSelected) {
elSwatchSelected?.classList.remove("selected"); // Deselect previous (if any)
elSwatchSelected = elSwatch; // Make this one the new seelected
}
elSwatchSelected.classList.toggle("selected"); // Toggle
});
.row {
display: flex;
margin-bottom: 1rem;
gap: 1rem;
}
.swatch {
display: inline-flex;
border: 2px solid #000;
width: 3rem;
aspect-ratio: 1;
cursor: pointer;
&.selected {
border-color: #0bf;
&::after {
margin: auto;
content: "✓";
}
}
}
<div id="swatches">
<div class="row">
<div class="swatch"></div>
<div class="swatch"></div>
<div class="swatch"></div>
</div>
<div class="row">
<div class="swatch"></div>
<div class="swatch"></div>
<div class="swatch"></div>
<div class="swatch"></div>
</div>
</div>
<script>
document.getElementById("swatches")
.addEventListener("click",function(ev) {
var element = ev.target.closest(".swatch");
var selectedSwatches = document.querySelectorAll(".selected");
selectedSwatches.forEach(function (swatch) {
swatch.classList.remove("selected");
});
if (element) {
element.classList.toggle("selected");
}
});
</script>
<!-- language: lang-css -->
<style>
.row {
display: flex;
margin-bottom: 1rem;
gap: 1rem;
}
.swatch {
display: inline-flex;
width: 3rem;
background:red;
aspect-ratio: 1;
cursor: pointer;
&.selected {
border-color: #0bf;
&::after {
margin: auto;
content: "✓";
}
}
}
</style>
<!-- language: lang-html -->
<!DOCTYPE html>
<html>
<body>
<h2>JavaScript addEventListener()</h2>
<p>This example uses the addEventListener() method to attach a click event to a button.</p>
<button id="myBtn">Try it</button>
<div id="swatches">
<div class="row">
<div class="swatch"></div>
<div class="swatch"></div>
<div class="swatch"></div>
</div>
<div class="row">
<div class="swatch"></div>
<div class="swatch"></div>
<div class="swatch"></div>
<div class="swatch"></div>
</div>
</div>
</body>
</html>