11548 sujets

JavaScript, DOM et API Web HTML5

Bonjour,

Je suis en-train de refaire une page contenant un carrousel pour la présentation de produits. Malheureusement le dit carrousel n'est pas très ergonomique, d'où le besoin de changer.

Après plusieurs recherche, je suis finalement tombé sur ce plugin qui m'offre beaucoup de souplesse pour adaptation et assez simple d'utilisation.

Voici où j'en suis
Quand on clique sur l'une des images, il y a une boîte qui s'ouvre avec le descriptif du produit. Le problème c'est que c'est toutes les boîtes qui s'ouvre alors que j'aimerais que ce soit seulement celle cliqué.
Et surtout, si j'enlève ma souris de la zone du carrousel, ça continue à tourner... avec la boîte toujours ouverte. Pas très jolie!

Mon code:

$(document).ready(function() {
	$('li .descr').hover().hide();
	var interval;
	$('ul#produits').roundabout({
		minOpacity: 1, //1 =100% opaque
		minScale: 0.5, //1 = pas de perspective
		tilt: -3, //inclinaison du cercle
		reflect: true, //true = inverser la rotation d'origine
		clickToFocus: false, //false = pas de click pour rotation
		btnNext: '#next',
		btnPrev: '#previous',
	}).click(function() {
		clearInterval(interval); //la rotation arrete
		$('.descr').slideUp(700).css({display:'block'}); //la boite s'ouvre
	}).hover(function() {
		clearInterval(interval); //la rotation arrete
	},
	function() {
		interval = startAutoPlay(); //mouseOut, la rotation repart
	});
	interval = startAutoPlay(); //rotation avec interval
});
function startAutoPlay() {
	return setInterval(function() {
		$('ul#produits').roundabout_animateToNextChild();
	}, 2500);
}
Administrateur
Pour cibler l'élément recevant un événement tel qu'un clic, il faut utiliser $(this)

$("ul.produits").click(function() {
  $(this).hide();
});


À adapter/compléter avec le script.
Oui, je "this" je connais, mais je n'arrive pas à l'appliquer correctement dans le cas présent.

Si je remplace cette ligne
$('.descr').slideUp(700).css({display:'block'});


par ceci
$(this).slideUp(700).css({display:'block'});


ça ne produit pas du tout l'effet recherché...
En même tu cibles tout ton UL pour le clic, comme cela pourrait marcher ??

$('#roundabout li').click(function() 
{
     $(this).find('.descr').slideToggle();
}


Devrait je pense fonctionner.
Bonjour,

Le "find" je connaissait pas, j'ai fait comme ça:
$(this).find('.descr').slideUp(700).css({display:'block'});

Et ça n'a rien changé...
Non mais le souci, c'est que tu définis le click sur $('ul#produits').

Donc dès que tu cliques n'importe où sur le ul, ça ouvre toutes les DIV desc.
Mets l'événement click sur les LI.
Ah ouais!
Bon j'avais déjà fait quelque chose de semblable dans ma multitude de test, mais faut croire que je n'arrivait pas à sélectionner le bon élément.

Bon maintenant ça ouvre puis ça ferme sur le bon élément, mais une fois que je ferme et que je clique sur un autre produit, le boîte s'ouvre et se fermer tout de suite...

Et ça continue de tourné si j'enlève ma souri de la zone.

Mon nouveau code:

$(document).ready(function() {
	$('.control').show();
	$('.descr').hide();
	var interval;
	$('ul#produits').css('height', '250px').roundabout({
		minOpacity: 1, //1 =100% opaque
		minScale: 0.5, //1 = pas de perspective
		tilt: -3, //inclinaison du cercle
		reflect: true, //true = inverser la rotation d'origine
		clickToFocus: false, //false = pas de click pour rotation
		btnNext: '#next',
		btnPrev: '#previous',
	}).hover(function() {
		clearInterval(interval); //la rotation arrete
		$('ul#produits li').click(function() {
			clearInterval(interval); //la rotation arrete
			$(this).find('.descr').slideUp(700).css('display','block'); //la boite s'ouvre
		});
	},
	function() {
		interval = startAutoPlay(); //mouseOut, la rotation repart
	});
	interval = startAutoPlay(); //rotation avec interval
});
function startAutoPlay() {
	return setInterval(function() {
		$('ul#produits').roundabout_animateToNextChild();
	}, 2500);
}

Modifié par juliesunset (31 Aug 2011 - 17:26)
Bon voilà ou j'en suis, je m'approche tranquillement de la bonne solution, mais c'est pas encore ça. Faut tester pour comprendre.

Le problème ce situe encore au niveau du 2e clique...

Mon nouveau code:

$(document).ready(function() {
	$('.control').show();
	$('.descr').hide();
	var interval;
	$('ul#carrousel2').css('height', '250px').roundabout({
		minOpacity: 1, //1 =100% opaque
		minScale: 0.5, //1 = pas de perspective
		tilt: -3, //inclinaison du cercle
		reflect: true, //true = inverser la rotation d'origine
		clickToFocus: false, //false = pas de click pour rotation
		btnNext: '#next',
		btnPrev: '#previous',
	}).hover(function() {
		clearInterval(interval); //la rotation arrete
		$('ul#carrousel2 li').click(function() { //on ouvre la bote
			if($(this).find('.descr').is(':hidden')){
				$(this).find('.descr').slideDown(700).css('display','block');
				clearInterval(interval); //la rotation arrete
			}
			else{
				$('.descr').slideUp(700).css('display','none');
			}
		});
		//$('.descr').click().slideUp(700).css('display','none');
	},
	function() {
		interval = startAutoPlay(); //mouseOut, la rotation repart
	});
	interval = startAutoPlay(); //rotation avec interval
});
function startAutoPlay() {
	return setInterval(function() {
		$('ul#carrousel2').roundabout_animateToNextChild();
	}, 2500);
}
Bonjour.

Tu pourrais peut-être essayer ça :
$(document).ready(function() {
		var interval;
		$('ul#carrousel').css('height', '250px').roundabout({
			minOpacity: 1,
			minScale: 0.5,
			tilt: -3,
			reflect: true,
			clickToFocus: false,
			btnNext: '#next',
			btnPrev: '#previous',
		}).hover(function() {
			clearInterval(interval);
		},
		function() {
			interval = startAutoPlay();
		});
		interval = startAutoPlay();
		
		
		$('ul#carrousel li').click(function() {
				$(this).find('.descr').show();
		});
		$('ul#carrousel li').mouseleave(function() {
			$(this).find('.descr').hide();
		});
	});


Il faut par contre virer dans le css le li:hover. J'espère que ça t'aidera.
SolidSnake a écrit :
Il faut par contre virer dans le css le li:hover. J'espère que ça t'aidera.
Je ne peux pas le virer. Je fait quoi si js est désactivé?

Mais je vais essayer ta solution, je te reviens là-dessus.

EDIT: Ça fonctionne, la boîte s'ouvre et ce ferme correctement maintenant, mais t'as raison, le li:hover semble faire interférence. Il faudrait donc que je trouve le moyen de gérer ça directement dans le fichier js.

Voici mon nouveau code:

$(document).ready(function() {
	$('.control').show();
	$('.descr').hide();
	var interval;
	$('ul#carrousel').css('height', '250px').roundabout({
		minOpacity: 1, //1 =100% opaque
		minScale: 0.5, //1 = pas de perspective
		tilt: -3, //inclinaison du cercle
		reflect: true, //true = inverser la rotation d'origine
		clickToFocus: false, //false = pas de click pour rotation
		btnNext: '#next',
		btnPrev: '#previous',
	}).hover(function() {
		clearInterval(interval); //la rotation arrete
	},
	function() {
		interval = startAutoPlay(); //mouseOut, la rotation repart
	});
	interval = startAutoPlay(); //rotation avec interval

	$('ul#carrousel li').click(function() { //on ouvre la bote
		if($(this).find('.descr').is(':hidden')){
			$(this).find('.descr').slideDown(700);
			clearInterval(interval); //la rotation arrete
		}
		else{
			$('.descr').slideUp(700);
		}
	});
});
function startAutoPlay() {
	return setInterval(function() {
		$('ul#carrousel').roundabout_animateToNextChild();
	}, 2500);
}


Merci!
Modifié par juliesunset (12 Sep 2011 - 15:32)
Bonjour, petit avancement, j'ai réussi à annuler le hover du li quand la boite s'ouvre.

Ne me reste plus à faire en sorte que la rotation s'arrête complètement quand la boite est ouverte et il faudrait aussi que la boite soit toujours positionné par-dessus le carrousel quand elle est ouverte.

Mon nouveau code... encore:
$(document).ready(function() {
	$('.control').show();
	$('.descr').hide();
	var interval;
	$('ul#carrousel').css('height', '250px').roundabout({
		minOpacity: 1, //1 =100% opaque
		minScale: 0.5, //1 = pas de perspective
		tilt: -3, //inclinaison du cercle
		reflect: true, //true = inverser la rotation d'origine
		clickToFocus: false, //false = pas de click pour rotation
		btnNext: '#next',
		btnPrev: '#previous',
		minZ: 1,
		maxZ: 100,
	}).hover(function() {
		clearInterval(interval); //la rotation arrete
	},
	function() {
		interval = startAutoPlay(); //mouseOut, la rotation repart
	});
	interval = startAutoPlay(); //rotation avec interval

	$('ul#carrousel li').click(function() { //on ouvre la boite
		if($(this).find('.descr').is(':hidden')){
			$(this).find('.descr').slideDown(700).css('display', 'block');
		
			if($('.descr').is(':visible')){
				clearInterval(interval); //la rotation arrete
			}
		}
		else{
			$('.descr').slideUp(700);
		}
	});
});
function startAutoPlay() {
	return setInterval(function() {
		$('ul#carrousel').roundabout_animateToNextChild();
	}, 2500);
}
Hello, en passant merci d'utiliser la balise "code=js" lorsque tu mets du code javascript (au lieu de "code" tout seul), c'est plus facile pour décrypter ton souci, et t'aider Smiley cligne
Bonjour Julie,

Pour arrêter ton carrousel quand un bloc est ouvert, tu devras utiliser la fonction :


  clearInterval(interval);


Lorsque tu ouvre ta boîte; donc lorsque l'évènement click() se produit sur ton bloc.

En gros, c'est ce que tu semble faire actuellement. Mais ce doit être ta condition (dixit: if... :visible) qui retourne false au moment où elle est testé.

Cela pourrait être dû au fait que Javascript ne va pas enchaîner tes actions une à la suite de l'autre, mais va les lancer tous à peu près en même temps. Alors même si écris:


  $(this).find('.descr').slideDown(700).css('display', 'block');


Il est possible que lors du test if() adjaçant le DOM n'ait pas encore réagit à la commande JS - car le DOM est beaucoup moins performant que JS.

...Alors...

Pour tester essaie ce code:


	$('ul#carrousel li').click(function() { //on ouvre la boite

		if($(this).find('.descr').is(':hidden')){

			$(this).find('.descr').slideDown(700).css('display', 'block');

		

			if($('.descr').is(':visible')){
                                alert("on arrête effectivement l'interval");
				clearInterval(interval); //la rotation arrete

			}

		}

		else{

			$('.descr').slideUp(700);

		}

	});


Et si tu n'as pas d'alert() qui s'affiche, tu pourras essayer d'écrire ton code ainsi:


	$('ul#carrousel li').click(function() { //on ouvre la boite

		if($(this).find('.descr').is(':hidden')){

			$(this).find('.descr').slideDown(700).css('display', 'block');
			clearInterval(interval); //la rotation arrete

		}

		else{

			$('.descr').slideUp(700);

		}

	});


2- Pour ne pas permettre l'affichage de plusieurs bloc d'affichage,

Je crois que le plus simple sera de forcer la fermeture de tous tes blocs (.desc ?) lors du click() sur un élément et d'afficher ensuite le bloc visé.

Par exemple:



	$('ul#carrousel li').click(function() { //on ouvre la boite

		if($(this).find('.descr').is(':hidden')){

                        $(".desc").hide(); // ou peut-être slideUp(); voit ce qui marche le mieux
			$(this).find('.descr').slideDown(700).css('display', 'block');


		}

		else{

			$('.descr').slideUp(700);

		}

	});


Je ne peux pas jurer que le code marche, mais à vu de nez, c'est dans cette direction que j'essayerais de travailler !

Bonne chance !
juliesunset a écrit :
Ben c'est ce que je fait pourtant...

Mea culpa, je viens de tester et cette balise (et peut-être d'autres je sais pas) déconne… Normalement, elle affiche une colorisation syntaxique, et des scrollbars si le code est trop long…
ZeB: Oui je sais bien, mais semblerais que la colorisation ne se fait plus pour aucune balise. (vue ailleur sur le forum)

Vaxilart: Merci pour les pistes! J'avais déjà essayé de mettre le "clearInterval(interval);" directement sous le "$(this).find('.descr').slideDown(700).css('display', 'block');" mais ça ne changeait rien. Cela dit j'ai essayer avec le alert de différente façon. Le alert s'affiche bien. Mais la rotation ne s'arrête toujours pas.

Entre-temps j'avais retravaillé un peu mon code depuis mon dernier message, pour régler quelque petits problèmes d'affichage par-ci par-là. J'y suis aller de plusieurs commentaire pour y voir plus clair.

À force de faire une tonne de test et d'y réfléchir, je me suis demandé si la solution ne serait pas plutôt de déplacer le "clearInterval(interval);" sur le "ul#carrousel" plutôt que sur le "ul#carrousel li" comme en ce moment. Après tout le premier est appelé sur le ul.
J'ignore si ma déduction est bonne...

Voici mon nouveau code, j'ai laissé le alert pour donner une idée de ce que ça donne.
$(document).ready(function() {
	$('.control').show();
	$('.descr').hide();
	var interval;
	$('ul#carrousel').css('height', '250px').roundabout({
		minOpacity: 1, //1 =100% opaque
		minScale: 0.5, //1 = pas de perspective
		tilt: -3, //inclinaison du cercle
		reflect: true, //true = inverser la rotation d'origine
		clickToFocus: false, //false = pas de click pour rotation
		btnNext: '#next',
		btnPrev: '#previous',
		minZ: 1,
		maxZ: 100,
	}).hover(function() {
		clearInterval(interval); //la rotation arrete
	},
	function() {
		interval = startAutoPlay(); //mouseOut, la rotation repart
	});
	interval = startAutoPlay(); //rotation avec interval

	$('ul#carrousel li').click(function(){
		if($('.descr').is(':visible')){ //si boite ouverte
			$('.descr').fadeOut(700); // fermer la boite
			if($(this).find('.descr').is(':hidden')){ //si boite fermer
				$(this).find('.descr').fadeIn(700).css('display', 'block'); //ouvrir la boite
			}
		}
		else{
			$(this).find('.descr').fadeIn(700).css('display', 'block'); //ouvrir la boite
		}
		if($('.descr').is(':visible')){ //si boite ouverte
			alert("on arrête effectivement l'interval");
			clearInterval(interval); //la rotation arrete
		}
	});
});
function startAutoPlay() {
	return setInterval(function() {
		$('ul#carrousel').roundabout_animateToNextChild();
	}, 2500);
}
Bon petite évolution.
Je pense que j'approche tranquillement de la solution.

voilà j'ai gardé le alert pour continué à faire mes tests, puis finalement je pense avoir trouvé les bon endroit pour mettre la partie qui arrête la rotation. En fait il faut que je le mette à 2 endroit.

Tant que je garde les alert, la rotation s'arrête totalement à l'ouverture d'une boîte et ce tant que la boîte demeure ouverte (comme souhaité). Mais dès que j'enlève les alert, ça ne fonctionne plus, la rotation ne s'arrête plus.

Mon nouveau code:
$('ul#carrousel li').click(function(){
		if($('.descr').is(':visible')){ //si boite ouverte
			$('.descr').fadeOut(700); // fermer la boite
			if($(this).find('.descr').is(':hidden')){ //si boite fermer
				$(this).find('.descr').fadeIn(700).css('display', 'block'); //ouvrir la boite
				if($('.descr').is(':visible')){ //si boite ouverte
					alert("on arrête effectivement l'interval");
					clearInterval(interval); //la rotation arrete
				}
			}
		}
		else{
			$(this).find('.descr').fadeIn(700).css('display', 'block');//ouvrir la boite
			if($('.descr').is(':visible')){ //si boite ouverte
				alert("on arrête effectivement l'interval");
				clearInterval(interval); //la rotation arrete
			}
		}
	});

Modifié par juliesunset (19 Sep 2011 - 19:52)