Hoover on repeater button

Yes, about onLoad() ← that was my fault, i did not pay attention, this is correct.
Forget about it again.

This is what i want exactly to see in your codings!!!
Now you are working the right way!!! :ok_hand:

console.log('DATASET READY...');
       // just debug purpose

:ok_hand:

//$w("#imageX18").src = undefined;
//console.log ("MOUSE FUORI!!!");

Pay attention here …

$w.onReady(function () { console.log('PAGE-READY...');

	$w.onReady(async()=> {

—> You have 2x onReady()

The max amount of onReadies() would be like …

$w.onReady(function () { console.log('PAGE-READY...');
	$w('#dataset1').onReady(()=>{ console.log('DATASET-READY...');
                $w("#repeater1").onItemReady(($item, itemData, index) => { 
                      console.log('Item-Data: ', itemData);
                      console.log('Index: ', index);                 
                      //CODE...
                      //CODE...
                      //CODE...
                      //CODE...
                      //CODE...
                 });       
         });
});
1 Like

I cleaned it up based on your suggestion, no wix data needed , u were right of course.

still not working…same glitches

$w.onReady(function () {
  $w('#dataset1').onReady(()=>{
    $w("#repeater1").onItemReady(($item, itemData, index) => {
      $item("#button1").onMouseIn(() => {
     
      preloadAndShowImage(itemData.image);
    });
    $item("#button1").onMouseOut(() => {
      // Hide the image on mouse out to reveal the default one behind
      $w("#imageX18").hide();
    });
  });
 
});
});

function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function preloadAndShowImage(imageUrl) {
  //$w("#imageX18").hide();
  $w("#imageX18").src = imageUrl;

  await delay(180); // simulation of onLoad()

  $w("#imageX18").show();
}

:face_with_spiral_eyes:

1 Like

Ok, at least you already have eleminated (1) PROBLEM.

Continue your inspections → i know you will make it !!!

Now you start to understand how to DEBUG !!! :ok_hand:

ok now no more glitch!!! but I’m feeling the weight of that 450 millis waiting for the next image showing :rofl:

and i don’t think I found the second problem u were talking about. it’s a workaround not a solution… can u please give me an extra lil help?

$w.onReady(function () { console.log("Page ready");
  $w('#dataset1').onReady(()=>{ console.log("DATASET ready");
    $w("#repeater1").onItemReady(($item, itemData, index) => { console.log("REPEATER ready");
      $item("#button1").onMouseIn(() => { console.log("BUTTON hover");
     
      preloadAndShowImage(itemData.image);
    });
    $item("#button1").onMouseOut(() => { console.log("BUTTON unhover");
      // Hide the image on mouse out to reveal the default one behind
      $w("#imageX18").hide();
    });
  });
 
});
});

function delay(ms) {
  return new Promise(resolve => setTimeout(resolve, ms));
}

async function preloadAndShowImage(imageUrl) {
  console.log("START SOURCING IMG");
  $w("#imageX18").src = imageUrl;

  await delay(450); // simula l'attesa di caricamento immagine
  console.log("END DELAY");
  $w("#imageX18").show();
}
1 Like

using await, even if it sounds controverse → is not a bad idea!
I remember that i have had similar problems, resolving it with await aswell.

Tweak on it a little bit more, surely you will find even a better solution.
Well done!

1 Like

Do not forget to chose the right answer and mark it as resolved, this will help upcomming coders to find solution faster.
Even if this is still more like a WORKAROUND.

1 Like

sure…i’d like to solve the problem first.
I don’t like this 450 millis of delay…try to figure it out something

1 Like

Perfect! We will wait for solution.
I like!

I see. So onLoad was just AI hallucination after all. :innocent:

OK !! :grin:

1 Like

Correct! Using Ai has advantages and disatvantages as you can see xDDD
At least it can speed-up things a little but in most of cases.

To put it in extreme terms, I think the issue could be solved by preloading all the images from the start and stacking them on top of each other. By fading out the ones you don’t want to show and fading in the one you do, even if animations occur simultaneously, it would just result in a crossfade effect. :innocent:

1 Like

Yes!

this is what I was trying to achieve right now. at least for training purpose…

not in love with stacking images from the Wix editor UI because now I have 6 images…but if they are 20 :face_with_spiral_eyes:

so i was looking if there is a way to preload them but not doing it in the editor.

Hmm, I see. That does sound tough.

So,

Another suggestion I have is that the issue might be because you’re attaching the hover event to the button itself. If you attach the hover event to the container that holds the button, it might react faster and load more efficiently. :upside_down_face:

I think two images should be enough. Once the mouse enters the container, the image should load, and when it hovers over the button, the image should fade in to replace it. If you handle the switch between the two images this way, it should work smoothly. :innocent:

1 Like

You both are flying like bees around their blooming flowers…
You are not far away from possible fast working solution (one of possible solutions).

So we know, that we have some problems with loading timings if it comes to load images on hover. Hovering is a process of milliseconds, so the IMAGE must be delivered in that time. In this case we recognize that loading those images are delayed.

So question → HOW TO LOAD THEM FASTER?

  1. Maybe not on → HOVER ← but already before.
    (This you both i think already have figured out).
    But how exactly?

  2. Maybe → again using the repeaters → onItemReady() ← and loading the images already before → HOVERING ← but direcly collapsing() or hiding() them and only showing them when needed → on HOVER. ???

Could this work?

This yellow marked field already was the idea behind it.

And what about your IMAGE-sizes and type?

Is there still space to reduce the size of your images? The smaler the image → the faster their loadings.

Depending on how big your images are in size, you even can hold them as base64-data-string inside an OBJECT, but not 100% sure if this will work → again back to the variable-solution, then it wouldn’t matter how much images you have, since you do no stacking but instead pushing your images as BASE64-STRING-DATA into your object!

Could that work ?

1. Direct Access vs. Event Binding

  • When you store your image URLs (or any data) in an object, you can access them directly by their keys. This is very efficient because JavaScript objects provide constant-time access (O(1)) to their properties.
  • On the other hand, when you use onItemReady in a repeater, you’re binding event handlers for each item in the repeater. This means that for each item, the code inside onItemReady will run when the user interacts with the item, and this introduces some overhead for each individual repeater item. Additionally, the event handler has to deal with DOM manipulation for each individual item, which can be more computationally expensive.

2. Reduced Overhead

  • Preloading images into an object or an array before any user interaction reduces the need for network calls or fetching resources repeatedly. This preloading reduces any delay when you access the data later (like when hovering over a button).
  • Repeaters, on the other hand, require more resources to process the item content and bind interactions (i.e., what happens on hover). This can add up if there are many items in the repeater, causing delays or a reduction in performance, especially for things like images.

I think there is now enough of input about your issue. :wink:

1 Like

Yeah. On a regular HTML page, if you preload images using a script tag or similar method, you usually won’t see this kind of noticeable delay when switching images. Also, on normal HTML pages, once an image is loaded and stored in memory, subsequent loads are much faster.

But from watching Emme’s video, it seems like there’s still a delay even after the first load. That suggests that on Wix, the only reliable way to solve this is by preloading image and then swapping them in when needed.

It’s absolutely essential that the image is loaded before the hover event on the button. And this is something I’ve been thinking for a while now—but maybe the images themselves are a bit too large. Since they’re just simple visuals, you could probably compress them to just a few kilobytes using the AVIF format.

If you’re doing it manually, Squoosh is a great tool for that. And if you’re dealing with a huge number of images and don’t want to go through them one by one, you can also run a local batch conversion program to process them all at once.

For now, I’d say give Squoosh a try and see how it goes! :melting_face:

P.S.

Or, if the images are preloaded in another repeater on the same page, would that mean they already exist in memory, so when other image elements reference the same URLs, they load faster? :thinking:

2 Likes

Ok, my last POST here…

let startTime = 0;

$w.onReady(function () {
    $w('#button1').onClick(() => {console.log('click');
        const imageUrl = "https://i.ytimg.com/vi/Yk1uCWWUl-4/maxresdefault.jpg";

        startTime = performance.now();

        // Trigger hidden image to preload
        $w('#image1').src = imageUrl;

        // Use a Wix delay + repeated check (simulate polling)
        const interval = setInterval(() => {
            const currentSrc = $w('#image1').src;

            // Check if the image src has been updated AND Wix has rendered it (approx)
            if (currentSrc === imageUrl) {
                const endTime = performance.now();
                const loadTime = endTime - startTime;

                console.log(`Image load time: ${loadTime.toFixed(2)} ms`);

                // Now show the image
                $w('#image1').src = imageUrl;

                clearInterval(interval);
            }
        }, 100); // Check every 100ms
    });
});

Try to use this code to test the → IMAGE-LOADING-SPEED ← inside your environment.

I just did a quick test with an external image without doing it inside a REPEATER, result?

---->

Ok, forgot to reduce the CHECKING-INTERVAL —> 50ms is too much!!!
New CHECKING-INTERVAL10ms —>
2025-04-17 17_49_16-Window
Let’s reduce even more —> 1 ms —>
2025-04-17 17_50_40-Window

The size of tested image…

Now your turn …

2 Likes

Thank you guys !!

I’ll be away for a couple of days I’ll be back and read and reply everything as soon as possible!

Take your time…

Here one improved version …

let startTime = 0;

$w.onReady(function () {
    // Button 1: Load image from URL
    $w('#button1').onClick(() => {console.log('URL Button clicked');
        const imageUrl = "https://i.ytimg.com/vi/Yk1uCWWUl-4/maxresdefault.jpg";
        loadImage(imageUrl);
    });

    // Button 2: Load image from Base64 string
    $w('#button2').onClick(() => {console.log('Base64 Button clicked');
        
        const base64String = "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/BASE-64 DATA STRING HERE........................................
        loadImage(base64String);
        
    });
});

// Reusable function to load image and track time
function loadImage(imageSource) {
    startTime = performance.now();

    // Trigger the image to load
    $w('#image1').src = imageSource;

    // Use a Wix delay + repeated check (simulate polling)
    const interval = setInterval(() => {
        const currentSrc = $w('#image1').src;

        // Check if the image src has been updated
        if (currentSrc === imageSource || currentSrc.includes("data:image/jpeg;base64")) {
            const endTime = performance.now();
            const loadTime = endTime - startTime;

            console.log(`Image load time: ${loadTime.toFixed(2)} ms`);

            // Now show the image
            $w('#image1').src = imageSource;

            clearInterval(interval);
        }
    }, 1); // Check every 100ms
}

//"https://i.ytimg.com/vi/Yk1uCWWUl-4/maxresdefault.jpg";

And with this you can turn any image into base64-string…

<!DOCTYPE html>
<html>
<body>
  <label for="imageUrl">Enter Image URL:</label>
  <input type="text" id="imageUrl" placeholder="Paste your image URL here" style="width:100%; margin-bottom:10px;"/>

  <button onclick="convertToBase64()">Get Base64</button>
  <p><strong>Result (Base64):</strong></p>
  <textarea id="output" style="width:100%; height:200px;"></textarea>

  <script>
    async function convertToBase64() {
      const imageUrl = document.getElementById("imageUrl").value; // Get the URL from the input field
      
      if (!imageUrl) {
        document.getElementById("output").value = "Please enter a valid image URL.";
        return;
      }

      try {
        const response = await fetch(imageUrl);
        const blob = await response.blob();

        const reader = new FileReader();
        reader.onloadend = function () {
          const base64data = reader.result;
          document.getElementById("output").value = base64data;
        };
        reader.readAsDataURL(blob);
      } catch (err) {
        document.getElementById("output").value = "Error: " + err.message;
      }
    }
  </script>
</body>
</html>

You can use it either directly in your wix-page → HTML-COMPONENT) or using → JS-Fiddle.

Paste in the image-url like —> https://i.ytimg.com/vi/Yk1uCWWUl-4/maxresdefault.jpg and convert it to base64-string.
Paste the base64-String into code---->

const base64String = "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/BASE-64 DATA STRING HERE........................................

Do your testings and have fun collecting informative results. :wink:

1 Like

I’m back again.

Thank you so much guys for your suggestions that made me think and search a lot…
I don’t think is an image dimension problem because they are very few kbites but I’ll do a test for sure with your code.
I’m trying to implement a preloading section but I’m facing some problems. my idea was in pseudo code:
for each item of the repeater, get the image url, load the image, store the image in an array.
then show the corresponding image when hover on button.

I’m facing difficulties since seems that you cannot create new images by code in Wix. Am I wrong or am I looking in the wrong direction?

So it comes in my mind your suggestion @onemoretime

Or, if the images are preloaded in another repeater on the same page, would that mean they already exist in memory, so when other image elements reference the same URLs, they load faster? :thinking:

so I tried this approach and nothing…i’m facing the same problem. seems like the repeater images, being hidden by default, are like not loaded…

I feel close to the solution but far as well :slight_smile:

So just to keep track of last days of work…

  • I tried the repeater collapsed image approach as suggested by @onemoretime (not hidden because otherwise it’s not preloaded) but no results . Same lagging.

  • I tried to prepend all the url in an array ,as @CODE-NINJA suggested, before the hover and then calling the image.src in the mouseIn function but nothing. Same glitch. i did something wrong for sure

  • I found a way of “preloading” images using fetch(url) method but seems like the glitch is the same… pasting the code for this attempt here.
    I don’t feel like i wrote something that actually preload images…

$w.onReady(function () {
    console.log("Page ready");

    // Nascondi l'immagine di destinazione
    $w("#imageX18").hide();

    // Configura il repeater collegato al dataset
    $w("#repeater1").onItemReady(($item, itemData, index) => {
        console.log("REPEATER ready, index:", index);

        // 1) image x20 hidden preload image
        $item("#imageX20").src = itemData.image;
        const fullUrl = $item("#imageX20").src;

        // 2) Preload 
        fetch(fullUrl)
            .then(() => console.log("Preloaded image:", fullUrl))
            .catch(err => console.warn("Preload failed for:", fullUrl, err));

        // 3)  hover sul button1
        $item("#button1").onMouseIn(() => {
            console.log("BUTTON hover at index", index);
            $w("#imageX18").src = fullUrl;
            $w("#imageX18").show();
        });

        // 4)  mouse out, 
        $item("#button1").onMouseOut(() => {
            console.log("BUTTON unhover at index", index);
            $w("#imageX18").hide();
        });
    });
});

Next attempt will be the base64 conversion…
I’ll keep you posted