Restore original state on various elements using JavaScript

I recently asked a question about changing the height of images when clicking on them using vanilla JS. A helpful user named Butalin provided me with a working function, but there seems to be an issue - if I click on one image to change its height and then click on another image without returning to the first one, the height of the first image does not revert back to normal as expected. Is there a way to achieve this behavior?

Below is the code I am using:

var element = document.querySelectorAll('.imgclasstosize');

element.forEach(el => {
  el.addEventListener('click', function(event) {
    if (event.target.style.height == '500px') {
      event.target.style.height = '80px';
    } else {
      event.target.style.height = '500px';
    }
  });
});

And here is the HTML code for the images:

<img class="imgclasstosize" src="https://assets.picspree.com/variants/FRgeQ4d3pFXszVF7QW9VBgFQ/f4a36f6589a0e50e702740b15352bc00e4bfaf6f58bd4db850e167794d05993d">

<img class="imgclasstosize" src="https://assets.picspree.com/variants/RXCuAnyzqoapjkZQuhDFwBMs/f4a36f6589a0e50e702740b15352bc00e4bfaf6f58bd4db850e167794d05993d">

Answer №1

The concept referred to by the original poster is known as mutual exclusion. To achieve mutual exclusion, the technique called Event Delegation is utilized in the demonstration below.

Specifics are elaborated in the demonstration provided:

// Reference parent element
const gallery = document.querySelector('.gallery');
// Gather all .img elements into a NodeList
const images = document.querySelectorAll('.img');
// Set parent element as click listener
gallery.onclick = toggleHeight;

// Event handler receives Event Object
function toggleHeight(event) {
  /* .currentTarget
  This Event property determines which
  element is listening for the click event,
  such as .gallery in this case
  */
  const listener = event.currentTarget;
  /* .target
  This Event property determines which 
  element was actually clicked by the user
  within .gallery
  */
  const clicked = event.target;

  /* Event Delegation
  By utilizing Event properties and flow
  control statements like "if", we can specify
  how specific elements should behave when the
  event occurs while excluding others
  */
  /* Delegating...
  1. Verify that the clicked element is
     within .gallery...
  2. Confirm that the clicked element
     has the class: ".img"
  If the user clicks an element that does not meet
  both conditions, nothing will happen.
  */
  if (clicked !== listener) {
    if (clicked.classList.contains('img')) {
      /* Mutual Exclusion
     A behavior where only one object in a group
     can exhibit a certain effect at any given time
      */
      /*
      For each ".img", check if it was clicked
      and toggle the class ".tall" on/off accordingly
      */
      images.forEach(img => {
        if (img === clicked) {
          img.classList.toggle('tall');
        } else {
          img.classList.remove('tall');
        }
      });
    }
  }
  /* 
  Prevent the click event from reaching
  ancestor elements (i.e., stop Event
  Bubbling)
  */
  event.stopPropagation();
};
.gallery {
  width: 90vw;
  height: auto;
  margin: 8px auto;
  display: flex;
  flex-flow: row wrap;
  justify-content: space-between;
}

.img,
.small {
  max-height: 80px;
  max-width: 20vw;
  margin: 4px auto;
  display: block;
}

.img {
  cursor: pointer;
}

.tall {
  min-height: 500px;
}

figure {
  width: max-content;
  margin: auto 30vw;
}
<section class='gallery'>
  <img class="img" src="https://assets.picspree.com/variants/FRgeQ4d3pFXszVF7QW9VBgFQ/f4a36f6589a0e50e702740b15352bc00e4bfaf6f58bd4db850e167794d05993d">

  <img class="img" src="https://assets.picspree.com/variants/RXCuAnyzqoapjkZQuhDFwBMs/f4a36f6589a0e50e702740b15352bc00e4bfaf6f58bd4db850e167794d05993d">

  <img class="img" src="https://assets.picspree.com/variants/Q6FeBijP3z1pVPPu9ZrDsebE/f4a36f6589a0e50e702740b15352bc00e4bfaf6f58bd4db850e167794d05993d">

  <figure>
    <img class='small' src='https://assets.picspree.com/variants/4yZoj6m5FAQkh5vgJbrkrrMC/f4a36f6589a0e50e702740b15352bc00e4bfaf6f58bd4db850e167794d05993d'>
    <figcaption>I'll never be tall because I don't have the class ".img"</figcaption>
  </figure>
</section>

Answer №2

Achieving this is totally doable. By utilizing Array.from, you can manipulate a DOM list just like an array. To toggle CSS classes, employ classList.toggle and define your dimensions within the CSS classes:

const allImages = document.querySelectorAll('.imgclasstosize');

allImages.forEach(el => {
  el.addEventListener('click', function(event) {
  
    const thisImg = event.target;
    const allOtherImages = Array.from(allImages).filter(img => {
       return img !== thisImg;
    });
  
    allOtherImages.forEach(img => {
        img.classList.remove('big')
    });
  
    thisImg.classList.toggle('big');
  
  });
});
img.imgclasstosize {
    height: 80px;
    border: 1px solid gray;
    transition: height 1s ease;
}

img.imgclasstosize.big {
    height: 250px;
}
<img class="imgclasstosize little" src="https://assets.picspree.com/variants/FRgeQ4d3pFXszVF7QW9VBgFQ/f4a36f6589a0e50e702740b15352bc00e4bfaf6f58bd4db850e167794d05993d" />

<img class="imgclasstosize little" src="https://assets.picspree.com/variants/RXCuAnyzqoapjkZQuhDFwBMs/f4a36f6589a0e50e702740b15352bc00e4bfaf6f58bd4db850e167794d05993d" />

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Challenges encountered with Material-UI elements

Attempting to implement the http://www.material-ui.com/#/components/drawer (Docked Example) component from Material-UI in conjunction with ReactJS. An error is encountered with the "=" sign in this line: handleToggle = () => this.setState({open: !this ...

In Google Chrome, the :after element on the left is cleared, while other browsers do not

In an effort to create a button using background images in the :before and :after pseudo-selectors for cross-browser compatibility, an issue arose where only Chrome did not display it correctly (Safari results were unknown). HTML: <div class="btn-cont ...

Remove the color gradient for the column headers in the Google Visualization table

Whenever I attempt to change the colors of the column headers using the method demonstrated in this insightful source, a rather generic gradient is applied. Interestingly, the example code provided also demonstrates the same default gradient on the secon ...

Attempting to grasp the intricacies of HTML5/JS video playback quality

I've been diving deep into research on this topic, but I can't seem to find a straightforward answer to my specific query. My main focus is understanding the inner workings of how video players transition between different quality settings (480p, ...

Substitute the identifier with the name

My Current Data I currently have some data stored in json format shown below: var info = [{id: 1, name="AB", position=1}, {id: 2, name="CD", boss= 1, position=2}, {id: 3, name="EF", boss= 1, position=2}, {id: 4, name=" ...

If the given response `resp` can be parsed as JSON, then the function `$

I was using this script to check if the server's response data is in JSON format: try { json = $.parseJSON(resp); } catch (error) { json = null; } if (json) { // } else { // } However, I noticed that it returns true when 'res ...

Synchronize data bidirectionally between parent and child components in Vue 2

This special wrapper I created for the Vue-multiselect package acts as a child component within this scenario. <template> <div> <multiselect v-model="items" :options="filteredList" ...

Troubleshooting Bootstrap bug caused by rollupPluginBabelHelpers

I am currently working on a Bootstrap 4 website. I noticed that in Internet Explorer, the modal works fine when opened for the first time, but then displays an error in the console and does not open when trying to do so a second time on the same window. On ...

Securing client-side code with AngularJS for enhanced security

It's a known fact that once browsers have downloaded frontend files, there's no way to hide code from the client. However, I've heard that clients can debug JavaScript code, add breakpoints, skip code lines (especially security checks), and ...

Trouble with jQuery not loading properly in HTML

I'm experiencing an issue with a code I want to use, but it isn't responding. Even though I've verified that the code is correct because it's on jsfiddle: http://jsfiddle.net/User86745458/ztz4Lf23/ However, when I try to copy and paste ...

Upgrading to React Router v6: Implementing Loader Functions with Context API

Having issues implementing loaders in React-Router V6 while making a request for a page through a function located in the context file. Unfortunately, I can't access the context from main.js where the router is defined. Main.js import ReactDOM from & ...

Having trouble sending serialized data using jQuery Ajax in IE6

When I use the jQuery AJAX command to post data in Internet Explorer 6 and then try to print the data with print_r($_POST), PHP prints an empty array. How can I post submitted data to PHP? I'm not sure what the issue is in IE6. To alert this data ...

How can I transfer a JavaScript variable to a Django template before submitting the form?

Trying to fetch a selected approver and validate before submitting a form in Django has proven quite complex. I've made significant progress, but I'm stuck on figuring out how to "get" the translated ID in the Django template. I have the ID, but ...

What is the best way to send an inline SVG string to my controller?

I am trying to send an inline svg string along with some other properties to my controller. When I replace the svg string with a normal string like "blabla", it successfully reaches my controller. However, with the actual svg string, it never makes it to ...

Utilizing commonjs pattern to share functions among different couchdb views for increased reusability

I am seeking a way to utilize a variety of functions across different couchdb view map functions. My attempt involves using the commonjs require pattern. Within the given design doc, I am puzzled as to why the require statement in test1 successfully funct ...

Generate a unique border using jQuery randomization techniques

I've been experimenting with creating a random number and having the border-radius of my div change on every pageload: <script> $(".card-body").each(function(){ var rand = Math.floor(Math.random() * 100) + 1; $(this).css( { borderRadius: rand ...

Connecting pages through index.html within the hosting file manager directory

I have just started my coding journey and recently signed up for ipage hosting. After uploading my .html files to a directory named "Website", I encountered an issue while trying to link multiple pages to the index.html home page. I tried using the code ...

What is the best way to navigate to a specific div while scrolling on a webpage?

Can anyone help me figure out how to make my page scroll between vertical divs directly, instead of the normal scroll behavior? I've tried using the ScrollTo plugin, but it's not working as expected because the example uses buttons for scrolling. ...

Leveraging Buttons within React Material UI Tables

I am facing an issue with the logic of editing and deleting rows on a table created using Material UI. The first column of every row contains two buttons for these actions, but I am unsure of how to implement them effectively. Is there a way to achieve thi ...

How can we use Angular Table to automatically shift focus to the next row after we input a value in the last cell of the current row and press the Enter key

When the last cell of the first row is completed, the focus should move to the next row if there are no more cells in the current row. <!-- HTML file--> <tbody> <tr *ngFor="let row of rows;let i=index;" [c ...