Pages :
Bonjour

On lit partout qu'il est préférable d'écrire
<img src="..." alt="" onclick="monscript(...)">

plutôt que
<a href="javascript:monscript(...)"><img src="..." alt=""></a>

ce que je comprend aisément et que j'utilise régulièrement depuis longtemps.

Néanmoins il ne semble pas possible d'éviter les href="javascript:..." dans le cas suivant:

<img src="..." alt="" usemap="#Map" onclick="monscript('tout')">
<map name="Map">
    <area shape="RECT" coords="0,0,345,140"
      href="javascript:monscript('gauche')" data-coords="000,000,345,140">
    <area shape="RECT" coords="427,0,999,199"
       href="javascript:monscript('droite')" data-coords="427,000,999,199">
</map>


A ce propos, l'utilisation de "name" au lieu de "id" dans la définition d'une <map> a l'air également "vieux jeu".
Y a-t-il quelque chose que j'ignore dans ce domaine?
Modifié par PapyJP (09 Mar 2017 - 12:05)
Modérateur
Bonjour,

Mon avis sur la question est que l'on peut même s'affranchir de tout JS en ligne dans le html. Je pense qu'il est tout à fait faisable d'utiliser des classes côté html et de placer une écoute dans le gestionnaire d'évènement.

<img src="..." alt="" usemap="#Map" class="JS-monscript JS-monscript-tout">
<map name="Map">
    <area shape="RECT" coords="0,0,345,140"
      href="" data-coords="000,000,345,140" class="JS-monscript JS-monscript-gauche">
    <area shape="RECT" coords="427,0,999,199"
       href="" data-coords="427,000,999,199" class="JS-monscript JS-monscript-droite">
</map>

Ainsi je place une écoute sur tous les éléments contenant la classe JS-monscript,
Au clique sur l'un d'eux, je récupère la seconde classe qui commence par JS-monscript-.
Je segmente ce string pour obtenir la dernière partie.
Enfin j'exécute monscript() avec comme paramètre le segment récupéré précédemment.

Bien sûr il est faisable de n'utiliser qu'une classe dans le html mais ça me paraît plus clair ainsi pour servir d'exemple.
Salut

Je plussois la réponse de Greg.

Dans une logique de développement orientée MVC il est préférable de bien segmenter le code et l'ajout d'une class spécifique, moi je préfixe en JQ Smiley cligne , ou un ID géré ensuite par le gestionnaire d'événement est plus souple.

Après pour répondre spécifiquement à la question de Papy, peu importe le onclick ou le href, c'est une question de faisabilité en revanche, pour des questions "de sécurité" il vaut mieux un onclick, le href étant visible dans la barre des tache des navigateurs cela informe directeemnt et sans effort de l'action qui va avoir lieu.
Voilà une approche très intéressante.
J'évite cependant d'utiliser le concept de "gestionnaire d'évènement" pour les pages qui sont destinées à un public large, car je ne sais pas comment faire pour avoir un gestionnaire d'évènements qui fonctionne de la même manière avec IE qu'avec les navigateurs standards.
Auriez vous une référence d'un document clair qui explique ce qu'il convient de faire?
Pareil pour moi également : j'écoute les événements sur les classes, les ID, ou les data-*.
Modifié par Olivier C (10 Mar 2017 - 05:52)
Désolé, mais je connais déjà cette page. Je n'y trouve nulle part la moindre mention de ce qu'il convient de faire pour fonctionner de la même façon sur IE et sur les autres navigateurs, ce qui est actuellement ma principale préoccupation. Je ne compte plus le nombre de choses que je ne peux pas utiliser parce que IE ne les supporte pas.
Modifié par PapyJP (09 Mar 2017 - 19:16)
Modérateur
PapyJP a écrit :
Désolé, mais je connais déjà cette page. Je n'y trouve nulle part la moindre mention de ce qu'il convient de faire pour fonctionner de la même façon sur IE et sur les autres navigateurs, ce qui est actuellement ma principale préoccupation.

Et tu l'as lu jusqu'au bout ? Jusqu’à la section "Browser Support" ? Avec cet exemple ci :

var x = document.getElementById("myBtn");
if (x.addEventListener) {                    // For all major browsers, except IE 8 and earlier
    x.addEventListener("click", myFunction);
} else if (x.attachEvent) {                  // For IE 8 and earlier versions
    x.attachEvent("onclick", myFunction);
}


???
Modifié par _laurent (10 Mar 2017 - 01:33)
Honnettement, en 2017 on peu cracher tant qu'on veut sur jQuery, mais quand il s'agit de rendre un js compatible avec de vieux machins il n'y a pas mieux que cette lib' dont la première raison d'être fût de résoudre les problèmes de compatibilité entre browsers.
Modérateur
Salut Olivier,

Olivier C a écrit :
Honnettement, en 2017 on peu cracher tant qu'on veut sur jQuery, mais quand il s'agit de rendre un js compatible avec de vieux machins il n'y a pas mieux que cette lib' dont la première raison d'être fût de résoudre les problèmes de compatibilité entre browsers.


Je ne sais pas trop ce que JQuery vient faire dans le débat du placement des écouteurs d'évènements mais franchement pour des cas comme celui là, se traîner toute une lib pour éviter de faire un "if" c'est un peu overkill non ?! Smiley langue

En plus les compatibilité de JQuery sont :
- Chrome: (Current - 1) and Current
- Edge: (Current - 1) and Current
- Firefox: (Current - 1) and Current
- Internet Explorer: 9+
- Safari: (Current - 1) and Current
- Opera: Current
http://jquery.com/browser-support/

Ce sont exactement les mêmes compatibilités que addEventListener()...

Pour supproter plus vieux avec JQuery il faut se traîner une second version antérieure :
JQuery a écrit :
If you need to support older browsers like Internet Explorer 6-8, Opera 12.1x or Safari 5.1+, use jQuery 1.12.


Bonne journée
Bonjour à tous et merci pour vos réponses

@_laurent
ce qu'il y a en bas de page, c'est comment attacher une fonction à un évènement, mais -- pour autant que je comprenne -- la façon de traiter les évènements n'est pas la même avec IE qu'avec les navigateurs standards, c'est ça qui me préoccupe.
Il doit bien y avoir quelque part un document qui explique comment l'ensemble fonctionne?

A propos de la nécessité de supporter les anciennes versions: il s'agit d'un site sur l'égyptologie, avec des habitués qui se connectent de touts les coins du monde, la plupart sont des gens âgés qui ne renouvellent pas leur matériel ou leur logiciel très souvent. Il ne faudrait pas que la rénovation du site les mette en situation de ne plus pouvoir y accéder.

A propos de jquery: jusqu'à présent, je suis parvenu à éviter d'introduire ce package, et je n'ai franchement pas envie d'ajouter un langage aux 4 que nous utilisons actuellement (HTML, JS, CSS, PHP). Nous ne sommes que 2 à travailler sur ce site, le propriétaire étant un égyptologue qui n'a que des connaissances limitées en techno. Moins il y a de chose à connaître, plus cela lui laisse de possibilité d'agir sur son site sans avoir besoin d'un "expert".
Modérateur
PapyJP a écrit :
la façon de traiter les évènements n'est pas la même avec IE qu'avec les navigateurs standards.

Mmmmmh là j'ai peur de ne pas comprendre.... en quoi la façon de traiter n'est pas la même ? Pour moi c'est juste une question de compatibilité d'une fonction et la solution est là... non ?
@_laurent
C'est sans doute que tu sais comment faire et moi pas.
Chaque fois que je cherche quelque chose sur ce sujet sur Internet, tout ce que je comprends c'est que c'est différent, par exemple comment faire un stopPropagation() sur IE, ou même comment accéder les paramètres "non déclarés" comme "event" ou "this".

Ce que je cherche, et que je n'ai pas (encore) trouvé c'est un document qui me donne un exemple complet. Tout ce que je trouve, c'est la définition de chaque fonction et quelques exemples basiques de son utilisation, mais je n'ai pas de vue cohérente.
C'est la différence entre une documentation, qui décrit chaque fonction indépendamment des autres, et un didacticiel, qui montre sur des exemples un peu moins simplistes que les traditionnels "hello world" comment ça s'utilise.
Coucou Papy Smiley smile ce surnom te va bien (rien de péjoratif) car je retrouve en toi ce côté mal comprenant des anciens Smiley cligne (j'ai 48 ans hein Smiley cligne )

Bref là tu t'embrouille car tu ne vois pas la simplicité de la chose Smiley cligne

Le système d'écoute permet juste de lancer une fonction JS Smiley smile

Si ta fonction est bien faite tu n'as pas spécialement à te préoccuper de la compatibilité.

Concernant l'écoute il n'y a que deux façon d'écouter Smiley smile


var x = document.getElementById("myBtn");
if (x.addEventListener) {                    // For all major browsers, except IE 8 and earlier
    x.addEventListener("click", myFunction);
} else if (x.attachEvent) {                  // For IE 8 and earlier versions
    x.attachEvent("onclick", myFunction);
}


ici x représente l'élément html avec l'id "myBtn"

ensuite si on est dans les browser/navigateur standard
if (x.addEventListener) {

on écoute l'élément sur l'action "click", l'équivalent d'un onclick directement sur le bouton.

sinon si on trouve attachEvent Smiley cligne c'est qu'on est sur IE et là on écoute différemment. Smiley cligne

tu vois c'est simple Smiley smile

PS : les jeunot Smiley cligne faut savoir expliquer et vulgariser pour que les anciens comprennent Smiley cligne
Modérateur
Bonjour PapyJP,

Je ne comprends pas vos craintes quand à placer en écoute vos évènements. En effet, selon vous-même le problème ne se situe aucunement dans votre fonction d'appel. Cela signifie donc qu'elle fonctionne quelque soit la version de IE.

En utilisant le fallback recopié ici même par _laurent, qu'est-ce qui peut représenter une gênes vis à vis de vos utilisateurs ? Vous maintiendriez la compatibilité avec l'ensemble des navigateurs et scinderiez par la même votre code statique de l'exécutif.

S'il était question de coder une nouvelle fonction, bien entendu pour prendre en considération vos remarques sur la compatibilité des différentes fonctions JS (qui par la doc relève du travail de fourmis), s'il devait être mon cas, je coderais ma fonction comme vous le faites actuellement, - c'est-à-dire inline au html - la testerais sur les dinosaures pré-jurassique (nous sommes dans la partie développement du code), puis appliquerais la mise sur écoute de l'évènement pour la partie production en appelant ma fonction - en enlevant bien sur les évènements de mon html.

Ceci ne rendrait-il pas plus lisible le code pour votre comparse égyptologue ?

Maintenant si un cas précis vous semble infaisable, vous avez toujours la possibilité de nous le soumettre et je suis persuadé que l'un d'entre-nous se ferait un plaisir de vous aider à la mise en application.

Bonne journée. Smiley smile
Bon! je vois que je me suis très mal fait comprendre

Premier point: pourquoi Papy? tout simplement parce que je suis un Papy: j'aurai 3/4 de siècles la semaine prochaine et j'ai deux petits enfants, dont un majeur. Et comme de plus ils habitent Strasbourg, ça m'a paru un pseudo approprié pour le site Alsacreations!

Pourquoi je crains pour les utilisateurs de "vieux systèmes"?
Je ne crains rien du tout pour eux, c'est simplement pour expliquer pourquoi je ne peux pas simplement faire du code sans me préoccuper de la compatibilité avec ces "vieux systèmes".

Par ailleurs, je comprends très bien comment marchent les "eventListeners" des navigateurs récents: on définit quelle(s) fonction(s) doi(ven)t être appelée(s) quand un évènement se produit sur un élément donné, ce n'est pas un problème, et j'utilise cette fonctionnalité quand je suis sûr que les utilisateurs sont munis d'un navigateur récent.
Par exemple j'ai fait des outils qui ne sont utilisés que par le propriétaire du site et moi même, et ces outils font largement appel à des gestionnaires d'évènement.

Par contre ce que je n'ai pas bien compris, c'est comment faire des gestionnaires d'évènement qui marchent de la même façon sur IE et sur -- disons -- Chrome ou FireFox.
Il n'y a peut être rien à comprendre, comme vous semblez tous me le dire, mais comme en plus je n'ai pas (plus) de vieil IE sous la main je ne peux même pas tester ça tranquillement, et comme toute ma vie j'ai travaillé dans l'informatique, je sais par expérience qu'un code qu'on n'a pas testé est a priori bogué.

Prenons un exemple très simple, se référant à une question que j'ai récemment posée sur le site et dont je n'ai toujours pas compris les réponses reçues:
J'ai une page qui a -- en gros -- la structure suivante:
<body>
    <figure>
        <img src="...">
        <figcaption>...<figcaption>
    </figure>
</body>

Le CSS est fait de telle sorte que l'image se présente bien centrée sur la page.
Je voudrais ajouter un gestionnaire d'évènements qui fasse que si on clique sur l'image on fasse apparaître une autre image, quand on clique dans <figure> en dehors de l'image il ne se passe rien et quand on clique en dehors de <figure> ça ferme la fenêtre.
Cela passe bien entendu par un gestionnaire d'évènement qui bloque la propagation de l'évènement, car si je ne le fais pas on n'aura pas le temps voir la nouvelle image remplacer la précédente, que la fenêtre sera fermée.
C'est ridicule, mais je ne parviens pas à comprendre comment faire cela de façon à ce que ça marche sous tous les navigateurs.
Pour l'instant, j'en suis donc resté à ne pas fermer la fenêtre quand on clique en dehors de <figure> et à compter sur l'utilisateur pour cliquer non pas n'importe où, mais sur le bouton de fermeture du navigateur.
Ce n'est pas trop gênant sur un ordinateur, mais sur un téléphone ou une tablette c'est une manœuvre plus complexe qu'un simple clic en dehors de l'image.

Je crois que si vous me montrez comment traiter ce problème, je disposerai (enfin!) du "didacticiel" que je cherche.

Merci de votre aide
Modifié par PapyJP (10 Mar 2017 - 15:16)
Modérateur
PapyJP a écrit :
je comprends très bien comment marchent les "eventListeners" des navigateurs récents: on définit quelle(s) fonction(s) doi(ven)t être appelée(s) quand un évènement se produit sur un élément donné, ce n'est pas un problème, et j'utilise cette fonctionnalité quand je suis sûr que les utilisateurs sont munis d'un navigateur récent.
Par exemple j'ai fait des outils qui ne sont utilisés que par le propriétaire du site et moi même, et ces outils font largement appel à des gestionnaires d'évènement.

Cette fonctionnalité marche justement sur TOUT les navigateurs, récent ou non. Le code :
var x = document.getElementById("myBtn");
if (x.addEventListener) {                    // For all major browsers, except IE 8 and earlier
    x.addEventListener("click", myFunction);
} else if (x.attachEvent) {                  // For IE 8 and earlier versions
    x.attachEvent("onclick", myFunction);
}

Lancera la fonction myFunction au clique sur l'élément html portant l'id myBtn et ce quelque soit le navigateur ou sa version, IE8 et moins compris.

PapyJP a écrit :
Par contre ce que je n'ai pas bien compris, c'est comment faire des gestionnaires d'évènement qui marchent de la même façon sur IE et sur -- disons -- Chrome ou FireFox.

C'est donc le cas avec le code proposé.

PapyJP a écrit :
Cela passe bien entendu par un gestionnaire d'évènement qui bloque la propagation de l'évènement,

Ha ! Il est là le nerf de la guerre en fait. Tu souhaites pouvoir faire un stopPropagation qui marche aussi sur IE<9.
D'après ce post là http://stackoverflow.com/questions/17102300/prototype-event-stoppropagation-for-ie-8
on s'en sors avec une petite fonction stopPropagation qui appliquera la bonne méthode selon si le stopPropagation par défaut est supporté ou non :
function stopPropagation(e) {
    if(e.stopPropagation) {
        e.stopPropagation();
    } else {
        e.returnValue = false;
    }    
}


Et donc voila un test avec une image dans 2 div. Ca marche bien sous Chrome, FF et IE11.
https://jsfiddle.net/m9sgbsff/1/

Mais là encore dur dur de tester sur un IE plus vieux pour approuver la théorie...

PapyJP a écrit :
C'est ridicule, mais je ne parviens pas à comprendre comment faire cela de façon à ce que ça marche sous tous les navigateurs.

En regardant la documentation officiel avec la table des navigateurs supportés et en cherchant sur internet une alternative sur comment on faisait avant. Il n'y a pas une seule solution miracle qui marche partout sur tout les navigateur à travers les ages et qui en plus soit une bonne pratique actuelle...

PapyJP a écrit :
Ce n'est pas trop gênant sur un ordinateur, mais sur un téléphone ou une tablette c'est une manœuvre plus complexe qu'un simple clic en dehors de l'image.

La c'est encore une autre soucis un poil différent des vieux navigateurs... mais pareil : doc, compatibilité, test,...

Smiley smile
Salut,
Il faut juste tester le support des différentes implémentations. Dans le code fourni plus haut, la condition
if (x.addEventListener)

vérifie juste que l'élément sur lequel on veut attacher le listener dispose d'une propriété "addEventListener" (et si oui, on sait d'office que cette propriété est la fonction d'ajout d'un listener). Dans le cas contraire, on en déduit qu'on se trouve sur un vieux IE et qu'il faut utiliser la fonction attachEvent.

Pour le reste, ce sera pareil, notamment la propagation, vous ferez dans le listener, dont event est le paramètre :
if(event.stopPropagation) event.stopPropagation();
event.cancelBubble = true;

On teste la présence de la fonction stopPropagation, si elle existe on l'appelle. J'aurais pu mettre le "else", mais taper directement la propriété utilisée par IE ne provoquera pas d'erreur sur les navigateur modernes. Ainsi, tout le monde stoppe la propa quelle que soit la méthode utilisée.

Idem pour le preventDefault (action par défaut, ou événement de l'UA) :
if(event.preventDefault) event.preventDefault();
event.returnValue = false;


Un dernier point, l'utilisation de this dans le listener qui ne fonctionne pas sur les vieux IE. Il faut, lorsque vous utilisez attachEvent, créer un delegate qui fait le bind sur l'objet.


function addEvent(el,ev,listener){ // élément, nom de l'événement sans "on", listener
  if(el.addEventListener){
    el.addEventListener(ev,listener);
  } else {
    el.attachEvent("on"+ev, function(){return listener.apply(el, arguments);});
  }
}

On ne pourra plus supprimer le gestionnaire avec ce code, mais il existe des méthodes pour y parvenir.
Ensuite, pour être exhaustif, il faut décortiquer l'objet event, noter les différences avec les navigateurs modernes, et adapter le code. Bon courage...

Edit : grillé, mais ça se complète Smiley cligne
Modifié par Seven tears (10 Mar 2017 - 16:33)
Meilleure solution
Merci de vos réponses
Comme on le voit très bien dans la réponse de Seven tears, c'est bien pratiquement à chaque moment qu'on doit se poser la question "est-ce que ma f... fonction est supportée par ce f... navigateur?"

Il en résulte un code incompréhensible, le pompon étant tenu par

function addEvent(el,ev,listener){ // élément, nom de l'événement sans "on", listener
  if(el.addEventListener){
    el.addEventListener(ev,listener);
  } else {
    el.attachEvent("on"+ev, function(){return listener.apply(el, arguments);});
  }
}

Je crois que je vais tout simplement écrire un code qui marche uniquement sur les navigateurs modernes et, en testant sur el.addEventListener, laisser les utilisateurs d'antiquités cliquer sur le bouton de fermeture de la fenêtre.
Après tout, c'est surtout gênant pour les utilisateurs de téléphones et tablettes, et autant que je sache il n'y en a pas qui tournent sous les vieilles versions de IE Smiley cligne
Pages :