Pages :
(reprise du message précédent)

Bonjour,

Je me risque à cocher Résolu.

Le code est en production.
Carrousel pouvant gérer un nombre indéterminé de vignettes.
Tous formats d'images et toutes tailles d'images sont possibles grâce à un couche de PHP en amont afin de créer quelques lignes de CSS ou de JS dynamiques.

Encore un grand merci à gcyrillus qui a trouvé ce code original et performant.
Bonjour,

Je rouvre le sujet pour un petit tracas Javascript, pas forcément facile à expliquer.

Un produit, un seul carrousel, ce code fonctionne parfaitement.

const trouve_ca_id = document.querySelector('img.picture');
 
const idImg = trouve_ca_id.id.split ('X');
const ca_id = idImg[0];
const tist = trouve_ca_id.alt;
 
const focused = [];
 
const imaxes = document.querySelectorAll('img.picture, img[src^="im/mu/' + ca_id + '-"] + img'); // Renommé en imaxes pour plus de clarté
 
imaxes.forEach (imax => {
 
let idImg = imax.id.split('X');
if (idImg.length < 3) return;
let ca_id = idImg[0];
let height = idImg[1];
let img_format = idImg[2];
 
imax.addEventListener('mousedown', function () {
 
let activeImg = document.activeElement.getAttribute('src');
focused[0] = activeImg;
PopGrand(ca_id, tist, height, img_format); 
});
 
imax.addEventListener('mouseup', function () {
 
document.querySelector('img[src="' + focused[0] + '"]').focus ();
 
});
 
})
 
 
function PopGrand(ca_id, tist, height, img_format) {
if (!mobile.matches) {return false;}
else
{
window.open ('popup.php?nom='+ encodeURI (ca_id+'G.'+img_format+'&tit='+tist), 'popImg', 'popup=yes,scrollbars=yes,resizable=yes,width=420,height='+height);
}
};


Il est aussi possible de charger plusieurs produits sur la même page afin de les comparer.
Dans ce cas il y a plusieurs carrousels sur la même page.

Un boucle me permet de trouver les produits :

for (let i = 0; i < tab_ca_id.length; i++)
{
bind_event (i, fo, recherche, mobile);
}


Ensuite je fais un quasi copier-coller du code qui marche pour un seul carrousel :

function bind_event (i, fo, recherche, mobile)
{

let imax = document.querySelector ('img.picture[src^="im/pr/' + tab_ca_id[i] + 'G."]');

let ca_id = tab_ca_id[i];

let tist = imax.alt;

let idImg = imax.id.split ('X');
let height = idImg[1];
let img_format = idImg[2];

let focused = [];

const idPreco = document.getElementById ('F'+ ca_id);

const cherch = document.getElementById ('J'+ ca_id);

let imaxes = document.querySelectorAll('img.picture, img[src^="im/mu/' + ca_id + '-"] + img');

imaxes.forEach (imax => {
	
let idImg = imax.id.split('X');
if (idImg.length < 3) return;
let ca_id = idImg[0];
let height = idImg[1];
let img_format = idImg[2];

imax.addEventListener ('mousedown', function()
{
let activeImg = document.activeElement.getAttribute('src');
focused[0] = activeImg;
PopGrand (ca_id, tist, height, img_format)
});

imax.addEventListener('mouseup', function ()
{
document.querySelector('img[src="' + focused[0] + '"]').focus ();
});

});


Cela fonctionne encore SAUF que l'identification de activeImg devient assez erratique.
Sur la carrousel 1 je me prends le titre de carrousel 2.
Si je ferme carrousel 2 je retombe sur carrousel 3.

Je pense qu'il a un problème de réinitialisation.

Comme le cas d'une page à plusieurs produits est rare et que les carrousels s'ouvrent correctement ce n'est pas dramatique mais si vous avez une solution pour bien identifier l'image active dans le cas de plusieurs carrousels je suis intéressé.
Bonjour,

Une première erreur porte sur cette ligne dans la fonction bind_event:

let imaxes = document.querySelectorAll('img.picture, img[src^="im/mu/' + ca_id + '-"] + img');


img.picture est à remplacer par :

img.picture[src^="im/pr/' + tab_ca_id[i] + 'G."]


Donc :

let imaxes = document.querySelectorAll('img.picture[src^="im/pr/' + tab_ca_id[i] + 'G."], img[src^="im/mu/' + ca_id + '-"] + img');


Là cela marche bien sauf que parfois l'image active est mal identifiée s'il s'agit de img.picture dans le carrousel.

let activeImg = document.activeElement.getAttribute('src');


Pas totalement fiable si img.picture...

Avez-vous une idée pour fiabiliser ?

Je rappelle que le problème n'existe que si plusieurs carrousels sur la même page.
Aucun souci avec un seul carrousel.

Plusieurs carrousels.
J'ouvre une popup par une image de Carrousel UN
Je ferme la popup
J'ouvre une popup par img.picture de Carrousel DEUX
Cela m'envoie vers carrousel UN comme si img.picture de Carrousel DEUX n'était pas active.

Si la deuxième popup est ouverte par une autre image que img.picture il n'y a pas de problème.
Modifié par boteha_2 (07 Sep 2025 - 13:03)
Modérateur
Bonjour,

Si tu as plusieurs carrousel, il serait alors peut-être plus judicieux de donner une classe aux vignettes cliquées et de te servir de cette cette class dans la feuille de style.

Le script ici ne stocke dans le tableau qu'une information sans différencier le(s) carrousel(s). Bien que tu pourrait aussi utiliser ce tableau pour stocker la dernière vignette active de chaque tableau.
imgFocused[0] = vignette active carroussel 0
imgFocused[1] = vignette active carroussel 1
imgFocused[2] = vignette active carroussel 2

Cela n’empêchera pas le fait qu'il n'est possible de ne donner le focus qu'a un seul élément.

Traiter les carrousels indépendamment et appliquer une class à la dernière vignette cliquée de chacun d'eux semble dans ce cas une solution adéquate.

Cdt
Bonjour gcyrillus,

Merci de ton suivi.

Je ne doute pas de ta solution mais je ne vois pas bien comment la coder.

Sachant que le problème n'apparaît que si clic sur img.picture.

imax.addEventListener ('mousedown', function()
{
let activeImg = document.activeElement.getAttribute('src');
focused[0] = activeImg;

PopGrand (ca_id, tist, height, img_format)
});


Le problème n'est-il pas avec activeImg qui pour une raison que j'ignore est mal défini si img.picture provient d'un carrousel différent de celui précédemment utilisé ?
Tordu je reconnais.

PS : problème constaté avec Firefox et Chrome.
Modifié par boteha_2 (07 Sep 2025 - 14:25)
Modérateur
Bonjour,

Sans voir le script fonctionner, le script enregistre normalement la dernière vignette qui à le focus si il y en a une sur l’événement "mousedown" .

Regarde la console pour les message d'erreur et éventuellement ajoute des console.log() sur ton script pour suivre les valeurs des variables et si cela correspond à la logique attendue du script.

Quant à img.picture,
combien y en à t-il ? (le script n'en cherche qu'une ),
y-a-t-il une vignette qui à le focus avant de cliquer dessus ? (je dirais non par défaut).

Cdt
Bonjour gcyrillus,

gcyrillus a écrit :
Quant à img.picture,
combien y en à t-il ? (le script n'en cherche qu'une ),
y-a-t-il une vignette qui à le focus avant de cliquer dessus ? (je dirais non par défaut).


img.picture
Un seul par carrousel, cela correspond à l'image principale.
C'est le deuxième élément dans <figure> si tu te souviens du code html.
Cette class picture n'est pas indispensable mais elle existait avant le carrousel et je l'ai conservée. Elle est utile si l'image n'est pas renforcée par un carrousel, ce qui est fréquent.

Autrement je pense avoir compris d'où vient le défaut de conception.

Comme img.picture est affiché par défaut tu peux ouvrir la popup sans avoir cliqué sur la vignette correspondante.
Si plusieurs carrousels l'image active en mémoire peut provenir d'un autre carrousel ouvert avant.

Il faut donc ajouter une déclaration.
Si clic sur img.picture la vignette correspondante (qui est img:first-child dans le carrousel) devient la vignette active.
Je vais essayer de faire ça tout seul, je reviens vers vous si problème.

Il faut noter qu'il n'y a pas de problème si un seul carrousel.
Si clic sur img.picture affiché par défaut il n'y a pas de vignette active, on reviendra donc sur img.picture.

Encore merci pour le suivi.
Bonjour,

Cela semble marcher avec ce code...
J'essaye d'expliquer la logique

let imaxes = document.querySelectorAll('img[src^="im/pr/' + tab_ca_id[i] + 'G."] + img, img[src^="im/mu/' + ca_id + '-"] + img');

imaxes.forEach (imax => {
	
let idImg = imax.id.split('X');
if (idImg.length < 3) return;
let ca_id = idImg[0];
let height = idImg[1];
let img_format = idImg[2];
let prov = 0;
let ca_id_produit = 0;

imax.addEventListener ('mousedown', function()
{
let activeImg = document.activeElement.getAttribute('src');

// Clic direct sur une grande image affichée par défaut au chargement de la page

if (activeImg === null) activeImg = 'im/pr/' + ca_id + 'G.' + img_format;
else
{
// Clic direct une grande image après ouverture d'un carrousel
// Je cherche à savoir quel a été le dernier carrousel cliqué
// C'est la variable prov qui est de type im/mu/123-1G.avif
// Je dois trouver le numéro du produit (du carrousel qui est 123

prov = activeImg.substring(6, activeImg.indexOf('.') - 1);
if (prov.indexOf('-') !== -1)
{
prov = prov.substring(0, prov.indexOf('-'));
}

// Je vais comparer prov avec le numéro du carrousel cliqué, ca_id est de type 345 ou 345-1
// L'objectif est de trouver 345

ca_id_produit = ca_id;
if (ca_id_produit.indexOf('-') !== -1)
{
ca_id_produit = ca_id_produit.substring(0, ca_id_produit.indexOf('-'));
}

// Si la prov est différente du carrousel cliqué je corrige activeimg en sachant que l'image active est une grande image en direct.

if (prov != ca_id_produit) activeImg = 'im/pr/' + ca_id + 'G.' + img_format;
}

focused[0] = activeImg;

PopGrand (ca_id, tist, height, img_format)
});

imax.addEventListener('mouseup', function ()
{
document.querySelector('img[src="' + focused[0] + '"]').focus ();
});
});


Dans le cas de vignette sur un carrousel > popup sur la grande image sélectionnée > fermer la popup > autre carrousel > vignette > popup sur la grande image sélectionnée : cela fonctionnait déjà car activeImg est correct.

Dans le cas de null cela fonctionne.
Cela évite une alerte dans la console mais le script s'exécutait correctement sans ça.

Dans le cas de vignette sur un carrousel > popup sur la grande image sélectionnée > fermer la popup > autre carrousel > clic direct sur une grande image d'un autre carrousel : cela fonctionne maintenant.

Dans le cas de Clic sur grande image sanas passer par un vignette > fermer la popup > clic direct sur une grande image d'un autre carrousel : cela fonctionne maintenant.

Je pense avoir couvert tous les cas.

À noter que le code d'origine fourni par gcyrillus fonctionnait parfaitement pour un seul carrousel, c'est la présence de plusieurs carrousels sur une page qui oblige à ces acrobaties.
Modifié par boteha_2 (09 Sep 2025 - 22:06)
Pages :