Je vous propose aujourd'hui un troisième exercice (voir le n° 1 et le n° 2) sur jQuery, dans l'idée de faire progresser les membres mais aussi d'animer la section.
Avant d'entrer dans le vif du sujet, il y aura un certain nombre de règles à respecter pour que tout se passe bien dans ce topic.
Règles
Le troll et le flood ne sont pas tolérés. Inutile de balancer des "Pourquoi jQuery et pas Mootools ?", les messages non constructifs seront modérés.
Je vous fournis le code HTML, vous n'aurez pas le droit de le modifier.
Votre réponse contiendra uniquement du code jQuery avec la balise <secret> de manière à respecter ceux qui n'ont pas commencé l'exercice.
Evidemment, le code que vous posterez devra être de vous, pas la peine de recopier un code externe, cela n'a pas d'intérêt. L'utilisation de plugins n'est pas autorisée.
Objectif du script
Description
Nous allons créer dynamiquement des notes de bas de page sur certains mots dans un texte. Ces mots seront définis, le HTML également (interdit de le modifier). Une portion de CSS sera également fournie.
Au clic sur un mot, cela devra mener vers l'élément qui contient les notes (comprendre une ancre, la même pour tous).
HTML
<div id="texte">
<p>PARIS (AFP) - Les prix à la consommation en France ont encore grimpé de 0,4% en décembre par rapport au mois précédent, pour atteindre 2,5% sur un an (+2,4% hors tabac), a annoncé jeudi l'<a href="#" class="footnote" data-note="l'Institut national de la statistique et des études économiques">Insee</a>.</p>
<p>Théoriquement, ce taux d'<a href="#" class="footnote" data-note="L'inflation est une baisse durable de la valeur de la monnaie">inflation</a> devrait faire monter le taux du Livret A de 2,25% à 2,50%, voire 2,75% au 1er février.</p>
<p>Mais le gouverneur de la Banque de France (BdF) Christian Noyer a déjà préparé les esprits à son éventuel maintien en l'état, expliquant que l'inflation devrait baisser dans les prochains mois et qu'il serait donc inutile de relever le rendement du <a href="#" class="footnote" data-note="Le livret A est le compte d'épargne réglementé et défiscalisé français le plus utilisé">Livret A</a> pour le diminuer dans la foulée.</p>
</div>
#notes correspond au bloc (avec le fond gris) qui contient toutes les notes, cet élément n'est pas présent par défaut.
N'oubliez pas les exposants pour chacun des mots (3 dans cet exercice). Ils devront bien sûr être dynamiques.
Il y a un seul problème, c'est que ma liste <ol> ne marche pas, pourtant, le code produit est bon !
Voici le code que me donne Chrome :
<ol id="lst"><li id="n_1">l'Institut national de la statistique et des études économiques</li><li id="n_2">L'inflation est une baisse durable de la valeur de la monnaie</li><li id="n_3">Le livret A est le compte d'épargne réglementé et défiscalisé français le plus utilisé</li></ol>
J'ai encapsulé le tout dans un if pour eviter d'avoir a executer du code inutilement si pas de footnote (superflu pour l'exercice j'en conviens)
Je n'ai pas utilisé de <ol></ol> parce qu'il semble que le temps d’exécution est plus important que lorsque l'on utilise directement l'index du each (le résultat reste identique pour l'utilisation actuelle)
Il était possible d'utiliser un scrollTo pour ne pas avoir a afficher le hash dans l'url, cela dit, le temps d’exécution prend une à deux millisecondes dans la face, donc vu qu'il était mentionné "ancre" dans l’énoncé je suis parti du principe que le hash ne posait pas de problème
Le test du .length est judicieux !
En revanche le <ol> ici est justifié. Ta ligne 10 par contre est inutile, les éléments sont déjà présents dans le DOM donc tu n'as pas besoin de faire comme cela. Et ça te fait un gestionnaire d'événement inutile d'ailleurs.
Effectivement pour <ol> si tu parle de l'espacement a gauche c'etait la seule solution sans retoucher au css, j'avais pas fait gaffe. Pour ce qui est de la ligne 10 tu veux bien dire que remplacer le .on par un .click etait suffisant ou j'ai mal compris ?
Effectivement pour <ol> si tu parle de l'espacement a gauche c'etait la seule solution sans retoucher au css, j'avais pas fait gaffe. Pour ce qui est de la ligne 10 tu veux bien dire que remplacer le .on par un .click etait suffisant ou j'ai mal compris ?
Tu as fait un .on() façon .live() (c'est-à-dire avec 3 arguments) qui est seulement nécessaire si c'est pour écouter un événement créé par jQuery.
@Desolation: ce serait bien de mettre en place une test jsperf
Le but du topic est de voir les différentes méthodes/logique en demandant à plusieurs personnes de coder sur un même énoncé, tout le monde fait différemment.
Du côté performance je ne trouve pas intéressant de débattre sur des millisecondes, surtout que ce qui changera, c'est la vitesse de chargement de jQuery qui est différente selon le débit, s'il est en cache ou pas... Bref nous aurons tous des résultats différents car plusieurs paramètres entrent en compte.
Mais essayons de ne pas nous écarter du sujet initial.
Point important :
$() est une fonction lourde dont il faut absolument éviter d'abuser !
Mettez vos sélections dans des variables !
@Dominique0796 :
var $nb = 0;
var $text = $('#texte');
$text.after('<br /><br /><ol id="notes" ></ol></div>');
var $notes = $('#notes');
$('.footnote').each(function(){
$nb++;
var $this = $(this);
$this.after(' <sup>'+$nb+'</sup> ');
$this.attr('href', '#n_'+$nb);
$notes.append('<li id="n_'+$nb+'" >'+$this.data('note')+'</li>');
});
@loun4st4ck :
var dataNotes = '';
$('.footnote').each(function(i) {
var noteIndex = 'note-'+(i+1);
var $this = $(this);
dataNotes += '<li id="'+noteIndex+'">'+ $this.data('note')+ '</li>';
$this.attr('href', '#'+noteIndex).append($('<sup />').text(i+1))
});
$('#texte').after($('<ol />', {
'id':'notes'
}).append(dataNotes));
@Str!k3z :
$(document).ready(function() {
var $footnotes = $('a.footnote');
// ".footnote" ou "a.footnote", il faut choisir...
// Sinon ton code a un côté illogique.
if($footnotes.length > 0){
var str="<div id='notes'><a name='footn'></a>";
$footnotes.each(function(i){
str += i+". "+$(this).data('note')+"<br />";
});
$('body').append(str+"</div>");
$('#texte').on('click','.footnote',function(){
document.location.hash = '#footn';
return false;
});
}
});
Personnellement, l'utilisation faite du .on() par Str!k3z ne me traumatise pas.
Ca a le mérite de ne placer qu'un seul écouteur au lieu d'en placer autant qu'il y a de notes.
Mais ça n'apporte pas grand chose niveau optim', vu que de toutes façons, on a déjà parcouru chaque lien.
Ce qui me choque plus, c'est l'utilisation de returnfalse et la modification du location, contrairement aux autres qui ont modifié le href des liens (ce qui est plus sémantique)...
A défaut, utiliser e.preventDefault() serait réellement préférable à returnfalse pour laisser l'événement se propager tranquillement.
Merci Golmote pour le rappel du $ même si je le répète à chaque fois.
Voici ma version :
var $this = $('#texte');
var $footnotes = $('a.footnote', $this);
if ($footnotes.length > 0) {
var notes = 'notes';
// creating the notes div
$('<div>', {
'id': notes,
'class': 'footnotes'
}).appendTo($this);
// creating le list
$('<ol>').appendTo('#' + notes);
// for each note
$('a.footnote', $this).each(function(i) {
i++;
$(this).attr('href', '#' + notes).after(' <sup>' + i + '</sup>');
// inserting the note into the list
$('<li>', {
html: $(this).data('note')
}).appendTo('#' + notes + ' ol');
});
}
Je me suis inspiré de cet exercice pour en faire un plugin qui fait la même chose à peu de chose près qu'il peut y avoir plusieurs textes sur la même page. Voir la news sur mon blog.
Point important :
$() est une fonction lourde dont il faut absolument éviter d'abuser !
Mettez vos sélections dans des variables !
@Str!k3z :
$(document).ready(function() {
var $footnotes = $('a.footnote');
// ".footnote" ou "a.footnote", il faut choisir...
// Sinon ton code a un côté illogique.
if($footnotes.length > 0){
var str="<div id='notes'><a name='footn'></a>";
$footnotes.each(function(i){
str += i+". "+$(this).data('note')+"<br />";
});
$('body').append(str+"</div>");
$('#texte').on('click','.footnote',function(){
document.location.hash = '#footn';
return false;
});
}
});
Personnellement, l'utilisation faite du .on() par Str!k3z ne me traumatise pas.
Ca a le mérite de ne placer qu'un seul écouteur au lieu d'en placer autant qu'il y a de notes.
Mais ça n'apporte pas grand chose niveau optim', vu que de toutes façons, on a déjà parcouru chaque lien.
Ce qui me choque plus, c'est l'utilisation de returnfalse et la modification du location, contrairement aux autres qui ont modifié le href des liens (ce qui est plus sémantique)...
A défaut, utiliser e.preventDefault() serait réellement préférable à returnfalse pour laisser l'événement se propager tranquillement.
Merci pour ces précisions, je ne savais pas vraiment pour la fonction $(), mais j'ai bien compris la problématique et j'en prend bonne note.
Pour le return false, j'ai oublié de le virer je m'en suis même pas rendu compte, je n'aurais pas du le mettre, il est totalement inutile a mon sens (en revanche si tu peux revenir sur l’intérêt du preventDefault() dans ce cas de figure je suis pas contre parce que je ne suis pas sur d'avoir saisi toute la subtilité de ce que tu as ecrit)
C'est vrai, j'ai pas pensé à mettre mes sélecteurs en cache
Il y a un détail qui m'embête (avis personnel) chez beaucoup de dev JS: lancer une manipulation directe du DOM à l'intérieur d'une boucle alors qu'on peut faire autrement(*). Il faut savoir que les manipulations directes du DOM sont souvent à l'origine de multiples reflow...
(*) Par exemple, stocker les items dans un string et faire un seul append
Tu dis vrai loun4st4ck, et en ça j'ai bien aimé ta concaténation
@Str!k3z : L'histoire du return false, en quelques lignes :
En JS, lorsqu'un événement se produit, il se propage.
Typiquement, quand tu cliques sur un élément, l'événement parcourt tout l'arbre DOM pour arriver jusqu'à l'élément en question, et déclenche l'écouteur d'événement approprié, s'il existe. Ensuite, l'événement remonte l'arbre DOM et déclenche ainsi les gestionnaires d'événements placés sur les éléments parents.
On peut imaginer de nombreux cas où ce comportement est utile.
Ce comportement est appelé la propagation de l'événement.
Lorsqu'on fait un returnfalse dans un écouteur d'événement avec jQuery, la conséquence principale est d'empêcher le navigateur d'effectuer l'action par défaut associée (suivre un lien au clic, par exemple). Mais l'autre conséquence est de stopper la propagation de l'événement, qui ne remontera donc pas, empêchant les écouteurs d'événement des éléments parents d'être déclenchés.
Les fonctions utilisées comme écouteurs d'événements reçoivent un paramètre, qu'on appelle souvent e (comme événement). Ce paramètre a notamment deux méthodes : preventDefault() qui sert à empêcher l'action par défaut du navigateur, et stopPropagation() qui stoppe la propagation de l'événement.
Bref. Tout ça pour dire que si votre intention est d'empêcher le comportement par défaut, alors utilisez preventDefault() et non pas return false. Car peut-être voulez-vous conserver la propagation !
Des exemples pour conclure :
<script type="text/javascript">
jQuery(function($) {
// return false
$('#test1').click(function() {
alert('Test 1 : div');
}).find('a').click(function() {
alert('Test 1 : a');
return false;
});
// preventDefault uniquement
$('#test2').click(function() {
alert('Test 2 : div');
}).find('a').click(function(e) {
e.preventDefault();
alert('Test 2 : a');
});
// preventDefault et stopPropagation
// ( + ou - équivalent à return false, donc.)
$('#test3').click(function() {
alert('Test 3 : div');
}).find('a').click(function(e) {
e.preventDefault();
e.stopPropagation();
alert('Test 3 : a');
});
});
</script>
<div id="test1">Texte du div <a href="http://www.google.fr">Lien</a></div>
<div id="test2">Texte du div <a href="http://www.google.fr">Lien</a></div>
<div id="test3">Texte du div <a href="http://www.google.fr">Lien</a></div>
En conclusion, on peut considérer que return false est rarement utile. preventDefault() et stopPropagation() offrent un meilleur contrôle de l'événement (et bonus : ils peuvent se placer au début de la fonction et donc agir même si la suite du code plante... )
@Golmote: Merci beaucoup de toutes ces précisions.
Je connaissais preventDefault et stopPropagation (du moins je les avait déjà utilisé) mais je n'avais une vue aussi précise de leurs répercussions ni des comparaisons avec l'action du return false.
Pour l'utilisation que j'en fait, je bannis donc le return false (dans la mesure du possible) et me dirige de ce pas vers du code plus propre.
Tant que j'y suis, il m'arrive de rencontrer dans des bouts de code a droite a gauche des onclick="javascript:void(0)", je n'en saisi pas l'utilité et d'instinct ça me parait sale. Si tu as 3 minutes de plus pour eclairer ma lanterne, j'en serais ravi.
Tant que j'y suis, il m'arrive de rencontrer dans des bouts de code a droite a gauche des onclick="javascript:void(0)", je n'en saisi pas l'utilité et d'instinct ça me parait sale. Si tu as 3 minutes de plus pour eclairer ma lanterne, j'en serais ravi.
Je ne suis pas golmote, mais je veux déjà te dire que javascript: est inutile, on ne peut que mettre du javascript dans un onclick (corrigez moi si je me trompe)
Pour void, si j'ai bien compris c'est un opérateur qui renvoi undefined, mais golmote t'expliquera mieux son utilisation que moi ...
En résumé, le code onclick='javascript:void(0)' est inutile (encore une fois corrigez moi si je me trompe) car par défaut, au clic, rien ne se passe ...
Je vous ai aidé ? Appuyez sur le bouton "Ce message est utile", avec le pouce levé vers le haut ! (en bas à gauche de mon message)
crf dit vrai concernant "javascript:". Ce pseudo-protocole n'aurait d'"intérêt" que dans un href (mais c'est bien évidemment à bannir quand même, vous le savez surement...)
Mettre un void(0) dans un onclick, vraiment, je n'en vois pas l'utilité. Desolation, après test, il s'avère que ça ne bloque même pas le comportement par défaut.
A mon avis, c'est plutôt href="javascript:void(0)" que tu as vu. Et ça, c'est une façon très sale de faire des liens qui n'en sont pas, et qui ne remontent pas en haut de page si on clique dessus (contrairement au href="#" qui oblige à stopper le comportement par défaut du navigateur).
Bref, c'est caca, faut pas utiliser, toussa toussa ; vous connaissez la chanson.
crf dit vrai concernant "javascript:". Ce pseudo-protocole n'aurait d'"intérêt" que dans un href (mais c'est bien évidemment à bannir quand même, vous le savez surement...)
Mettre un void(0) dans un onclick, vraiment, je n'en vois pas l'utilité. Desolation, après test, il s'avère que ça ne bloque même pas le comportement par défaut.
A mon avis, c'est plutôt href="javascript:void(0)" que tu as vu. Et ça, c'est une façon très sale de faire des liens qui n'en sont pas, et qui ne remontent pas en haut de page si on clique dessus (contrairement au href="#" qui oblige à stopper le comportement par défaut du navigateur).
Bref, c'est caca, faut pas utiliser, toussa toussa ; vous connaissez la chanson.
mm d'accord.
en fait, moi j'utilisait ce href="javascript:void(0);" juste pour dire de remplir le href de mes lien, sans le #, justement pour que la page ne remonte pas en haut comme tu dis.
Et tu utilise quoi alors pour ne pas que ta page remonte ?
bien vu Golmote, c'etait effectivement href=...
Tu arrives donc meme a corriger mes questions avant d'y repondre
Mon instinct ne me trompais donc pas, c'est deja ça, mais c'est toujours mieux de savoir et comprendre le pourquoi du comment.
Merci beaucoup à vous 3 de ces precisions, je suis ravi !
mm d'accord.
en fait, moi j'utilisait ce href="javascript:void(0);" juste pour dire de remplir le href de mes lien, sans le #, justement pour que la page ne remonte pas en haut comme tu dis.
Et tu utilise quoi alors pour ne pas que ta page remonte ?
Pour moi, il y a... disons 3 situations envisageables.
Tu veux faire un lien qui, quand on clique dessus, ouvre une modal box super sexy avec un formulaire de connexion. Ok, mais tu as certainement une page de connexion (en fallback pour les noJS), alors tu mets l'url de la page de connexion dans le href, et tu empêches le comportement par défaut dans le onclick.
Tu veux faire un lien qui, quand on clique dessus, scroll de manière super sexy jusqu'au footer de ton site. Là, pas de page de fallback. Mais plutôt que de mettre un bête "#" dans ton href, mets-y une ancre correspondant à ton footer. Sémantiquement, c'est mieux. Et tu empêcheras le comportement par défaut pour faire le scroll.
Enfin, tu veux faire un lien qui, quand on clique dessus fais exploser la page en un feu d'artifice super sexy, absolument pas adapté aux noJS. Mais alors pourquoi utiliser un <a> (qui est censé t'emmener quelque part) ? Sémantiquement, cela n'a aucun sens. A la place, tu peux utiliser un <button> par exemple, conçu pour cliquer dessus.
× Après avoir cliqué sur "Répondre" vous serez invité à vous connecter pour que votre message soit publié.
× Attention, ce sujet est très ancien. Le déterrer n'est pas forcément approprié. Nous te conseillons de créer un nouveau sujet pour poser ta question.
Je vous ai aidé ? Appuyez sur le bouton "Ce message est utile", avec le pouce levé vers le haut ! (en bas à gauche de mon message)