1

I have a <h1> who change on click and who gets new content. The new content is two <span> with different id and there is text and an img in each.

If a <span> is on hover, I'd like to change the src of his image.

Actually, my code only works if I set $('h1').hover(function() {}; which in my case should be two functions because otherwise it will change the src of both images.

I tried $('#SpanId').hover(function() {}; but without success.

Here is my simplified code :

HTML

<h1>Hello World</h1>
<button>Change title</button>

jQuery

// On click, change title
$('button').click(function() {
  $('h1').html('');
  $('h1').append('<span id="info">Information <img alt="Info icon" src="http://www.iconsdb.com/icons/preview/orange/info-xxl.png"></span>');
});

// Change info icon on hover
$('#info').hover(function() {
  $('#info img').attr('src', 'http://www.iconsdb.com/icons/preview/gray/info-2-xxl.png');
}, function() {
  $('#info img').attr('src', 'http://www.iconsdb.com/icons/preview/orange/info-xxl.png');
});

Codepen https://codepen.io/Qasph/pen/vmLwWJ

Thanks in advance and have a nice day!

BoltClock
  • 630,065
  • 150
  • 1,295
  • 1,284
Julien W.
  • 159
  • 1
  • 15
  • Take a look at the alternative solution I send you, by just using CSS that is even better solution for such simple implementation. – KodeFor.Me Apr 20 '17 at 08:34

4 Answers4

2

The think is that you dynamically create a new element for which the jQuery it is not yet aware of it, and this makes it not listening for events on it.

The solution I have to provide you here is to listen the whole document $( document ).on( 'event_name', 'searching_element', callback_function ) for the given event on the given element.

// On click, change title
$('button').click(
  function() {
  $('h1').html('');
  $('h1').append('<span id="info">Information <img alt="Info icon" src="http://www.iconsdb.com/icons/preview/orange/info-xxl.png"></span>');
  }
);

$( document ).on(
  'mouseover',
  '#info',
  function () {
    var $info = $ ( this );
    var $img = $info.find( 'img' );

    $img.attr(
      'src',       
      'http://www.iconsdb.com/icons/preview/orange/info-2-xxl.png'
    );
  }
);

$( document ).on(
  'mouseout',
  '#info',
  function () {
    var $info = $ ( this );
    var $img = $info.find( 'img' );

    $img.attr(
      'src',
      'http://www.iconsdb.com/icons/preview/orange/info-xxl.png'
    );
  }
);

Try it your self : https://codepen.io/Qasph/pen/vmLwWJ

In addition to that, you can have the same effect just by using CSS, that is much better solution than writing javascript for such simple stuff.

$('button').click(
  function() {
  $('h1').html('');
  $('h1').append('<span id="info">Information <span class="img_icon"></span></span>');
  }
);
body {
  background-color : dodgerblue;
}

h1 .img_icon {
  width : 20px;
  height : 20px;
  display : inline-block;
  background-image : url( 'http://www.iconsdb.com/icons/preview/orange/info-xxl.png' );
  background-repeat : no-repeat;
  background-size : cover;
  background-position : 50% 50%;
}

h1:hover .img_icon {
  background-image : url( 'http://www.iconsdb.com/icons/preview/orange/info-2-xxl.png' );
}

#info:hover {
  color : white;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>Hello World</h1>
<button>Change title</button>
KodeFor.Me
  • 11,719
  • 19
  • 82
  • 154
  • 1
    To avoid code duplication you can bind two event listeners at once: `$(document).on('mouseover mouseout', '#info', function(e) { const src = e.type === 'mouseover' ? 'http://www.iconsdb.com/icons/preview/gray/info-2-xxl.png' : 'http://www.iconsdb.com/icons/preview/orange/info-xxl.png'; $(this).find('img').attr('src', src) })` – dfsq Apr 20 '17 at 08:44
  • @dfsq ! :) I didn't new this tweek !! :) Thank you :) – KodeFor.Me Apr 20 '17 at 09:46
1

hover not trigger because listener is listen on object that not exist, you must set listener after #info is set:

// On click, change title
$('button').click(function() {
  $('#info').unbind('hover'); // prevent duplicating hover event

  $('h1').html('');
  $('h1').append('<span id="info">Information <img alt="Info icon" src="http://www.iconsdb.com/icons/preview/orange/info-xxl.png"></span>');
  
  $('#info').hover(function() { 
    $('#info img').attr('src', 'http://www.iconsdb.com/icons/preview/gray/info-2-xxl.png');
  }, function() {
    $('#info img').attr('src', 'http://www.iconsdb.com/icons/preview/orange/info-xxl.png');
  });
});
body {background-color: dodgerblue}
h1 img {width:20px}
#info:hover {color: white}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<h1>Hello World</h1>
<button>Change title</button>
Sojtin
  • 2,601
  • 2
  • 14
  • 29
  • 1
    No way. This is terrible answer because it will result into multiple listeners registered on each click. Bad, bad answer. – dfsq Apr 20 '17 at 08:33
  • @dfsq i just said that direct listener must be set when goal object is already created – Sojtin Apr 20 '17 at 08:35
  • Yes, and then you provided worse-practice solution, which OP will take and think it's fine to do it like this, while it's not. Look at Merianos Nikos's or Luke's answer if you want to know how it should be done properly. – dfsq Apr 20 '17 at 08:37
  • @dfsq Right, i fixed that. – Sojtin Apr 20 '17 at 08:43
1

The reason is that your span with #info doesn't exist when you create the hover bind. I'd recommend using on mouseenter/mouseleave with .on:

// On click, change title
$('button').click(function() {
  $('h1').html('');
  $('h1').append('<span id="info">Information <img alt="Info icon" src="http://www.iconsdb.com/icons/preview/orange/info-xxl.png"></span>');
});

$('h1').on('mouseenter', '#info', function() {
  $('#info img').attr('src', 'http://www.iconsdb.com/icons/preview/gray/info-2-xxl.png');
});

$('h1').on('mouseleave', '#info', function() {
  $('#info img').attr('src', 'http://www.iconsdb.com/icons/preview/orange/info-xxl.png');
});

The event listener expects the event to bubble up to the h1 element, which is an object that actually exists when you create the event handlers.

Luke
  • 19,970
  • 26
  • 98
  • 180
1
Change 

$('#info').hover(function() { 
    $('#info img').attr('src', 'http://www.iconsdb.com/icons/preview/gray/info-2-xxl.png');
  }, function() {
    $('#info img').attr('src', 'http://www.iconsdb.com/icons/preview/orange/info-xxl.png');
  });

To:

$('h1').on({
    mouseenter: function () {
        $('#info img').attr('src', 'http://www.iconsdb.com/icons/preview/gray/info-2-xxl.png');
    },
    mouseleave: function () {
        $('#info img').attr('src', 'http://www.iconsdb.com/icons/preview/orange/info-xxl.png');
    }
}, '#info');
Jame
  • 21
  • 2