Hoover on repeater button

Question:
Can I hover a button of a repeater triggering images outside repeater?

Product:
Wix Studio

What are you trying to achieve:

I have a repeater connected to a dataset. I have buttons in my repeater that is clickable and links to a dynamic page. I’d like to hover the button and show the corrispondent field image on the right of the page, outside the repeater.

What have you already tried:

I tried some code. But the problem is: when i hover button 1 image 1 is showed. when i hover button 2, I see for a fraction of second image 1 and then image 2. I cannot solve the problem. this the code i’m using:

import wixData from 'wix-data';

$w.onReady(function () {
	

  wixData.query("LOCALI_COMMERCIALI")
    .find()
    .then((results) => {
      if (results.items.length > 0) {
        const items = results.items;

        $w("#repeater1").data = items;

        $w("#repeater1").onItemReady(($item, itemData, index) => {
          $item("#button1").onMouseIn(() => {
            $w("#imageX18").src = itemData.image;
            $w("#imageX18").show("fade" , { duration: 25});
			
          });

          $item("#button1").onMouseOut(() => {
            $w("#imageX18").hide("fade" , { duration: 50});
          });
        });
      }
    });
});

Hi, @emme_works !!

Based on your explanation and the actual code, my initial impression is that it seems like you’re using both a dataset and a wix-data query. As for the issues with the repeater and images, I don’t fully understand the exact problem yet, but if you’re already using Velo code, I’d recommend disconnecting the dataset from the repeater to avoid confusion. Generally speaking, it’s best to stick with just one method—either a dataset or Velo code, not both. :innocent:

Also, if possible, I think it’s better to define onItemReady first. :innocent:

import wixData from "wix-data";

$w.onReady(function () {

  $w("#repeater1").onItemReady(($item, itemData, index) => {

    $item("#button1").onMouseIn(() => {
      $w("#imageX18").src = itemData.image;
      $w("#imageX18").show("fade", { duration: 25 });
    });

    $item("#button1").onMouseOut(() => {
      $w("#imageX18").hide("fade", { duration: 50 });
    });

  });

  wixData
    .query("LOCALI_COMMERCIALI")
    .find()
    .then((results) => {
      if (results.items.length > 0) {
        const items = results.items;
        $w("#repeater1").data = items;
      }
    });
    
});
1 Like

:ok_hand:
Seems to be a good idea, but could bring some disatvantages as sideeffect.

@onemoretime
Since you are already a more advanced coder, i would recommend you to evolve your skills even more…

This one you are using directly, yes it is ok (just ok), but for you → JUST-OK ← shouldn’t be enough!!!

 wixData
    .query("LOCALI_COMMERCIALI")
    .find()
    .then((results) => {
      if (results.items.length > 0) {
        const items = results.items;
        $w("#repeater1").data = items;
      }
    });

Instead your intention should be always to keep the following on your mind..

  1. I have always to code as most as possible the dynamic way (avoiding hardcodings)
  2. I should always try to produce reusable code.
  3. My code should always be as much as possible → MODULAR (and again reusable)
  4. I should maybe use → USER-INTERFACES ← to be able to provide my customers a more simple SETUP-SOLUTIONS!

EDIT:
5) Using more → RETURNING FUNCTIONS!

Take a look here…

Maybe your answer now will be → "Oh, i just did not want to spend to much time onto solution → NOT ACCEPTED !!! :upside_down_face:

EDIT: →
Type in → USER-INTERFACE ← into the search of this forum and you will understand…
https://forum.wixstudio.com/search?q=user-interface

2 Likes

Thank you both for your reply.

First of all I have to say I’m a beginner both in coding and in wix. And I’m fully open to suggestions.

I’m using the repeater on the left connected to a dataset because I need it since the data about the apartments can change, and clicking the button i need to go to the specific page of the apartment. (those pages about the apartments ar dynamic pages).

What i’d like to achieve is what partially already is on the video I’m trying to upload. hovering on button (inside repeater) trigger opacity of the corresponding apartment image (the right image, outside the repeater) . I’m saying Corresponding because each apartment has its own image in the same dataset “LOCALI_COMMERICALI”.

Seems like it works, but as shown in the video, the triggered effect isn’t fluid.

That’s my problem.

Do you have some idea? Below imageX18, I have another one, same place, same dimension, that is basically tha floor plan without any green area highlighted. In my mind this should be the “no hover state”…

1 Like

I will only step in, if onemoretime isn’t able to give you an appropirate solution.
Please wait for his answer…

2 Likes

Sure, i’ll wait.

here the video with the glithc

Meanwhile, you can check out all the posts, about integrated USER-INTERFACES, because many of them have had very similar issues! It is always the same if it comes to a new ongoing coder doing his first steps by using (datasets+repeaters in combination with wix-data and so on..)

By just reading few of provided posts, you will maybe even solve your problem on your own.

2 Likes

thank you so much i’ll do for sure!

2 Likes

And my suggestion for you…

…try always to solve problems on your own (even if they seems to be not solveable), push yourself to your own limits and even beyond to get your → OWN-SOLUTION ← this way you will learn coding much faster and you will memorize it much better!

Waiting for delivery from others (of course also works and of course you also will learn), but doing it your own way → it will change your coding skills more efficient!

That beein said, does not mean only to go your own way!
Learning from other is also fundamental !!!

Like i always like to say, —> Viele Wege führen nack Rom! (a german metaphor)

The phrase “Viele Wege führen nach Rom” translates to “Many roads lead to Rome” in English.

It means that there are many different ways to reach a goal or achieve something, emphasizing that there is not just one solution or path to success. It’s often used to suggest flexibility or the idea that multiple approaches can lead to the same desired outcome.

2 Likes

thanks for your suggestion. I usually ask help to somebody only if its my last chance…

I’m struggling from days to solve this :sweat_smile: and still no clue

2 Likes

I like that!

→ STRUGGLING ← is exactly the thing, what will bring you forward! :wink:

Here my CODER’S - STRUGGLING -SCALA:

Struggling minutes → I don’t think programming was made for you.
Struggling hours -----> I can recognize some interest into coding.
Struggling days -------> Yes, definetely you are already in a learning process.
Struggling weeks -----> Maybe a new ongoing super-coder, maybe.
Struggling months —> Either you are already experienced, someone gave you apayed coding-job, or you really do it out of passion.
Struggling years ------> Ok, you are OVERKILL!!! Either you started your own big PROJECT, or definetely someone pays you! :upside_down_face:

EXEPTION: NO STRUGGLING @ ALL → GOD-CODER!!! :grinning_face:

Ok, we will wait for onemore time, let’s see his result on the STRUGGLING-SCALA

See you soon again xDDDDDD

1 Like

Sorry, Ninja Captain, I’m back now… Looks like things have been heating up—my apologies for being away! :innocent: The reason it seemed like I dropped an answer and disappeared was because I had to clean my pet turtle’s tank…:turtle::turtle::turtle:

P.S

Captain. Indeed, you’re absolutely right—it’s as if you saw right through me… The code I proposed as a temporary first-step solution is definitely not something I’m personally satisfied with. However, please hear me out. My approach to answering questions is often based on the idea that it’s easier for the asker to understand if I start by adapting their original code, rather than jumping straight into what I believe is the best practice.

People understand things in different ways, and for beginners in particular, presenting an unfamiliar or overly polished solution from the start could be overwhelming. I believe that it’s better for the asker to achieve some initial success using a form similar to what they already have.

And…

There’s actually a reason behind this approach. In the past, I used to give what I thought was the best solution right from the beginning, but I was told by other members of the forum that presenting a fully finished solution upfront wasn’t always a good idea. Since then, I’ve refrained from doing so. :innocent:

I also came to realize that just handing over a clean solution might not be the most helpful thing for the asker in the long run. That’s why I’ve made a conscious decision to contribute to the community in a way that’s more educational and easier to follow.

1 Like

Take your time, no rush! It is not a payed job! Just some testing.
Maybe i will want to engage you in my team in future :wink:

I think the glitch might simply be happening because show() finishes before the new image is fully loaded. :innocent: As a quick experiment, try using show() and hide() without the fade option and see if that helps.

P.S.

Good morning! By the way, am I the one being tested here? :melting_face:
Honestly, as someone who usually only speaks Japanese, I didn’t quite get what “STRUGGLING SCALA” meant at first—especially since I was still half-asleep! But now I get it, and thanks to that, I had a shockingly energizing start to my morning! :melting_face:

Well then… maybe I’ll just keep struggling with this problem for years? :thinking: Would you two stick with me until then? Wait for me? Aim for God-coder status together with me?

We don’t know how long it’ll take for the Japan national soccer team to win the World Cup, but I do promise that I’ll get this code working by then!
But you know, I think there’s something we can learn from soccer that really applies here—something that’s important for keeping our passion alive while solving problems like this.

In soccer, it’s always the goal or the scorer that gets the spotlight. But in reality, everything that led up to that goal is incredibly important. The person who scores is awesome, no doubt—but don’t forget the players who set it all up.
I think what our Ninja Captain passionately wants to say is something along those lines. And I believe it applies perfectly to coding too.

Are we content with code that just happens to work (a lucky goal)? Or do we strive for reliable, maintainable code—where things work every time based on a well-structured system (a goal that’s the inevitable result of organized play)?
A team that wins the World Cup is almost always the latter.
And as for our current code—well, it’s still in the unstable but kind of working phase. The execution timing, including the animations, is still shaky.

That’s why I think the Captain is emphasizing the importance of defining the user interface properly in order to stabilize the overall behavior.
It’s not just a good habit or best practice in coding—it’s also a key step in helping ourselves understand what approach we’re using to solve the problem.

For simple programs, I personally don’t think this kind of structure is always necessary—but in order to avoid future confusion like what we’re dealing with now, I totally get why the Captain is so passionate about it.

Code generally runs top-to-bottom (though in JavaScript, that comes with caveats). So it’s ideal to have variable declarations and key definitions at the top—just like how a book has a table of contents up front.
This becomes increasingly important the more complex a program gets, or when you’re sharing your code with others.

Also, ideally, code should be broken into single-purpose functions that behave like black boxes—where you don’t need to know how the internals work as long as you provide the correct input and expect a consistent output.
That black-box design is ultimately what contributes to the reproducibility and stability the Ninja Captain is talking about.

While this particular program might not grow into a massive complex one, and yes, it’s technically possible to cram everything into a single onReady callback, it’s still not the best approach.

Even if we can get away with it here, but it’s important to understand that following the proper approach is generally recommended. :innocent:

The right attitude toward programming is probably something like this. :innocent:

1 Like

Regarding the specific code, if you’re using both a dataset and wix-data together, it might be helpful to refer to the code shared by the captain in the link. Also, just to confirm — are you using the dataset in order to swap out the apartment images (the ones placed below the highlight image) when the page is refreshed?

import wixData from 'wix-data';

//xxxxxxxxxxxxxxxxxx [USER-INTERFACE] xxxxxxxxxxxxxx
const DATASET = "myDatasetID"; // the name of your dataset, which you still did not mention in this context !!!
const DATABASE = "Properties"; // the name of your database, which is in your case --> PROPERTIES !!!
const REPEATER = "myRepeaterID"; // the name of your repeater, which you still did not mention in this context !!!
const FIELD = "mapLocation"; // the name of your field, in your case --> mapLocation !!!
//xxxxxxxxxxxxxxxxxx [USER-INTERFACE] xxxxxxxxxxxxxx


$w.onReady(()=> {console.log('PAGE-READY...');        
    $w(`#${DATASET}`).onReady(async()=>{console.log('DATASET READY...');
        const myDataQuery = await wixData.query(DATABASE).find(); console.log('myDataQuery: ', myDataQuery); 
        // REPEATER-PART...
        $w(`#${REPEATER}`).onItemReady(($item, itemData, idex) => {console.log('Item-Data: ', itemData);
            if(itemData) {console.log('Item-Data found!');
                if (itemData[FIELD]) { console.log('Location-Property found!');
                    const mapLocation = itemData[FIELD];
                    const city = mapLocation.city;
                    const state = mapLocation.state;
                    const country = mapLocation.country;
                    $item('#txtElemntCity').text = `${city}`;
                    $item('#txtElemetState').text = `${state}`;
                    $item('#txtElementCountry').text = `${country}`;
                    $item('#txtElementAlltogether').text = `${city}, ${state}, ${country}`;
                } else {console.log('Location-Property NOT found!');}  
            } else {console.log('Item-Data is not defined or null...');}
        });
    });
});

Referenced from …

1 Like

Hi, thank for your reply.

Yes, I have a dataset because I need a dynamic list of all the apartments (on the left), and I’d like to have a different image( high lithed floorplan ) on the right. This image should change as I hover on the button. The need for a dataset to inform the repeater is also because once i click on the button it goes to the specific apatment page. ( a dynamic page based on the same dataset).
And I don’t need to manipulate the dataset by code… I just need to read the value on the buttone been hovered and show the corrisponding image. Actualy I did it, the code kind works as shown in the video, but the glitch is telling me that something is wrong… maybe could be about asynchronus behaviour or loading/waiting time?

Well, i think i have to step in now.

First let us inspect your setup! I see a lot of alarming problems regarding your setup.

  1. You say that your repeater is already connected to a dataset.
  2. But at same time you are feeding your repeater by wix-data.
  3. Again → $w('yourDatasetId).onReady() ← missing.
  4. Retrieving the same data out of database, just to load an image makes no sense if the data do not change! → At least even if it would still be a bad solution, you could load the data into a variable and iterate trough it, which would already save you some loading time, because you load it only ONCE and then just use it.
  5. You must understand, that AS SOON AS YOU USE A → DATASET ← you have to pay attention on how you mix it up with → CODE ← especially if you are mixing it with Wix-Data.
    The DATASET has it’s own processflow and it do not pay attention onto code.
    You can imagine it like 2 in parallel running tasks independet from eachother.

You were able to solve your own question, if it is possible to control external buttons from → WITHING THE REPEATER<–. And YES, the answer is → YES it is possible.
If you have already read this post →

Then you will even know how exactly to control external and internal elements of a REPEATER.

Well, your idea was to generate the following code…

import wixData from 'wix-data';

$w.onReady(function () {
  wixData.query("LOCALI_COMMERCIALI")
    .find()
    .then((results) => {
      if (results.items.length > 0) {
        const items = results.items;
        $w("#repeater1").data = items;
        $w("#repeater1").onItemReady(($item, itemData, index) => {
          $item("#button1").onMouseIn(() => {
            $w("#imageX18").src = itemData.image;
            $w("#imageX18").show("fade" , { duration: 25});	
          });
          $item("#button1").onMouseOut(() => {
            $w("#imageX18").hide("fade" , { duration: 50});
          });
        });
      }
    });
});

Which was not a bad idea → but back again to my introduction, you recognize very fast, that you get into trouble! And if you have read all the posts about the USER-INTERFACE of other users having the similar or even identical issues, which mainly also did not understand why NOT to mix a DATASET connected setup with CODE in parallel, you would already stop trying to drive against a wall.

Well, but since we are already on fire, we need now some water!

By the way, the USER-INTERFACE itself is just a little HELPER, which can make your coding life easier in many cases if you use it.

Ok, what could be the exact issue here? We already know one possible problem…

  1. Mixing-up DATASET and CODE processes in paralel.
    Second one could be…
  2. You are changing the image sourceand while doing some fadind at the same time, The browser maybe still not ready and still loading the new image, but fading already working.
    So it fades in the old one but then switches over to the new one and this could already be the issue.

You can try to increase the fading DURATION to be able to see this sideefect maybe even better. GLITCHES in most cases comes from loading times and delayed actions, like in this case i think.

So as you can see, we have here some kind of a CHAIN-REACTION, caused by wrong handling of DATASET and CODE.

So i think we have here different options of how to resolve the issue.

  1. You go the total CODING-WAY, which will give you total freedom and space for all your wished features and functions and creativity, without causing you a lot of headaches (pure code controled version).

  2. You rely on your already implemented dataset and you try ANOTHER CODE …


    Since your repeater is already connected with your dataset, it could be the perfect solution and you do not need to load the data twice.

Everything about REPEATER you can read here —> Repeater Introduction | Velo

  1. You try this one one more time…
$w.onReady(function () {
 $w('#dataset1').onReady(()=>{
  $w("#repeater1").onItemReady(($item, itemData, index) => {
    $item("#button1").onMouseIn(() => {
      // Instantly hide the current image (no fade-out delay)
      $w("#imageX18").hide("fade", { duration: 0 });

      // Change the source of the image
      $w("#imageX18").src = itemData.image;

      // Wait until the new image is loaded before fading in
      $w("#imageX18").onLoad(() => {
        $w("#imageX18").show("fade", { duration: 250 });
      });
    });

    $item("#button1").onMouseOut(() => {
      // Hide the image on mouse out to reveal the default one behind
      $w("#imageX18").hide("fade", { duration: 100 });
    });
  });
 });
});

I am currious if you need wixData at all.

Let us know what was your solution.

Yeah, I thought so too. It really comes down to conflicting animations targeting a single element. Also, I need to decide whether to stick with a dataset or use wix-data. I’m relieved to know that my thinking wasn’t completely off. :innocent: By the way, I have a question for the captain about waiting for images to load—does an API like onLoad actually exist? I’ve always wanted something like that. Are you basically creating something similar to native JavaScript’s onload? :upside_down_face:

1 Like

Yes, your assumtions were in the right direction.

does an API like onLoad actually exist?

Good catch at this point!!!

And no, i think there is no → onLoad command in wix out of my knowledge, this happens when you try to speed up your work, using some stupid robots xDDDD

1 Like

Hi @onemoretime , while struggling this morning i tried an onLoad solution but seems like it doesn’t exists as a function for images…

thank you so much for your in deep explanation. I’m very very far to understand it as I’m really noob in coding and web. Any way I’ll have a look at all the links you provide me to go “more deep” in the subject.

anyway … yesterday inspired by your suggestion I got “close”(please forgive me :sweat_smile:) to your code of today, i’m pasting it here.

import wixData from 'wix-data';
let currentItem
//const BASEIMAGE = "https://static.wixstatic.com/media/ccf9d9_e0257691a4f343248b154d17fb6d24ff~mv2.jpg";

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

	$w.onReady(async()=> { 
		$w("#dataset1").onReady(async()=>{console.log('DATASET READY...');

			const myDataQuery = await wixData.query("LOCALI_COMMERCIALI").find(); 
			//console.log('myDataQuery: ', myDataQuery); 
			
			$w("#repeater1").onItemReady(($item, itemData, index) => {
				
          		
				$item("#button1").onMouseIn(() => {
					$w("#imageX18").src = itemData.image;
					
            		$w("#imageX18").show("fade", { duration: 25});
					
			
          		});
				$item("#button1").onMouseOut(() => {
					
					//$w("#imageX18").src = undefined;
					//console.log ("MOUSE FUORI!!!");
					
            		//$w("#imageX18").hide("fade" , { duration: 50});
          		});
			});
		});
	});
});

no result. same problem.

the second attempt was to make it wait, a sort of onLoad function but custom made…no results.

import wixData from 'wix-data';

let currentItem;

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

  $w.onReady(async () => {
    $w("#dataset1").onReady(async () => {
      console.log('DATASET READY...');
       // just debug purpose
      const myDataQuery = await wixData.query("LOCALI_COMMERCIALI").find();

      $w("#repeater1").onItemReady(($item, itemData, index) => {

        $item("#button1").onMouseIn(() => {
          preloadAndShowImage(itemData.image);
        });

        $item("#button1").onMouseOut(() => {
          
          // $w("#imageX18").hide("fade", { duration: 50 });
        });

      });
    });
  });
});

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

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

  await delay(180); // simula l'attesa di caricamento immagine

  $w("#imageX18").show("fade", { duration: 25 });
}

I tried your code but onLoad function “doesn’t exist on type image” …

1 Like