-1

Having an issue with replacing text in multiple elements while hovering only one element

I tried doing document.getElementsbyClassName() but it didnt seem to work

function replace(text) {
  var display = document.getElementById('head');
  display.innerHTML = "";
  display.innerHTML = text;
}

function revert(text) {
  var display = document.getElementById('head');
  display.innerHTML = "";
  display.innerHTML = text;
}
<h2 id="head" onmouseover="replace('oh no!! the heading is gone')" onmouseout="revert('e8')"> e8 </h2>
<p id="pp"> :) </p>

I can replace the header but not the paragraph.

Tyler Roper
  • 21,445
  • 6
  • 33
  • 56
granbraan
  • 1
  • 1
  • 3
    Perhaps not a step towards the answer but why define two identical functions with different names? In regards to the question, please include the code you've tried that doesn't work, not just the part *up* to it. – Tyler Roper Aug 02 '19 at 19:16
  • Seems second function has typo. Mistake is in element identifier name. The `'pp'` must be instead of `'head'`. And two calls must be on each event. `onmouseout="replace_h2('...');replace_pp('...')"` – oklas Aug 02 '19 at 19:19
  • Why does the `

    ` change when the `

    ` is hovered? Because it's the *next* element? Because it's the next *`

    `* element? Because it has an ID of `"pp"`? The question needs more detail. What does the other element's text become? The same as the `

    `'s?

    – Tyler Roper Aug 02 '19 at 19:32
  • @TylerRoper This is for a homework assignment. When hovering over h2,

    would have the text from h2, and h2 would have a different text. Exiting out would revert everything to the original text

    – granbraan Aug 03 '19 at 00:42

4 Answers4

1

Personally I'd recommend a more extensible route revolving around data attributes.

The benefit to this approach is that you don't need to modify the JavaScript for each new item. You simply add attributes to the HTML elements themselves.

See the examples below - comments in the code.

If each element has it's own hover and replace information:

const elems = document.querySelectorAll('[data-replace]');
elems.forEach(elem => {
  elem.addEventListener("mouseover", function() {
    this.dataset["original"] = this.innerHTML;    // store the text as data-original
    this.innerHTML = this.dataset["replace"];     // update the html to be data-replace
  });
  elem.addEventListener("mouseout", function() {
    this.innerHTML = this.dataset["original"];    // revert back to data-original
  });
});
<h2 id="head" data-replace="'oh no!! the heading is gone'">e8</h2>
<p id="pp"    data-replace="Something else"> :) </p>

If one item being hovered affects others, check out the example below instead.

You can group items by giving them the same data-group attribute. The one with the data-replace attribute is the one that triggers the replacement and defines the text.

const elems = document.querySelectorAll('[data-replace]');
elems.forEach(elem => {
  //Get all elements that have the same data-group as the item being hovered
  let group = document.querySelectorAll(`[data-group='${elem.dataset.group}']`);
  
  elem.addEventListener("mouseover", function() {
    group.forEach(e => {                           //For all group elements
      e.dataset.original = e.innerHTML;            //Store the original text
      e.innerHTML = this.dataset.replace;          //Replace the current text
    });
  });
  
  elem.addEventListener("mouseout", function() {
    group.forEach(e => e.innerHTML = e.dataset.original); //Rever to original text
  });
});
<h2 data-group="group1" data-replace="Hello World">heading</h2>
<p  data-group="group1">p</p>

<h2 data-group="group2" data-replace="Goodbye World">heading 2</h2>
<p  data-group="group2">p 2</p>
Tyler Roper
  • 21,445
  • 6
  • 33
  • 56
0

Once option would be to pass the mouseover/mouseout event into the function. then you could use one function for multiple places.

<h2 id="head" onmouseover="replace(this, 'oh no!! the heading is gone', 'pp', 'moused over the heading')" onmouseout="replace(this, 'e8', 'pp', ':)')"> e8 </h2>

<p id="pp"> :) </p>

then use one function that will update the content of whatever element is passed to it.

function replace(e, text, secondElmID, secondElmText) { 
  // update the first element
  e.innerHTML = "";
  e.innerHTML = text;
  // update the second element if is exists
  var secondElm = document.getElementById(secondElmID);
  if (secondElm) {
    secondElm.innerHTML = secondElmText;
  }
}
Ponyboy
  • 956
  • 9
  • 16
0

You just need to make sure that you reference both the elements that need to be affected and change both of them when one of them initiates the event.

Now, for few notes:

let head2 = document.getElementById("head2");
let display = document.getElementById("pp");
let origHead2 = null;
let origPP = null;

head2.addEventListener("mouseover", function(){ replace("oh no!! the heading is gone"); });
head2.addEventListener("mouseout", revert);

function replace(text) {
  // Store the original values before changing them
  origHead2 = head2.textContent;
  origPP = pp.textContent;
  
  // Set the new values to what was passed into the function
  head2.textContent = text;
  display.textContent = text;
}

function revert() {
  // Set the values back to the originals
  head2.textContent = origHead2;
  display.textContent = origPP;
}
<h2 id="head2"> e8 </h2>
<p id="pp"> :) </p>
Scott Marcus
  • 64,069
  • 6
  • 49
  • 71
0

You can proceed by grouping the elements which have the hover and replace text functionality under the same class and give each one a data-txt (where you can change txt part per your requirements) that holds the text that will be shown on hover and also will hold the old text each time an element gets hovered.

Here's a demo :

/**
* txtChange: the elements to be changed (their text) on mouse enter.
* doTextChange: a function that handles changing the text back and forth (replace and return to the original) for each element on both mouseenter and mouseleave events.
**/
const txtChange = [...document.querySelectorAll('.text-change')],
  doTextChange = () => {
    /** loop through the elements **/
    txtChange.forEach(el => {
      /** save the old text **/
      const oldTxt = el.textContent;
      /** replace the old text with the one in the data-txt **/
      el.textContent = el.dataset.txt;
      /** store the old text in the data-txt so that we return to the original text on mouse leave **/
      el.dataset.txt = oldTxt;
    });
  };

/** cycle through the elements and attach the events **/
txtChange.forEach(el => {
  /** the "doTextChange" can handle both the events **/
  el.addEventListener('mouseenter', doTextChange);
  el.addEventListener('mouseleave', doTextChange);
});
/** for demo purposes **/
.text-change {
  margin: 35px 0;
  padding: 8px;
  background-color: #eee;
  transition: all .4s 0s ease;
}

.text-change:hover {
  background-color: #c0c0c0;
}
<!-- the hoverable elements share the same class "text-change" and each one has its own "data-txt" -->

<h2 class="text-change" data-txt="new text !">e8</h2>
<p class="text-change" data-txt="yet another new text">:)</p>
ThS
  • 4,597
  • 2
  • 15
  • 27