开发者问题收集

单击其他后,javascript删除元素样式

2024-04-25
122

我尝试在单击其他 span 元素(不是同一个 div)时从 span 元素中删除属性“selected” div1 span swatch clickedanother div1 span swatch clicked

如何在 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_bottom2div_bottom3

单击 div2span 会将 style.display = "none"; 设置为 div_bottom1div_bottom3

单击 div3span 会将 style.display = "none"; 设置为 div_bottom1div_bottom2

这有关系吗?

我做错了什么?我是 javascript 新手,目前使用 php + html 编码

html javascript

3个回答

无需任何 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>
Peter Seliger
2024-04-25

将选定的 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>
Roko C. Buljan
2024-04-25
<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>
Syed Bilal Haider
2024-04-25