Velo by Wix: Imitating hover event on repeater container
Velo API doesn't provide a hover event on the repeater container. In this post, we look at one way how we can imitate the hover event.
Motivation
We have a $w.Repeater
component with items of users' cards. When we point with the mouse cursor over some item we want to change background color of this item to light blue color #CCE4F7
and when the cursor moves off of item we want to return the initial white color.
For this, we're going to use two other events that provide repeater API:
onMouseIn()
runs when the mouse pointer is moved onto the element.onMouseOut()
runs when the mouse pointer is moved off of the element
Also, repeater items don't have property style.backgroundColor
for changing the background color of an element. But we can use background.src
property for changing the background image. So in this way, we're going to use a one-pixel image.
Event handlers
To start with, set handlers to onMouse{In/Out}
events. We will use one function for two events by repeaters containers. We declare the handler function above and pass the function's name as an argument to container methods.
/**
* @param {$w.MouseEvent} event
*/
const imitateHover = (event) => {
// our handler for containers
}
$w.onReady(function () {
$w('#container1').onMouseIn(imitateHover).onMouseOut(imitateHover); // set handlers
});
Imitate hover
We use one function for two events, therefore we need to listen to which type of event is going. We're expecting two event types:
event.type === 'mouseenter'
whenonMouseIn()
is running.event.type === 'mouseleave'
whenonMouseOut()
is running.
Let's see the code:
/**
* @param {$w.MouseEvent} event
*/
const imitateHover = (event) => {
if (event.type === 'mouseenter') {
console.log('we have mouseenter if onMouseIn() is running');
}
if (event.type === 'mouseleave') {
console.log('we have mouseleave if onMouseOut() is running');
}
};
$w.onReady(function () {
$w('#container1').onMouseIn(imitateHover).onMouseOut(imitateHover);
});
The object event
always will be consistent with the current container item, which we point mouse cursor. And we can change the background.src
property of the container by event.target
.
// link to one pixel image
const HOVER_PNG = 'https://static.wixstatic.com/media/e3b156_df544ca8daff4e66bc7714ebc7bf95f1~mv2.png';
/**
* @param {$w.MouseEvent} event
*/
const imitateHover = (event) => {
// when the cursor over container then set image.
if (event.type === 'mouseenter') {
event.target.background.src = HOVER_PNG;
}
if (event.type === 'mouseleave') {
// when the cursor is gone then remove the pixel image.
event.target.background.src = '';
}
}
$w.onReady(function () {
$w('#container1').onMouseIn(imitateHover).onMouseOut(imitateHover);
});
Great! It works.
One-pixel image
We used the direct link to the one-pixel image. The size of this image is only 70 bytes. For example, the link of this image has 82 chars length, it's 82 bytes. The link takes up more memory than the image. ¯\_(ツ)_/¯
data:URL
Data URLs, it's a protocol that allows embedded small files inline in documents as a string. It means we can convert a one-pixel PNG image to string and pass it to background.src
.
We can create needed images by 1x1 PNG generator #cce4f7ff.
// one-pixel image encoded to base64
const HOVER_PNG = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAADUlEQVR42mM88+R7PQAIUwMo5M6pSAAAAABJRU5ErkJggg==';
/**
* @param {$w.MouseEvent} event
*/
const imitateHover = (event) => {
if (event.type === 'mouseenter') {
event.target.background.src = HOVER_PNG;
}
if (event.type === 'mouseleave') {
event.target.background.src = '';
}
};
$w.onReady(function () {
$w('#container1').onMouseIn(imitateHover).onMouseOut(imitateHover);
});
The data:URL
image is a little longer than the direct link for this image. And other reason to use data:URL
with the small image we don't send HTTP request for fetching this image.