11548 sujets

JavaScript, DOM et API Web HTML5

Bonjour,

Après avoir lu de nombreux sujets, ici et ailleurs, concernant la possibilité d'afficher/masquer du contenu avec jQuery, je tente moi aussi de réaliser un petit slider maison.

Il s'agit tout simplement, lorsque l'on clique sur une image, d'afficher ou masquer le contenu du commentaire sur un blog.

J'aimerais savoir si je ne fais pas fausse route. Voici le code HTML que j'utilise :
<ul id="lastcomments">
	<li>
		<input type="image" src="http://sxjpl.free.fr/dotclear-files/themes/biblio/img/plus.png" alt="afficher/cacher le commentaire" />
		Fix, le 22.02.12, a laissé un commentaire :<br />
		<div class="toggle"><p>Commentaire numéro 1</p></div>
	</li>
	<li>
		<input type="image" src="http://sxjpl.free.fr/dotclear-files/themes/biblio/img/plus.png" alt="afficher/cacher le commentaire" />
		Fix, le 03.03.12, a laissé un commentaire :<br />
		<div class="toggle"><p>Commentaire numéro 2</p></div>
	</li>
</ul>


On peut voir le résultat ici.
Et voici le code javaScript correspondant :
$(document).ready(function() {
	$("input.image").click(function () {
		$(this).nextAll(".toggle").first().toggle("slow");
	});
});


J'aurais donc quelques questions :
1. Est-ce pertinent d'utiliser un "<input type="image">" pour déclencher le script ? J'avais d'abord utilisé la balise <button> qui me semblait bien adaptée, mais j'ai lu qu'elle posait trop de problèmes pour être stylée en CSS de manière identique sur tous les navigateurs... À moins que cela ne pose pas de problème lorsqu'il s'agit d'une simple image ?
2. Actuellement, il ne se passe rien... Je suppose que mon problème vient de $("input.image") ? Avec $("button"), ça fonctionnait sans problème...
3. Dans l'idéal, il faudrait que le commentaire soit masqué au démarrage. Cela est-il possible ?
4. Enfin, dans l'idéal toujours, j'aimerais que l'url de l'image sur le <input> change selon que le commenhtaire est visible ou non... Cela est-il également possible ?

Merci d'avance pour votre aide !
Modifié par Fix (04 Mar 2012 - 10:20)
Bon, voilà où j'en suis :

. Le numéro 2 est réglé : le code js fonctionne désormais.
. Le numéro 3 l'est aussi : en m'inspirant de ce billet du forum, on ajoute une classe à l'élément html via javaScript, de sorte que si (et seulement si) il est activé, alors on cache les commentaires par un display:none dans la CSS.
. le numéro 4 est en cours : il me semble que le meilleur moyen de modifier l'image est d'utiliser les sprites CSS, ce qui permet que les 2 images (+ et -) soient instantanément dispos, et ne soient pas rechargées à chaque click. Pour cela, j'ajoute une class "on" si le commentaire est affiché (image "-"), ou "off" s'il est masqué (image "+").

Voici donc mon code js actuel :
$(document).ready(function() {
	document.documentElement.className += ' js';
	$("#lastcomments > li > input").click(function () {
		$(this).nextAll(".toggle").first().toggle("slow");
		if ($(this).hasClass('on')) {
			$(this).removeClass('on').addClass('off');
		} else if ($(this).hasClass('off')) {
			$(this).removeClass('off');
		} else {
			$(this).addClass('on');
		}
	});
});


Il me reste toujours 2 questions :
1. Ai-je choisi la bonne option en partant sur un "<input type="image">" pour ce genre de choses ?
2. Comment concilier la technique des sprites CSS avec cet "input" ? En d'autres termes : comment afficher l'icône "+" si l'input a une class "off", et l'icône "-" si l'input a une class "on" ? (en utilisant les sprites CSS, donc)

Je sèche lamentablement. Merci de votre aide !
Bon, je progresse, mais deux ou trois choses me posent toujours problème.

Mon code javaScript est le suivant :
$(document).ready( function () {
	document.documentElement.className += ' js';
	$("#lastcomments > li").image(
		"http://sxjpl.free.fr/dotclear-files/themes/biblio/img/plus.png",
		function () {
			$(this).click( function () {
				$(this).nextAll(".toggle").first().toggle("slow");
				if ($(this).hasClass('expand')) {
					$(this).removeClass('expand');
					$(this).alt="masquer le commentaire";
					$(this).attr("src", "http://sxjpl.free.fr/dotclear-files/themes/biblio/img/plus.png");
				} else {
					$(this).addClass('expand');
					$(this).alt="devoiler le commentaire";
					$(this).attr("src", "http://sxjpl.free.fr/dotclear-files/themes/biblio/img/minus.png");
				}
			});
		}
	);
});

$.fn.image = function (src, f) {
	return this.each(function () {
		$("<img />").appendTo(this).each( function () {
			this.src = src;
			this.onload = f;
		});
	});
}


Ce code ajoute une image à la suite de chaque "<li>" (à la réflexion, comme c'est une image porteuse de sens, qu'il s'agisse d'un "plus" ou d'un "moins", j'ai viré l'idée des sprites CSS), permettant d'afficher ou masquer le contenu d'un commentaire.

Il me paraissait logique d'ajouter cette image via javaScript, puisque si celui-ci est désactivé, le contenu du message est affiché par défaut, donc il n'y a aucun intérêt à inclure l'image "plus"/"moins" en dur dans le code HTML.

Il me reste néanmoins deux problèmes :
1. il faut cliquer DEUX fois au lieu d'une sur l'image "plus" pour qu'elle se change en "moins", et inversement !
2. Le contenu du commentaire n'est pas affiché quand on clique. Il y a donc un problème avec le $(this).nextAll(".toggle"), qui ne pointe pas correctement vers le contenu du commentaire. J'ai essayé $(this).parent().nextAll(".toggle") sans plus de succès, et je suis à court d'idées !

Toute aide serait grandement appréciée. Un grand merci d'avance !
Mon point 2 est résolu ! Ça ne pouvait pas fonctionner, car l'image était ajoutée À LA FIN du contenu de <li>, c'est-à-dire APRÈS le commentaire. Il fallait donc mettre :
$("<img />").prependTo(this).each( function () {

à la place de :
$("<img />").appendTo(this).each( function () {


Il n'empêche que j'ai toujours un problème : maintenant, un clic sur l'image dévoile bien le contenu du commentaire, mais quand on reclique dessus, le commentaire se déplie et se replie à plusieurs reprises avant d'être "caché" !

C'est toujours visible ici.

Une idée de ce qui cloche dans le code donné précédemment ? Merci de votre aide !
Bon, j'ai fini par résoudre tous mes petits problèmes. Et sans aide : je suis fier de moi Smiley cligne

Voici le code javaScript que j'utilise au final :
$(document).ready( function () {
	document.documentElement.className += ' js';
	$("#lastcomments > li").image(
		"../dotclear-files/themes/biblio/img/plus.png"
	);
	$("#lastcomments > li > a > img").click( function () {
		$(this).closest("li").find(".toggle").toggle("slow");
		if ($(this).hasClass('collapse')) {
			$(this).removeClass('collapse');
			$(this).attr("alt", "d\351voiler le commentaire");
			$(this).attr("src", "../dotclear-files/themes/biblio/img/plus.png");
		} else {
			$(this).addClass('collapse');
			$(this).attr("alt", "masquer le commentaire");
			$(this).attr("src", "../dotclear-files/themes/biblio/img/minus.png");
		}
		return false;
	});
});

$.fn.image = function (src) {
	return this.each(function () {
		$("<img />").prependTo(this).each( function () {
			this.src = src;
			this.alt = "d\351voiler le commentaire";
		});
		$("#lastcomments > li > img").wrap("<a href=\"#\"></a>");
	});
}


Je ne suis pas certain que ce soit très bien codé... mais au moins, ça fonctionne.