Image hover effect with Javascript and Kirby

Hi i’d like to have a hover effect on my images like:

hover img1 -> change img 1 to img 2 -> keep img 2 on mouseout
hover img2 -> change img 2 to img 3 -> keep img 3 on mouseout

with 5 various images and one first image

I tried the following with one image and it works

HTML

<div class="img--container">
   <img src="<?php echo $project->images()->first()->url() ?>" alt="<?php echo $project->title()->html() ?>" data-other-src="<?php echo $project->images()->shuffle()->first()->url() ?>">
</div>

JS

$(document).ready(function() {
 $('img').bind('mouseenter', function() {
  $(this).attr({
      src: $(this).attr('data-other-src') 
      , 'data-other-src': $(this).attr('src') 
  })
})

});

But now i don’t know how to set up the code for more images. Maybe you have an idea?

Hi,

Here is one way to achieve this :

<?php
$i = 0;
$datasrc = '';
// loop through the images
// result is a comma separated list of the srcs
foreach($project->images() as $image) {
    if ($i == 0) {
        $datasrc .= $image->url();
    } else {
        $datasrc .= ',' . $image->url();
    }
    $i++;
}
?>

<div class="img--container">
   <img src="<?php echo $project->images()->first()->url() ?>" alt="<?php echo $project->title()->html() ?>" data-src="<?php echo $datasrc ?>" data-index="0">
</div>

JS :

$('img').bind('mouseenter', function () {
        var _this = $(this),
            _imgSrc = _this.attr('data-src').split(','),
            _imgIndex = _this.attr('data-index');
        
        // Increment our index
        _imgIndex++;
        // If the incremented value is higher than the images count -> back to 0
        // (since length isn't 0-based, we need to substract 1 in order to compare the two)
        _imgIndex = (_imgIndex > _imgSrc.length - 1) ? 0 : _imgIndex;
        // Insert the new src and update the index
        _this.attr({
           src: _imgSrc[_imgIndex],
           'data-index': _imgIndex
        });
});

https://jsfiddle.net/cppc7cgz/

Echo the other images as JSON

<div class="img--container">
   <img src="https://images.pexels.com/photos/33109/fall-autumn-red-season.jpg?w=640" alt="Image title" data-other-src='["https://images.pexels.com/photos/218820/pexels-photo-218820.jpeg?w=640", "https://images.pexels.com/photos/147329/pexels-photo-147329.jpeg?w=640"]'>
</div>
"use strict";

$(document).ready(function () {
  var nextImage = function nextImage() {
    var nextImg = JSON.parse($(this).attr("data-other-src"));
    var nextN = $(this).attr("data-other-count") || 0;
    if (nextN > nextImg.length - 1) return;

    $(this).attr("src", nextImg[nextN]).attr("data-other-count", parseInt(nextN, 10) + 1);
  };

  $("img").bind("mouseenter", nextImage);
});

thx for your help guys!

@sylvainjule the fiddle is exactly what i’m looking for. But the html seems not to work. Maybe because i did not show you the whole code. Sorry. Check:

<div>
	<?php 
	$projects = page('projects')->children()->visible();
	$count = 0; foreach ($projects as $project) : ?>
	<?php if($count % 3 < 1): ?>
		<div style="text-align: center;">
			<div>
				<h2><a href="<?php echo $project->url() ?>"><?php echo $project->title()->html() ?></a></h2>
				<a href="<?php echo $project->url() ?>">
<?php
$i = 0;
$data-src = '';
// loop through the images
// result is a comma separated list of the srcs
foreach($project->images() as $image) {
if ($i == 0) {
    $data-src .= $image->url();
} else {
    $data-src .= ',' . $image->url();
}
$i++;
}
?>

<div class="img--container">
   <img src="<?php echo $project->images()->first()->url() ?>" alt="<?php echo $project->title()->html() ?>" data-src="<?php echo $data-src ?>">
</div>
				</a>
				<div>
					<span><?php echo $project->images()->count() ?> Images</span>
				</div>
			</div>
		</div>

	<?php else: ?>
		<div>
			<h2><a href="<?php echo $project->url() ?>"><?php echo $project->title()->html() ?></a></h2>
			<a href="<?php echo $project->url() ?>">
<?php
$i = 0;
$data-src = '';
// loop through the images
// result is a comma separated list of the srcs
foreach($project->images() as $image) {
    if ($i == 0) {
        $data-src .= $image->url();
    } else {
        $data-src .= ',' . $image->url();
    }
    $i++;
}
?>

<div class="img--container">
   <img src="<?php echo $project->images()->first()->url() ?>" alt="<?php echo $project->title()->html() ?>" data-src="<?php echo $data-src ?>">
</div>
    			</a>
    			<div>
    				<span><?php echo $project->images()->count() ?> Images</span>
    			</div>
    		</div>

    	<?php endif; ?>
    	<?php $count++; endforeach ?>
    </div>

Woops it was a late-night-code-mistake from my part, remove the dash in the variable’s name ($datasrc instead of $data-src), i edited my previous post.

Hi, thx for your answer.
It works, but every project has the same data-src images like project 1 now. I hover and the same images appear on on every project.

Maybe because of the foreach loop inside foreach?

Edited for it to work with multiple img tags :slight_smile:

(added a data-index=“0” to the html and updated the JS, updated the fiddle as well)

1 Like

Wow it works perfect! Thank you very much.

But still have one questions :slight_smile:

How can i limit and shuffle the data-src images to 5, excluding the first image of the project?

You’re welcome.

Use limit() :

foreach($project->images()->limit(6) as $image)

1 Like

And again Kudos! Thx