3

I have a requirement to change the text on hover of multiple menu items at once but I cannot use CSS and nor can I give each individual item its own CSS class. What I would like to do is when the mouse hovers anywhere over the .menu-wrapper the Javascript replaces each of the <li> item texts with the relevant replacement text.

I have a script which works perfectly for a single item:

    <div class="menu-wrapper">
        <ul>
            <li>WORD1</li>
        </ul>
    </div>

Javascript:

var originalText = $('.menu-wrapper > ul > li').text();

$('.menu-wrapper').hover(function () {

    var $p = $(this).find('li');
    $p.fadeOut(300, function () {
        $(this).text('replacement word 1').fadeIn(300);
    });
}, function () {
    // set original text
    $(this).find('li').fadeOut(300, function () {
        $(this).text(originalText).fadeIn(300);
    });
});

But obviously if you add multiple <li> items it breaks because it is only storing a single .text() variable and concatenates all the entries after the first mouseout event.

I tried using a switch statement to look for the value of the .text() and change the text value accordingly but it didn't work (my Javascript is weak...).

I'd appreciate any help with this. I only have four items to replace the text of so repeating any script as necessary is not a problem. Normally I would give each one it's own class identity and use what I already have but unfortunately I can't.

Please don't suggest using CSS as I already know how to do that but for this I need to use Javascript.

I could not find this question elsewhere.

Thanks!

Lyall
  • 1,367
  • 3
  • 17
  • 42

5 Answers5

2

Main issue is first line:

var originalText = $('.menu-wrapper > ul > li').text();

This will get all text from all elements in the collection:

What you could do is store that text on each element using jQuery data() by looping over the elements and dealing with instances:

$('.menu-wrapper > ul > li').each(function(){
     $(this).data('original', $(this).text());
});

Then in mouseout part of hover read the previously stored text using data() again

$(this).find('li').fadeOut(300, function () {
    var originalText = $(this).data('original');
    $(this).text(originalText).fadeIn(300);
});

Several options for the new text:

Put it in markup as data attribute

<li data-alt_text="alternate word">

Then within mousenter callback of hover:

$p.fadeOut(300, function () {
    $(this).text($(this).data('alt_text')).fadeIn(300);
});

Or put in array and use first loop to add the array data to element

var words=['W1','W2','W3'];
// first argument of "each" is "index"
$('.menu-wrapper > ul > li').each(function(index){
     $(this).data(
         {
             'alt_text': words[index],
             'original', $(this).text()
           }
      );
});
charlietfl
  • 170,828
  • 13
  • 121
  • 150
  • Thank you very much for the helpful answer - it's the looping through the data that I needed. However while this works perfectly for reverting everything to the original, how can I get it to replace each `
  • ` item with the correct text? For example the second item would be 'replacement word 2' and the third 'replacement word 3' etc. Thanks again.
  • – Lyall Jul 18 '15 at 17:57
  • You could use `data-` attributes in the html...then use `data()` method to read those also `
  • `. Or add them to elements from array within the first loop. `each` has index you can use
  • – charlietfl Jul 18 '15 at 17:59
  • Thank you - unfortunately it isn't possible for me to add the alternative words to the HTML anywhere as the menu is generated by the ecommerce system I'm using. I was hoping for a 'pure' Javascript solution if possible? Appreciate it might not be! – Lyall Jul 18 '15 at 18:11
  • Need to tell us where the data comes from then. I also gave you an array option. If it is related to existing text in anyway and can be parsed from that. You haven't defined any source for it – charlietfl Jul 18 '15 at 18:13