Skip to content
Advertisement

How to change the contents of one container by hovering over elements/links in a DIFFERENT container

I’m currently developing an e-catalogue. Following the suggestion of a Stackoverflow contributor, I now have a navigation bar with a dropdown that produces a two-container menu. Next, I am trying to set it in such a way that when one hovers over a specific element in one container (the left container), the contents of the other container (the right one) of the dropdown, change and allows the user, interact with the changed contents of the right container.

I am using ‘mouseenter’ and ‘mouseleave’ event handlers, and yes, you’ve guessed it, the moment I leave the element (in the left container) I hovered over to trigger the change (in the right container), the contents of the right container reverse back to their original contents!

To get ’round’ this problem, within the mouseenter eventlistener function, I wrote in a second mouseenter eventlistener function, this time for the right container itself. I hoped that if I left the element (in the left container), that triggered the change in the right container, and went into the right container, I would be able to interact with the altered contents of the right container. Alas, it worked it!

The problem now, however, is that ANYTIME I hover over the right container, the contents change as if I had hovered over the specific element in the left container, regardless of whether or not I had actually hovered over that element in the left container.

I have tried numerous approaches, including, ‘mouseout’ (which ‘bubbles’), and also tried giving the two mouseenter event functions, names, so that the ‘inner’ function for the mouseenter event of the right container only executes when the ‘outer’ function for the mouseenter event of the element in the left container has executed (a very Pythonistic way of thinking!), but nothing has worked.

I need to keep a mouseout or mouseleave event of some sort for the element in the left container; otherwise, the change in the right container will persist as you move the mouse on to other elements in the left container.

Ultimately, I want each element in the left container to trigger different changes in the contents of the right container, much like what you see in the dropdown here.

A minimal working version of my code is shown below:

// block-1h selectors
const breakingLine = document.querySelector(".breakingline");
const breaking = document.querySelector(".breaking");

// block-2h selector(s)
const block2H = document.querySelector(".block-2h");
const drop2HCaptionText = document.querySelector(".drop-2h-captiontext");

// Event listeners

breakingLine.addEventListener("mouseenter", function() {
  drop2HCaptionText.textContent = "Camon C2000 Rotavator";
  block2H.addEventListener("mouseenter", function() {
    drop2HCaptionText.textContent = "Camon C2000 Rotavator";
  })
})

breaking.addEventListener("mouseleave", function() {
  drop2HCaptionText.textContent = "Boss Ladderspan 3T Scaffold Tower (Single Width)";
  block2H.addEventListener("mouseleave", function() {
    drop2HCaptionText.textContent = "Boss Ladderspan 3T Scaffold Tower (Single Width)";
  })
})
.nav-list {
  list-style: none;
  border: 1px solid blue;
  display: flex;
  flex-flow: row wrap;
  align-items: left;
  justify-content: left;
  color: white;
  background-color: #429CD9;
}

#hire-dropdown {
  position: absolute;
  cursor: pointer;
  padding-right: 3em;
  padding-left: 3em;
}

.hdrop,
.block-1h,
.block-2h {
  display: none;
}

#hire-dropdown:hover * {
  display: grid;
}

#hire-dropdown .hdrop {
  grid-template-areas: "block-1h block-2h";
  grid-template-columns: 1fr 1fr;
}

.block-1h {
  grid-area: "block-1h";
  height: 30em;
}

.block-2h {
  grid-area: "block-2h";
  background-color: white;
  border: 1px solid black;
  height: 40em;
}

.drop-1h-list {
  list-style: none;
  display: block;
  border: 1px solid black;
  background-color: white;
  height: 40em;
}

.drop-most-popular-hire,
.drop-2h-captiontext {
  color: #3D3F41;
}

.drop-most-popular-hire {
  padding-left: 3em;
}
<nav>
  <ul class="nav-list">
    <li>Nothing</li>
    <li class="to-hire">
      <div id="hire-dropdown">To Hire
        <div class="hdrop">
          <div class="block-1h">
            <ul class="drop-1h-list">
              <li><a href="#">Access</a></li>
              <li class="breakingline"><a class="breaking" href="#">Breaking</a></li>
              <li class="compactionline"><a class="compaction" href="#">Compaction</a></li>
            </ul>
          </div>
          <div class="block-2h">
            <h3 class="drop-most-popular-hire">Our most popular product in this category</h3>
            <p class="drop-2h-captiontext">Boss Ladderspan 3T Scaffold Tower (Single Width)</p>
          </div>
        </div>
      </div>
    </li>
  </ul>
</nav>

Your (constructive) help will be most appreciated.

Advertisement

Answer

You could just remove the mouseleave event listener.

When you enter a li element in the left container, the mouseenter event listener will be fired and the text in the right container will be changed.

The content will be changed to another text only when you enter another element in the left container.

const drop2HCaptionText = document.querySelector(".drop-2h-captiontext");

let texts = [
  "Boss Ladderspan 3T Scaffold Tower (Single Width)",
  "Camon C2000 Rotavator",
  "Boss Ladderspan 3T Scaffold Tower (Single Width)",
]

let listItems = document.querySelectorAll('.drop-1h-list li');
listItems.forEach((item, index) => {
  item.addEventListener('mouseenter', () => {
    drop2HCaptionText.textContent = texts[index];
  })
})
.nav-list {
  list-style: none;
  border: 1px solid blue;
  display: flex;
  flex-flow: row wrap;
  align-items: left;
  justify-content: left;
  color: white;
  background-color: #429CD9;
}

#hire-dropdown {
  position: absolute;
  cursor: pointer;
  padding-right: 3em;
  padding-left: 3em;
}

.hdrop,
.block-1h,
.block-2h {
  display: none;
}

#hire-dropdown:hover * {
  display: grid;
}

#hire-dropdown .hdrop {
  grid-template-areas: "block-1h block-2h";
  grid-template-columns: 1fr 1fr;
}

.block-1h {
  grid-area: "block-1h";
  height: 30em;
}

.block-2h {
  grid-area: "block-2h";
  background-color: white;
  border: 1px solid black;
  height: 40em;
}

.drop-1h-list {
  list-style: none;
  display: block;
  border: 1px solid black;
  background-color: white;
  height: 40em;
}

.drop-most-popular-hire,
.drop-2h-captiontext {
  color: #3D3F41;
}

.drop-most-popular-hire {
  padding-left: 3em;
}
<nav>
  <ul class="nav-list">
    <li>Nothing</li>
    <li class="to-hire">
      <div id="hire-dropdown">To Hire
        <div class="hdrop">
          <div class="block-1h">
            <ul class="drop-1h-list">
              <li><a href="#">Access</a></li>
              <li class="breakingline"><a class="breaking" href="#">Breaking</a></li>
              <li class="compactionline"><a class="compaction" href="#">Compaction</a></li>
            </ul>
          </div>
          <div class="block-2h">
            <h3 class="drop-most-popular-hire">Our most popular product in this category</h3>
            <p class="drop-2h-captiontext">Boss Ladderspan 3T Scaffold Tower (Single Width)</p>
          </div>
        </div>
      </div>
    </li>
  </ul>
</nav>
User contributions licensed under: CC BY-SA
3 People found this is helpful
Advertisement