Utilizing a repetitive element as a fresh offspring in the replaceChild() function

const addToCartButtons = document.getElementsByClassName('add-to-cart');
const addToCartButtonsArray = Array.from(addToCartButtons);

const increment = document.createElement('img');
increment.setAttribute('src', '/assets/images/icon-increment-quantity.svg');
increment.style.zIndex = '0';
increment.style.width = '15px';
increment.style.marginBottom = '0.5px';
increment.style.marginRight = '6px';
increment.style.border = 'none';
increment.style.cursor = 'pointer';

const decrement = document.createElement('img');
decrement.setAttribute('src', '/assets/images/icon-decrement-quantity.svg');
decrement.style.zIndex = '1';
decrement.style.width = '15px';
decrement.style.marginBottom = '0.5px';
decrement.style.marginLeft = '6px';
decrement.style.border = 'none';
decrement.style.cursor = 'pointer';

const quantity = document.createElement('span');
quantity.textContent = 0;

const addToCartButtonOnHover = document.createElement('div'); // new element when hovering
addToCartButtonOnHover.classList.add('add-to-cart-on-hover');

addToCartButtonsArray.forEach((button, index) => {

  button.addEventListener('mouseover', (e) => {

    const element = e.target.parentElement;

    element.replaceChild(addToCartButtonOnHover, element.children[0]); // replaces old add-to-cart button with the hover one

    addToCartButtonOnHover.append(decrement, quantity, increment);

    let count = 0;

    increment.onclick = function() {
      count += 1;
      quantity.textContent = count;
    }
    // adding and deducting products
    decrement.onclick = function() {
      count -= 1;
      if (count < 0) {
        count = 0;
      }
      quantity.textContent = count;
    }
  });
   addToCartButtonOnHover.addEventListener('mouseleave', (e) => {
      const element = e.target.parentElement;
      element.replaceChild(addToCartButtonsArray[index], element.children[0]); // returns the old add-to-cart button
});
});
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Red Hat Text';
}

body {
  display: flex;
  height: 100vh;
  justify-content: space-evenly;
}

.products {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-evenly;
  align-items: center;
}

.product {
  flex-direction: column;
  align-items: center;
  width: 30%;
  height: 43vh;
  margin-left: 0;
  margin-bottom: 5%;
  margin: 50px;
}

.add-to-cart {
  border: 1px solid hsl(14, 65%, 9%);
  border-radius: 20px;
  margin-left: 16%;
  text-align: center;
  width: 10vw;
  height: 5vh;
  line-height: 4.5vh;
  background-color: white;
}

.add-to-cart-on-hover {
  border: 1px solid hsl(14, 65%, 9%);
  border-radius: 20px;
  text-align: center;
  margin-left: 16%;
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 10vw;
  height: 5vh;
  background-color: orange;
}
  <div class="products">
    <div class="product">
      <div class="add-to-cart">Add to cart</div>
    </div>
    <div class="product">
      <div class="add-to-cart">Add to cart</div>
    </div>
  </div>

Can we utilize an iterated element as a new child in the replaceChild() function? The current code works only on the first button because it's accessed using 'array[0' in the second event listener. I aim for both buttons to behave similarly, but adjusting the index causes one to disappear. Looping through the addToCartButtonsArray inside the event listener was attempted without success. How can both buttons work identically?

Answer №1

When using forEach, the index can be accessed as the second parameter of the callback function. Here's an example:

let array = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'];

array.forEach((item, index) => {
    console.log(`${index}: ${item}`);
});

You simply need to define your function like this:

addToCartButtonsArray.forEach((button, index) => {
    //your code here
});

After that, you can use [index] instead of [0]

const addToCartButtons = document.getElementsByClassName('add-to-cart');
const addToCartButtonsArray = Array.from(addToCartButtons);

// Code for creating elements dynamically
const increment = document.createElement('img');
increment.setAttribute('src', '/assets/images/icon-increment-quantity.svg');
increment.style.zIndex = '0';
increment.style.width = '15px';
increment.style.marginBottom = '0.5px';
increment.style.marginRight = '6px';
increment.style.border = 'none';
increment.style.cursor = 'pointer';

const decrement = document.createElement('img');
decrement.setAttribute('src', '/assets/images/icon-decrement-quantity.svg');
decrement.style.zIndex = '1';
decrement.style.width = '15px';
decrement.style.marginBottom = '0.5px';
decrement.style.marginLeft = '6px';
decrement.style.border = 'none';
decrement.style.cursor = 'pointer';

const quantity = document.createElement('span');
quantity.textContent = 0;

// Event listeners and functionality for each add-to-cart button
addToCartButtonsArray.forEach((button, index) => {

// Creating new element for hover effect
const addToCartButtonOnHover = document.createElement('div');
addToCartButtonOnHover.classList.add('add-to-cart-on-hover');
  button.addEventListener('mouseover', (e) => {

    const element = e.target.parentElement;

    element.replaceChild(addToCartButtonOnHover, element.children[0]);

    addToCartButtonOnHover.append(decrement, quantity, increment);

    let count = 0;

    increment.onclick = function() {
      count += 1;
      quantity.textContent = count;
    }

    // Functionality for adding and deducting products
    decrement.onclick = function() {
      count -= 1;
      if (count < 0) {
        count = 0;
      }
      quantity.textContent = count;
    }
  });

   addToCartButtonOnHover.addEventListener('mouseleave', (e) => {
      const element = e.target.parentElement;
      element.replaceChild(addToCartButtonsArray[index], element.children[0]);
});
});
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
  font-family: 'Red Hat Text';
}

body {
  display: flex;
  height: 100vh;
  justify-content: space-evenly;
}

.products {
  display: flex;
  flex-wrap: wrap;
  justify-content: space-evenly;
  align-items: center;
}

.product {
  flex-direction: column;
  align-items: center;
  width: 30%;
  height: 43vh;
  margin-left: 0;
  margin-bottom: 5%;
  margin: 50px;
}

.add-to-cart {
  border: 1px solid hsl(14, 65%, 9%);
  border-radius: 20px;
  margin-left: 16%;
  text-align: center;
  width: 10vw;
  height: 5vh;
  line-height: 4.5vh;
  background-color: white;
}

.add-to-cart-on-hover {
  border: 1px solid hsl(14, 65%, 9%);
  border-radius: 20px;
  text-align: center;
  margin-left: 16%;
  display: flex;
  justify-content: space-between;
  align-items: center;
  width: 10vw;
  height: 5vh;
  background-color: orange;
}
<div class="products">
    <div class="product">
      <div class="add-to-cart">Add to cart</div>
    </div>
    <div class="product">
      <div class="add-to-cart">Add to cart</div>
    </div>
  </div>

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

Locate an item based on the `Contains` criterion by utilizing Express and Mongoose

Looking to find items in my collection that have userName containing adm. Expecting 2 results based on having records with userNames like admin0 and admin2, but the search returns nothing. The query being used is: Person .find({ userName: { $in: &a ...

What is the best way to avoid having multiple files in a JavaScript file input when a user selects a new file?

I am trying to implement a file input using vanilla JavaScript, and my goal is to restrict the user to uploading only a single file at a time. The issue I am facing is that if the user repeatedly selects a file and clicks the upload button, the file gets ...

Issue with JQUERY where HTML select element is not visible

$(document).ready(function(){ var selArr = [ {val: 'corsair', text: 'Corsair'}, {val: 'evga', text: 'EVGA'}, {val: 'antec', text: 'Antec'} ]; $('#pSupply& ...

Using Ruby to filter elements from a complex JSON structure based on specific criteria

Looking to extract all marketID values from markets where the marketName is 'Moneyline'. I've attempted various combinations of .map, .reject, and/or .select methods, but the complex structure is making it challenging to narrow down. The da ...

Identify when the user intends to open the link in a new window or tab

I am developing an AJAX application where all links on the page are JavaScript links (href="javascript:void(blahblah)"). Some of these links open small webpages in an iframe within a positioned div element that can be moved around. While this design looks ...

I'm currently attempting to incorporate the Material-UI InfoIcon into my code, but I'm unsure of how to properly integrate it within a TextField component

I am attempting to integrate the Material-UI InfoIcon into my TextField code, but I'm unsure of how to go about it. Here is the snippet of Material-UI code: <InfoIcon fontSize="small" /> This is where I would like to place it: <Grid item ...

How to incorporate markdown files as strings in Next.js

Is there a way to bring in markdown files as strings in Next.js for use on both the client and server sides? ...

Place the elements of the array on individual rows

Here, I am successfully inserting dynamic array values into a database table. However, I need to make a slight modification to the code. Currently, the data is being inserted into the database table with commas separating the values. I would like each arra ...

Troubleshooting a Tiny Bottom Sheet Problem in react-native

On my page, I have a bottom sheet that takes up 3/4 of the space. Then, within that bottom sheet, I open another bottom sheet that only occupies 1/4 of the space (without closing the first one). ...

Unable to display the attributes of an object using console.log

I am attempting to log the properties of an object in TypeScript, but I am encountering issues. setTitleAndBody(result: { title: String; body: String; }) { console.log(result) console.log(result.title) } What's interesting is that if I only l ...

Is there a way to use flexbox in a grid to center only a specific tab from MUI?

I am working with an array of tabs and encountering a layout issue. The tabs need to share the available space when there's more than one tab, but when there's only one tab, it should be positioned in the middle of the column. How can I address t ...

Color the column of our kendo ui grid in gray

Within this kendo ui grid here, the initial column [OrderID] cannot be modified. I am seeking a solution to visually distinguish all disabled columns by applying a subtle gray shade, allowing users to easily identify them as non-editable. ...

three.js: Converting 2 directional vectors into either 3 rotations or a matrix

My coding system consists of 2 unit vectors labeled 'Ox' and 'Oy', 1 insertion point, and nearby is an 'Oz' vector that always appears to be {0 0 1}. For instance (after 2 rotations): Ox:{x: 0.956304755963036, y: -0.29237170 ...

Encountering an issue with resolving 'create-react-class'

I have some files with hobbies listed in Data.js. I am attempting to add these hobbies and display them in a list format within my App.js file. However, I keep encountering an error stating that the create-react-class module cannot be found. Does anyone k ...

breaking up various dates into specific formatting using React

I need to convert a series of dates Wed Nov 13 2019 00:00:00 GMT+0000 (UTC),Tue Nov 19 2019 00:00:00 GMT+0000 (UTC),Tue Nov 19 2019 00:00:00 GMT+0000 (UTC) into the format 11/13/2019, 11/19/2019, 11/19/2019 ...

What is the best way to generate text dynamically in React Native by utilizing an array as the source of text content?

I am looking to generate 8 lines of text using a predetermined array of text. For instance: const data = ["Mobile Phones", "Restaurants", "Tv Channels", "Music", "Health", "Wifi", "Real Estate", "Meetups"]; From there, a straightforward: export default ...

Transformation of Gremlin-Javascript Output to JSON Format

Looking for a solution to easily convert the output of Gremlin-Javascript into JSON format. The data seems to be in the form of a Map or multiple Maps based on the traversal. Currently, we are resorting to manually determining the type and utilizing Objec ...

Getting the (x,y) Coordinate Value from jQuery Script and Saving it as a NSString

div tag is essential for applying bold, italic, and various other formatting options in UIWebview. My goal is to retrieve the position coordinates when a user interacts with the div tag using JavaScript/jQuery. I stumbled upon the required code on JSFiddl ...

Error encountered with IPCRenderer in the electron render process

Currently, I am delving into the world of Electron and exploring more nodes. However, I seem to encounter an error every time I try to interact with IPC Renderer. render.js:6 Uncaught ReferenceError: Cannot access 'ipc' before initialization at u ...

What is the correct method of implementing the "OnChange" event to a WooCommerce select element?

My task is to include the onchange="myFunction()" in the select menu below. However, because the select menu is part of woocommerce, I want to ensure that the onchange="myFunction()" remains intact even after updating my theme. How can I achieve this goal ...