wrgt
wrgt

Reputation: 167

Find not event.target using querySelectorAll() :not()

I have a group of elements that have 'click' event listeners attached.

When triggered, I want to find which elements are not the target of the event.

I've been using querySelectorAll() with :not(), but this selects all of the elements including the target:

https://codepen.io/wrgt1/pen/rNMqbpm?editors=1010

const thumbnail = document.querySelectorAll(".thumbnail");

thumbnail.forEach(function(thumb) {
  thumb.addEventListener("click", (e) => {
    const target = "." + e.target.classList[1];
    const notTarget = document.querySelectorAll(".thumbnail:not(target)");
    console.log(target);
    console.log(notTarget);
  });
});
#thumbnails {
  position: relative;
  display: flex;
}

.thumbnail {
  height: 100px;
  width: 100px;
  margin: 10px;
  background: #FF7400;
  cursor: pointer;
}
<div id="thumbnails">
  <div class="thumbnail project1">Project 1</div>
  <div class="thumbnail project2">Project 2</div>
  <div class="thumbnail project3">Project 3</div>
</div>

Upvotes: 1

Views: 2418

Answers (3)

mplungjan
mplungjan

Reputation: 178285

If you delegate you can do this

const container = document.getElementById("thumbnails");
container.addEventListener("click", function(e) {
  const tgt = e.target.closest("div"); // handle clicks inside the divs too
  if (tgt.classList.contains("thumbnail")) {
    console.log(tgt.textContent, "clicked");
    const thumbs = [...container.querySelectorAll(".thumbnail")]; // here in case thumbs are added
    const others = thumbs.filter(thumb => thumb !== tgt); // this is what you wanted
    const texts = others.map(thumb => thumb.textContent);
    console.log(texts, "not clicked");
  }
});
#thumbnails {
  position: relative;
  display: flex;
}

.thumbnail {
  height: 100px;
  width: 100px;
  margin: 10px;
  background: #FF7400;
  cursor: pointer;
}
<div id="thumbnails">
  <div class="thumbnail project1">Project 1</div>
  <div class="thumbnail project2">Project 2</div>
  <div class="thumbnail project3">Project 3</div>
</div>

Upvotes: 1

Paul Ghiran
Paul Ghiran

Reputation: 1233

What you want to do here is select all the other elements that match your criteria, then run through them and exclude the event.target, i.e. the current element.

const allSiblings= allThumbnailsArray.filter( element => element != target);

Made a codepen for you here:

https://codepen.io/pghiran/pen/mdrzYYO?editors=1010

You shouldn't use a new query with a "not" selector because that's not reliable as classes are not made for identifying elements, but classifying or grouping them(i.e. if you have 2 sections with thumbnails, you'll exclude thumbnail project4 from both of them) if you're working with classes, and it's also more costly(slow) than processing an array.

Upvotes: 1

Jamiec
Jamiec

Reputation: 136134

target is a variable and needs to be concatenated into the selector:

const thumbnail = document.querySelectorAll(".thumbnail");

thumbnail.forEach(function(thumb) {
  thumb.addEventListener("click", (e) => {
    const target = "." + e.target.classList[1];
    const notTarget = document.querySelectorAll(".thumbnail:not(" + target + ")");
    console.log(target);
    console.log(notTarget);
  });
});
#thumbnails {
  position: relative;
  display: flex;
}

.thumbnail {
  height: 100px;
  width: 100px;
  margin: 10px;
  background: #FF7400;
  cursor: pointer;
}
<div id="thumbnails">
  <div class="thumbnail project1">Project 1</div>
  <div class="thumbnail project2">Project 2</div>
  <div class="thumbnail project3">Project 3</div>
</div>

Upvotes: 2

Related Questions