7. Les effets jQuery▲
Contrairement à d'autres bibliothèques, jQuery n'est pas axée particulièrement sur les effets et animations. La bibliothèque en intègre trois grandes familles permettant d'afficher ou cacher des éléments, ainsi qu'une plus générique destinée à faire varier des valeurs de propriétés CSS.
Ces effets sont amplement suffisants dans la plupart des cas. Ils sont tous basés sur le principe d'affichage / apparition d'éléments ou au contraire leur masquage / disparition. Si vous aviez besoin d'utiliser d'autres effets, je vous invite à vous renseigner sur l'extension jQuery UI (pour user interface) qui intègre à jQuery un large panel de fonctionnalités utiles. Sinon, en fouillant dans la collection de plugin (cherchez de préférence dans les plugins « officiels », présentés sur le site de jQuery) vous trouverez certainement votre bonheur.
L'utilisation des effets est très simple avec jQuery. Ils se mettent en place à l'aide d'une unique méthode, dont les principaux paramètres sont communs.
Un effet correspond à une animation. Il est donc possible de préciser la durée de cette animation grâce à un paramètre duree. Ce paramètre peut être soit un entier, qui correspondra à la durée en millisecondes, soit l'une des valeurs prédéfinies slow ou fast.
Une animation correspond à la modification progressive de certaines propriétés d'affichage de l'élément. Lorsque l'on crée soi-même des animations JavaScript, on utilise le plus souvent des timers (setInterval ou setTimeout) et à chaque appel de la fonction de rappel, on modifie des propriétés CSS d'une valeur fixe. L'effet a donc une progression linéaire. Le paramètre easing permet (souvent grâce à des fonctions trigonométriques) de ne pas avoir cette linéarité pour rendre l'animation plus souple visuellement. Il est possible par exemple de donner un effet d'accélération (on augmente légèrement à chaque itération la valeur de la variation), d'accélération initiale et de décélération finale, de rebonds, etc. Seules deux valeurs sont disponibles de base : easing (valeur par défaut) et linear, mais jQuery UI ainsi que plusieurs plugin permettent d'en avoir plus à disposition.
Enfin, un troisième paramètre commun est la possibilité de préciser une fonction de rappel. Si vous appelez un effet et que vous faites suivre d'autres instructions après cet appel, ces instructions seront exécutées en même temps que l'effet. La fonction de rappel permet de définir les instructions à exécuter à la fin de l'animation.
Dans la suite de cette partie, nous allons ajouter différents effets à l'exemple du chapitre précédent, dont les styles ont été légèrement modifiés. Voici le code de la page que nous allons enrichir (ici aussi, le remplissage du contenu a été supprimé), notez l'ajout d'un champ de type select qui permettra de choisir l'effet que l'on veut utiliser.
<!DOCTYPE html>
<html lang="fr">
<head>
<meta charset="UTF-8" />
<title>Onglets</title>
<style type="text/css">
#onglets{
display: none;
}
#onglets li{
position: relative;
float: left;
list-style: none;
padding: 2px 5px 7px;
margin-right: 5px;
border: 1px solid #1175AE;
cursor: pointer;
background-color: #0D5995;
color: #EEEEEE;
}
#onglets li:hover{
text-shadow: 1px 1px #131C25;
}
#onglets .actif{
border-bottom: none;
font-weight: bold;
text-shadow: 1px 1px #131C25;
}
#contenu{
clear: both;
position: relative;
margin: 0 20px;
padding: 10px;
border: 5px solid #0D5995;
top: -6px;
background-color: #EEEEEE;
color: #0F67A1;
width: 500px;
overflow: hidden;
border-radius: 15px;
}
.item{
width: 500px;
}
</style>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script>
$(function() {
$('#onglets').css('display', 'block');
$('#onglets').click(function(event) {
var actuel = event.target;
if (!/li/i.test(actuel.nodeName) || actuel.className.
indexOf('actif') > -1) {
alert(actuel.nodeName)
return;
}
$(actuel).addClass('actif').siblings().
removeClass('actif');
setDisplay();
});
function setDisplay() {
var modeAffichage;
$('#onglets li').each(function(rang) {
modeAffichage = $(this).hasClass('actif') ? '' :
'none';
$('.item').eq(rang).css('display', modeAffichage);
});
}
setDisplay();
});
</script>
</head>
<body>
<h1>Navigation par onglets</h1>
<p>
<label for="effet">Sélectionnez un effet :</label>
<select id="effet">
</select>
</p>
<ul id="onglets">
<li class="actif">Item 1</li>
<li>Item 2</li>
<li>Item 3</li>
</ul>
<div id="contenu">
<div class="item">
<h2>Premier onglet</h2>
...
</div>
<div class="item">
<h2>Deuxième onglet</h2>
...
</div>
<div class="item">
<h2>Troisième onglet</h2>
...
</div>
</div>
</body>
</html>
Par la suite, nous ne montrerons que le code jQuery modifié pour chaque ajout d'effet.
7-1. Les effets show() et hide()▲
Comme leurs noms l'indiquent, ces effets servent à afficher ou masquer un élément. Cependant, leur action va être différente en fonction des paramètres passés.
Dans leur forme la plus simple :
$(selecteur).hide();
$(selecteur).show();
leur action se limite à modifier la propriété display de la collection en cours. Notez toutefois que la valeur de la propriété display est conservée (via l'objet Data lié aux éléments) de façon à pouvoir être récupérée ultérieurement, ce qui rend cette façon de procéder préférable à l'utilisation de la méthode .css('display', 'none|autre'). Une autre utilisation de ces méthodes est :
$(selecteur).hide(duree[, easing][, callback]);
$(selecteur).show(duree[, easing][, callback]);
Si une durée est précisée, alors l'effet hide() va réduire les valeurs des propriétés CSS height, width et opacity jusqu'à 0 puis leur affecter un display à none. À l'inverse, show() va augmenter ces valeurs de façon à afficher les éléments correspondants (après avoir rétabli la valeur de display). Une fois que l'effet sera complet, la fonction callback sera appelée.
Pour mettre en place deux appels distincts de ces méthodes dans notre page d'exemple, nous modifions le code comme suit :
$(function(){
$('#onglets').css('display', 'block');
var effets = {};
$('#onglets').click(function(event){
if(!/li/i.test(event.target.nodeName) || event.target.className.
indexOf('actif') > -1){
return;
}
var actuel = $(event.target);
actuel.addClass('actif').siblings().removeClass('actif');
var animation = $('#effet').val();
effets[animation]();
});
function setDisplay(){
var modeAffichage;
$('#onglets li').each(function(rang) {
modeAffichage = $(this).hasClass('actif') ? '' : 'none';
$('.item').eq(rang).css('display', modeAffichage);
});
}
setDisplay();
effets.swapDisplay = function(){
$('#contenu').hide();
setDisplay();
$('#contenu').show();
};
effets.swapFullDisplay = function(){
$('#contenu').hide('fast', function(){
setDisplay();
$(this).show('slow');
});
};
});
La seule modification apportée au script est la création d'une variable effets qui sera un objet contenant les différents effets applicables. Chaque nouvel effet sera donc ajouté en tant que méthode de cet objet. Le but de ce fonctionnement est de pouvoir appeler la fonction dont le nom correspond à l'attribut value de l'option sélectionnée.
var animation = $('#effet').val();
effets[animation]();
Nous ajoutons donc aussi deux options dans la balise <select> :
<option value="swapDisplay">show() / hide()</option>
<option value="swapFullDisplay">show(duree) / hide(duree)</option>
Le fonctionnement de swapDisplay() est très simple, on cache la balise #contenu, la fonction setDisplay() change le contenu visible, puis on réaffiche #contenu. La fonction swapFullDisplay() nécessite, quant à elle, de passer par une fonction de rappel. En effet, le fait d'avoir précisé une durée va fixer une durée pour masquer l'élément. Si nous avions utilisé la même syntaxe que pour l'effet précédent, cela aurait aussi fonctionné, c'est-à-dire que le second effet aurait attendu la fin du précédent avant de se lancer. En fait, jQuery utilise un système de queue pour gérer les effets, or ici, nous n'avons pas précisé de nom de queue pour nos effets, ils sont donc par défaut affectés à la même file d'attente. En revanche, l'exemple n'est pas satisfaisant, car le contenu visible serait modifié en même temps que le lancement de l'effet de disparition, or nous préférons que cela se fasse lorsque l'élément n'est plus visible, nous sommes donc obligés de passer par une fonction de rappel. Il n'est en revanche pas obligatoire de lancer show() dans cette fonction de rappel, mais si vous la déclarez en dehors, vous ne pouvez plus utiliser $(this).
Notez aussi qu'à l'image de nombreuses méthodes de jQuery, il existe un raccourci pour appeler alternativement show() ou hide() en fonction de la valeur en cours du display. La syntaxe est identique :
$(selecteur).toggle([duree,][,easing][,callback]);
Il est aussi possible de passer en paramètre un booléen qui forcera soit l'affichage soit le masquage des éléments. Cette option va être utile pour améliorer la fonction setDisplay() :
function setDisplay(){
$('#onglets li').each(function(rang){
$('.item').eq(rang).toggle($(this).hasClass('actif'));
});
}
7-2. Les effets fade▲
Les effets de type fade sont ceux qui vont permettre de modifier l'opacité d'un élément jusqu'à une valeur donnée.
La base de cette collection d'effets est la méthode fadeTo(). Sa syntaxe est simple :
$(selecteur).fadeTo(duree, opacite[, easing][, callback]);
L'opacité des éléments en cours variera de leur valeur actuelle à la valeur opacite pouvant aller de 0 à 1.
Cette méthode est particulièrement utile, car l'opacité est gérée différemment suivant le navigateur notamment en ce qui concerne la valeur à attribuer, qui va de 0 à 1 ou de 0 à 100 pour les versions d'Internet Explorer antérieures à 9. Avec jQuery, une seule syntaxe permet de gérer tous les cas.
Si la durée est fixée à 0, alors l'effet aura le même comportement que la méthode css() appliquée à la propriété opacity.
Cette méthode va nous permettre d'améliorer le code de l'exemple pour mettre en valeur l'onglet en cours en diminuant l'opacité des autres onglets et en leur ajoutant un effet de survol. On modifie donc la ligne affichant les onglets pour initialiser cette fonctionnalité :
$('#onglets').css('display', 'block').find('li:not(.actif)').fadeTo(0, 0.4);
Une fois la barre d'onglets affichée, on recherche tous ceux qui n'ont pas la classe actif et on leur applique l'opacité avec une durée à 0. De la même manière, on va modifier la gestion du clic sur les onglets pour réattribuer les bonnes opacités à chaque clic :
actuel.addClass('actif').siblings().removeClass('actif').fadeTo('fast', 0.4);
Notez qu'il n'est pas utile d'affecter l'opacité à 1 pour le nouvel onglet actif puisque le mouseleave ne pourra pas survenir avant la fin du clic, donc au moment où la souris sortira de la zone de l'onglet, il aura la classe actif et ne sera plus concerné par le changement d'opacité.
Enfin, nous ajoutons la gestion de l'effet de survol :
$('#onglets li').hover(
function(){
if($(this).hasClass('actif')){
return;
}
$(this).fadeTo('fast', 1);
}, function(){
if($(this).hasClass('actif')){
return;
}
$(this).fadeTo('fast', 0.4);
}
);
Le résultat est visible dans le fichier jquery-6-3.html.
Si vous souhaitez juste masquer ou afficher un élément avec un effet d'opacité, vous pourrez utiliser les méthodes fadeOut() et fadeIn() :
$(selecteur).fadeOut([duree,][easing,][callback]);
$(selecteur).fadeIn([duree,][easing,][callback]);
Tous les paramètres sont optionnels. Si vous ne précisez pas de durée (ou si vous mettez une chaîne incorrecte), la valeur par défaut est 400 (millisecondes).
Nous ajoutons donc un nouvel effet à notre exemple :
effets.fadeDisplay = function(){
$('#contenu').fadeOut('fast', function(){
setDisplay();
$( this).fadeIn('slow');
});
};
La méthode alternative fadeToggle() permet d'appeler fadeOut() ou fadeIn() en fonction de l'état actuel du display de l'élément.
$(selecteur).fadeToggle([duree,][easing,][callback]);
7-3. Les effets slide▲
Les effets de type slide permettent de masquer ou d'afficher des éléments en modifiant leur hauteur.
$(selecteur).slideUp([duree,][easing,][callback]);
$(selecteur).slideDown([duree,][easing,][callback]);
$(selecteur).slideToggle([duree,][easing,][callback]);
Le comportement est similaire aux effets fade (y compris la valeur par défaut de 400 pour la durée), mais il n'existe pas d'effet slideTo().
La mise en place dans la page d'exemple se fera comme suit :
effets.slideDisplay = function(){
$('#contenu').slideUp('fast', function(){
setDisplay();
$(this).slideDown('slow');
});
};
7-4. La méthode animate()▲
La méthode animate() va vous permettre de créer des animations personnalisées en précisant les propriétés que vous souhaitez faire varier et la valeur finale attendue. Les propriétés que vous pouvez passer à animate() sont quasiment toutes celles qui ont des valeurs numériques (mais il n'est pas possible d'animer les valeurs correspondant à des couleurs ou les raccourcis de propriétés multiples, comme border). D'autre part, vous n'êtes pas limités aux propriétés de style (par exemple, vous pouvez animer les propriétés scrollTop et scrollLeft).
$(selecteur).animate(proprietes, [duree, ][easing, ][callback]);
Les paramètres sont globalement connus, notez toutefois que proprietes correspond à un objet de couples propriété / valeur à attribuer.
À titre d'exemple, nous allons améliorer légèrement notre barre d'onglets en masquant partiellement les onglets inactifs (propriété CSS top fixée à 10px) et les animer au survol pour les afficher entièrement. Pour cela, nous modifions l'animation fadeTo() de la fonction liée au survol des onglets :
$(this).animate({'top': 0, 'opacity': 1}, 'fast');
$(this).animate({'top': 10, 'opacity': 0.4}, 'fast');
ainsi que celle liée au clic sur les onglets :
actuel.addClass('actif')
.siblings()
.removeClass('actif')
.animate({'top': 10, 'opacity': 0.4}, 'fast');
Attention, si vous utilisez animate() pour faire apparaître un élément caché par les méthodes vues précédemment, vous devrez affecter vous-même le display de l'élément en question. En effet, les autres effets prédéfinis se chargent d'attribuer la bonne valeur à cette propriété en fonction du type d'animation demandée (afficher ou masquer), mais animate() ne le fait pas.
Enfin, la méthode animate() propose des réglages additionnels à ceux déjà présentés. Pour cela, vous devrez passer les paramètres dans un objet dont les propriétés correspondent aux options associées à l'effet.
$(selecteur).animate(proprietes, {
duree : numérique ou 'slow' ou 'fast',
easing: 'swing' ou 'linear',
complete: callback,
step: fonction de rappel,
queue: chaine,
specialEasing: easing
});
Les propriétés duree, easing et complete sont déjà connues. step correspond à une fonction de rappel qui sera appelée à chaque étape de l'animation (c'est-à-dire à chaque mise à jour des propriétés), queue permet d'affecter l'animation à une file d'attente spécifique, chaque nom différent créant une nouvelle queue (le nom de la queue par défaut est « fx »), enfin, specialEasing est un objet, ses propriétés correspondent à celles passées en premier paramètre, leurs valeurs correspondent à un easing spécifique à appliquer pour cette propriété.
7-5. Les effets stop() et delay()▲
Dans son état actuel, l'exemple est relativement abouti. Il reste toutefois un léger bogue à corriger. En effet, si l'on passe rapidement la souris plusieurs fois sur les onglets, on constate que les effets s'enchaînent autant de fois les uns après les autres, même après que l'on a fini de déplacer la souris. Pour parer à cela, il va falloir préciser chaque fois qu'un effet de survol est déclenché que l'on veut que celui en cours s'arrête. Pour cela, on va utiliser la méthode stop(). On modifie donc le code de l'événement hover() pour la rajouter :
$('#onglets li').hover(
function(){
if($(this).hasClass('actif')){
return;
}
$(this).stop().animate({'top': 0, 'opacity': 1}, 'fast');
}, function(){
if($(this).hasClass('actif')){
return;
}
$(this).stop().animate({'top': 10, 'opacity': 0.4}, 'fast');
}
);
Notez qu'il est possible de passer à cette méthode un ou deux paramètres booléens, le premier indiquant s'il faut lancer ou non les animations suivantes (par défaut, ce paramètre vaut false, ceci dit, dans notre exemple, il n'y a pas d'autres effets dans la queue), si le second paramètre vaut true (sa valeur par défaut est false) alors l'effet sera stoppé, mais l'élément se verra affecter la valeur finale spécifiée pour chacune des propriétés qui s'appliquent à cet effet.
L'effet delay() est un peu particulier dans la mesure où il ne fait rien à part attendre un certain temps avant de lancer l'effet suivant dans la pile. Il prend en paramètre la durée à attendre (en millisecondes) ou l'une des valeurs prédéfinies (fast pour 200 ou slow pour 600) et éventuellement le nom de la queue sur laquelle doit s'appliquer ce délai.
À titre d'exemple, on pourrait souhaiter, pour notre barre d'onglets, un léger temps d'attente après le survol afin de masquer les onglets inactifs. Dans ce cas, on pourrait ajouter dans la gestion du hover :
$(this).stop().delay(500).animate({'top': 10, 'opacity': 0.4}, 'fast');
Bien entendu, dans ce cas, si la souris sort de l'élément pendant que l'effet est en cours, celui-ci sera bien stoppé, mais l'onglet restera dans son état actuel, c'est-à-dire partiellement caché. On va donc utiliser les paramètres optionnels de stop() pour indiquer que l'on souhaite que l'onglet se mette dans l'état final attendu par l'effet :
$(this).stop(false, true).delay(500).animate({'top': 10, 'opacity': 0.4}, 'fast');
7-6. Compléments sur les effets▲
Nous allons maintenant ajouter d'autres effets disponibles pour nos onglets et en améliorer d'autres.
Tout d'abord, l'effet fade fonctionne correctement, mais on pourrait préférer qu'il se produise sur les éléments .item en jeu et non sur l'ensemble de la div #contenu, ce qui permettrait de garder le cadre visible.
Pour y parvenir, nous allons avoir besoin de modifier certains aspects du code. Tout d'abord, nous aurons besoin d'avoir une référence à la balise à faire apparaître après la disparition de celle actuellement affichée. Nous créons pour cela une variable enCours, qui vaudra par défaut (c'est-à-dire au chargement de la page) la première balise <div> dont la classe est .item. Ensuite, dans ce cas précis (mais pas pour les effets déjà existants), nous ne souhaitons pas mettre l'élément à afficher en display block puisque c'est l'effet lui-même qui s'en chargera, nous modifions donc la fonction setDisplay() pour lui passer un paramètre qui permettra de savoir s'il faut ou non modifier cette propriété :
function setDisplay(isSetDisplay){
$('#onglets li').each(function(rang) {
isSetDisplay && $('.item').eq(rang).toggle($(this).
hasClass('actif'));
$(this).hasClass('actif') && (enCours = $('.item').eq(rang));
});
}
Notez au passage la syntaxe particulière des deux instructions de la boucle. Il s'agit d'une syntaxe permettant de simplifier l'écriture d'une condition (un peu à l'image de l'opérateur ternaire expression ? siVrai : siFaux). Ici, par exemple l'instruction :
isSetDisplay && $('.item').eq(rang).toggle($(this).hasClass('actif'));
est équivalente à :
if(isSetDisplay){
$('.item').eq(rang).toggle($(this).hasClass('actif'));
}
En effet, il s'agit d'une seule instruction, mais qui effectue une comparaison, or selon les règles de l'opérateur &&, celui-ci n'évalue chaque opérande que si la précédente est équivalente à true, donc ici, la partie après l'opérateur ne sera évaluée que si le paramètre passé vaut true.
Dans la seconde instruction, on vérifie si l'onglet possède la classe actif, si c'est le cas, on met à jour la variable enCours.
Désormais, il ne faudra pas oublier de passer le paramètre si l'on ne veut pas provoquer une erreur. Notez que JavaScript ne permet pas d'attribuer de valeur par défaut aux paramètres avec la syntaxe fonction(parametre=valeur){…} comme c'est le cas dans de nombreux langages.
Dans ce cas, si le paramètre n'est pas précisé, il vaudra undefined, qui est un équivalent booléen à false). Le code de l'effet sera alors :
effets.innerFadeDisplay = function(){
$('.item:visible').fadeOut('fast', function(){
setDisplay(false);
enCours.fadeIn('slow');
});
};
On sélectionne d'abord parmi les éléments qui ont pour classe .item ceux qui sont visibles (en espérant que, lorsque l'effet sera lancé, il n'y en aura qu'un seul !), puis on le cache avec fadeOut(), on appelle la fonction setDisplay() dans la fonction de rappel, qui permettra de modifier la valeur de la variable enCours, enfin, on fait apparaître enCours.
De façon similaire, on pourrait avoir, au lieu de la disparition d'un élément puis l'apparition de l'autre, un effet de fondu enchaîné pour lequel l'apparition et la disparition se feraient en parallèle. Cela est assez facile en gérant l'opacité des deux éléments. Mais pour cela, il va falloir que les deux éléments soient référencés en même temps, ce qui n'était pas le cas jusqu'à présent. Il va donc falloir créer une variable pour stocker l'élément actuellement visible, puis lancer la fonction setDisplay() avec le paramètre false et enfin lancer en parallèle fadeIn() sur un élément et fadeOut() sur l'autre. Notez au passage qu'étant donné que les effets ne s'appliquent pas aux mêmes éléments, ils ne se trouvent pas dans la même queue et qu'ils peuvent donc être exécutés en parallèle.
Le principe est séduisant, mais à l'exécution, on constate un léger problème : les éléments sont l'un au-dessus de l'autre et non pas superposés ! Il va donc falloir, à l'exécution de l'effet, créer la superposition en mettant la propriété CSS position à absolute, sans oublier de la remettre à sa valeur initiale à la fin de l'effet.
Mais un autre problème se pose. En effet, si les éléments visibles sont en position absolute, alors ils sortent du flux et donc l'élément #contenu ne contiendra plus rien à afficher et se réduira, il va donc falloir forcer sa hauteur à celle du plus grand des deux éléments en cours et, à la fin de l'effet, rétablir les éléments dans le flux (en supprimant la position absolute) et rendre à #contenu une propriété height adaptée à l'élément affiché (si le plus grand des deux éléments de l'animation est celui qui disparaît, il ne faut pas que #contenu conserve sa hauteur). Le code pour y parvenir est le suivant :
effets.fonduDisplay = function(){
$('.item').css({'position': 'absolute'});
var actuel = enCours;
setDisplay(false);
$('#contenu').css('height', Math.max(actuel.height(),
enCours.height()));
actuel.fadeOut('slow');
enCours.fadeIn('slow', function(){
$('.item').css({'position': ''});
$('#contenu').css('height', '');
});
};
L'effet slide peut aussi être modifié. Plutôt que d'avoir un effet de glissement vers le haut, on peut vouloir obtenir un effet de glissement latéral, le contenu visible se décalera d'un côté, une fois qu'il aura complètement disparu, on le modifie, puis on fait revenir le contenu à son emplacement initial. Cela n'est pas très compliqué à mettre en place, puisqu'il suffit de faire varier le margin-left (ou margin-right, notez au passage que vous ne pouvez pas utiliser animate() sur la propriété margin, mais que vous pouvez sur chacune des marges d'un élément). Il faudra cependant bien penser à attribuer à la propriété CSS overflow de #contenu la valeur hidden pour masquer l'élément lorsqu'il sort de sa balise parente ainsi que la propriété width de l'élément à déplacer pour empêcher l'agrandissement de sa zone de contenu, ce qui provoquerait une adaptation indésirable du rendu du texte au fur et à mesure de l'agrandissement de sa balise parente (d'où la propriété CSS width pour les éléments .item dans la balise <style>).
Au final, le code de l'animation est le suivant :
effets.lateralDisplay = function(){
$('.item').animate({'margin-left': -600}, 'fast', function(){
setDisplay(true);
$('.item').animate({'margin-left': 0}, 'slow');
});
};
Le dernier effet que nous mettrons en place est une amélioration du précédent. Cette fois-ci, au lieu de déplacer l'élément visible, de le remplacer et enfin de le remettre à sa place, nous souhaitons que l'élément à venir apparaisse au fur et à mesure que l'autre disparait, en gros, que l'un pousse l'autre. Nous souhaitons aussi faire en sorte qu'en fonction de la position de chacun des éléments, l'animation se fasse sur la droite ou sur la gauche, donc si l'onglet cliqué est avant l'onglet actuel, l'animation se fasse vers la droite, sinon, vers la gauche.
Pour réaliser cela, il va falloir affecter aux éléments .item des numéros d'ordre correspondant à ceux des onglets. Bien entendu, on a besoin de faire cette affectation qu'une fois lors du lancement du premier effet. L'état de cette affectation sera stocké dans une propriété de l'objet effets et chaque élément se verra affecter son numéro d'ordre grâce à son objet Data. Le code de la fonction commencera donc par :
if(!effets.isCounted){
$('.item').each(function(rang){
$(this).data('rang', rang);
effets.isCounted = true;
});
}
Ensuite, comme dans l'exemple précédent, on va modifier la propriété CSS position des éléments, stocker une référence à l'élément actuellement affiché et appeler setDisplay(). On n'oubliera pas non plus de définir la position par défaut de l'élément en cours et d'en déduire la position finale de l'élément actuellement visible :
$('.item').css('position', 'absolute');
var actuel = enCours, dirActuel = -550, dirEnCours = 550;
setDisplay(false);
Maintenant que l'on a récupéré l'élément à afficher, on peut si besoin rectifier les variables dirActuel et dirEnCours :
if(actuel.data('rang')>enCours.data('rang')){
dirActuel = 550;
dirEnCours = -550;
}
Il ne reste plus qu'à positionner les éléments et ajuster la hauteur de #contenu :
enCours.css({'margin-left': dirEnCours+'px', 'display': 'block'});
$('#contenu').css('height', Math.max(actuel.height(), enCours.height()) + 'px');
Il ne reste plus qu'à lancer les animations, sans oublier à la fin de rétablir les valeurs des propriétés CSS position, margin, height et display des éléments appropriés :
enCours.animate({'margin-left': 0}, function(){
$('.item').css({'position': '', 'margin-left': ''});
actuel.css('display', 'none');
$('#contenu').css('height', '');
});
Le code complet du script est disponible dans le fichier jquery-6-7.html.