Utiliser un bouton HTML pour appeler une fonction JavaScript

229

J'essaie d'utiliser un bouton HTML pour appeler une fonction JavaScript.

Voici le code:

<input type="button" value="Capacity Chart" onclick="CapacityChart();">

Cela ne semble cependant pas fonctionner correctement. Y a-t-il une meilleure manière de faire cela?

Voici le lien: http://projectpath.ideapeoplesite.com/bendel/toolscalculators.html cliquez sur l'onglet capacité en bas à gauche. Le bouton doit générer une alerte si les valeurs ne sont pas modifiées et doit produire un graphique si vous entrez des valeurs.

forêt
la source
6
veuillez définir "ne semble pas fonctionner correctement". Quelle (s) erreur (s) obtenez-vous lorsque vous cliquez dessus?
juste quelqu'un
Le bouton fonctionne dans IE8, mais pas FF 3.5 en raison d'une erreur JavaScript (voir la réponse de Jeff)
Chris Shouts
1
Ouais, il s'avère que document.all est une chose IE non standard; mis à jour ma réponse avec une alternative suggérée.
Jeff
@ paper1337, @Jeff: La fonction n'obtient toujours pas l'effet souhaité dans IE8, donc même le remplacement de document.all par document.getElementById ne le corrigera pas.
Andy E

Réponses:

356

Il existe plusieurs façons de gérer les événements avec HTML / DOM. Il n'y a pas vraiment de bonne ou de mauvaise façon, mais différentes manières sont utiles dans différentes situations.

1: Il est défini dans le HTML:

<input id="clickMe" type="button" value="clickme" onclick="doFunction();" />

2: Il est ajouté à la propriété DOM pour l'événement en Javascript:

//- Using a function pointer:
document.getElementById("clickMe").onclick = doFunction;

//- Using an anonymous function:
document.getElementById("clickMe").onclick = function () { alert('hello!'); };

3: Et il y a attacher une fonction au gestionnaire d'événements en utilisant Javascript:

var el = document.getElementById("clickMe");
if (el.addEventListener)
    el.addEventListener("click", doFunction, false);
else if (el.attachEvent)
    el.attachEvent('onclick', doFunction);

Les deuxième et troisième méthodes autorisent les fonctions inline / anonymes et les deux doivent être déclarées après que l'élément a été analysé à partir du document. La première méthode n'est pas XHTML valide car l'attribut onclick n'est pas dans la spécification XHTML.

Les 1ère et 2e méthodes s'excluent mutuellement, ce qui signifie que l'utilisation de l'une (la 2e) prévaudra sur l'autre (la 1re). La 3ème méthode vous permettra d'attacher autant de fonctions que vous le souhaitez au même gestionnaire d'événements, même si la 1ère ou la 2ème méthode a également été utilisée.

Très probablement, le problème se situe quelque part dans votre CapacityChart()fonction. Après avoir visité votre lien et exécuté votre script, la fonction CapacityChart () s'exécute et les deux fenêtres contextuelles sont ouvertes (une est fermée selon le script). Où vous avez la ligne suivante:

CapacityWindow.document.write(s);

Essayez plutôt ce qui suit:

CapacityWindow.document.open("text/html");
CapacityWindow.document.write(s);
CapacityWindow.document.close();

EDIT
Lorsque j'ai vu votre code, je pensais que vous l'écriviez spécifiquement pour IE. Comme d'autres l'ont mentionné, vous devrez remplacer les références à document.allpar document.getElementById. Cependant, vous aurez toujours la tâche de corriger le script après cela, donc je recommanderais de le faire fonctionner au moins dans IE d'abord, car toute erreur que vous commettez en changeant le code pour fonctionner entre les navigateurs pourrait causer encore plus de confusion. Une fois qu'il fonctionne dans IE, il sera plus facile de dire s'il fonctionne dans d'autres navigateurs pendant que vous mettez à jour le code.

Andy E
la source
7
En utilisant jquery, il y a aussi: $("#clickMe").bind('click', function () { alert('hello!'); };)
Roman
32

Je dirais qu'il serait préférable d'ajouter le javascript de manière discrète ...

si vous utilisez jQuery, vous pourriez faire quelque chose comme:

<script>
  $(document).ready(function(){
    $('#MyButton').click(function(){
       CapacityChart();
    });
  });
</script>

<input type="button" value="Capacity Chart" id="MyButton" >
Paul
la source
4
D'accord. Dans de nombreux cas, jQuery et d'autres cadres sont excessifs pour de petites quantités de javascript et tous les codes javascript n'ont pas besoin d'être multi-navigateurs.
Andy E
2
Assez juste .. le point que j'essayais de faire était "une meilleure façon de le faire" est discrètement ... Sans jQuery, quelque chose comme: var btn = document.getElementById ('MyButton'); btn.onclick = function () {CapacityChart ();}
Paul
1
Ces personnes qui utilisent jQuery semblent être déterminées à l'utiliser pour tout ce qui concerne le Web. Que diriez-vous d'utiliser un JavaScript plat pour un? Mon Dieu, jQuery me met vraiment en colère maintenant. LOL! Je vais appeler ça la façon de l'homme paresseux de créer du Web, car je suppose que c'est tout ce que c'est vraiment.
DoctorLouie
@DrLouie: Je n'ai rien du tout contre jQuery, c'est une bonne solution à de nombreux problèmes, mais quand il n'est pas balisé ou demandé par l'OP, toute mention de jQuery devrait également être assistée par une méthode non jQuery, sinon ils courent le risque de a) confondre le demandeur - il pourrait ne pas savoir ce qu'est jQuery ou b) ennuyer le demandeur en lui disant d'utiliser jQuery pour quelques lignes de code javascript. @Paul - Je dois dire que ce n'était pas une bonne lecture ...
Andy E
1
excuses ... mauvais lien posté - destiné à publier un stackoverflow. stackoverflow.com/questions/1588374/…
Paul
8

Votre code HTML et la façon dont vous appelez la fonction à partir du bouton semblent corrects.

Le problème semble être dans la CapacityCountfonction. Je reçois cette erreur dans ma console sur Firefox 3.5: "document.all is undefined" sur la ligne 759 de bendelcorp.js.

Éditer:

On dirait que document.allc'est une chose uniquement IE et est un moyen non standard d'accéder au DOM. Si vous utilisez document.getElementById(), cela devrait probablement fonctionner. Exemple: document.getElementById("RUnits").valueau lieu dedocument.all.Capacity.RUnits.value

Jeff
la source
Ce n'est pas spécifiquement le problème avec la fonction, qui ne génère aucune erreur dans IE
Andy E
4

Cela semble correct. Je suppose que vous avez défini votre fonction avec un nom différent ou dans un contexte qui n'est pas visible pour le bouton. Veuillez ajouter du code

gigue
la source
3

Juste pour que vous le sachiez, le point-virgule ( ; ) n'est pas censé être là dans le bouton lorsque vous appelez la fonction.

Il devrait donc ressembler à ceci: onclick="CapacityChart()"

alors tout devrait fonctionner :)

jacki
la source
2

Un problème majeur que vous avez est que vous utilisez le sniffing du navigateur sans raison valable:

if(navigator.appName == 'Netscape')
    {
      vesdiameter  = document.forms['Volume'].elements['VesDiameter'].value;
      // more stuff snipped
    }
    else
    {
      vesdiameter  = eval(document.all.Volume.VesDiameter.value);
      // more stuff snipped
    }

Je suis sur Chrome, donc ça navigator.appNamene le sera pas Netscape. Chrome est-il compatible document.all? Peut-être, mais encore une fois peut-être pas. Et les autres navigateurs?

La version du code sur la Netscapebranche devrait fonctionner sur n'importe quel navigateur dès le retour à Netscape Navigator 2 à partir de 1996, donc vous devriez probablement vous en tenir à cela ... sauf que cela ne fonctionnera pas (ou n'est pas garanti de fonctionner) ) car vous n'avez pas spécifié d' nameattribut sur les inputéléments, ils ne seront donc pas ajoutés au elementstableau du formulaire en tant qu'éléments nommés:

<input type="text" id="VesDiameter" value="0" size="10" onKeyUp="CalcVolume();">

Soit leur donner un nom et utiliser le elementstableau, soit (mieux) utiliser

var vesdiameter = document.getElementById("VesDiameter").value;

qui fonctionnera sur tous les navigateurs modernes - pas de branchement nécessaire. Juste pour être sûr, remplacez ce reniflement pour une version de navigateur supérieure ou égale à 4 par une vérification de getElementByIdprise en charge:

if (document.getElementById) { // NB: no brackets; we're testing for existence of the method, not executing it
    // do stuff...
}

Vous souhaitez probablement également valider votre entrée; quelque chose comme

var vesdiameter = parseFloat(document.getElementById("VesDiameter").value);
if (isNaN(vesdiameter)) {
    alert("Diameter should be numeric");
    return;
}

aiderait.

NickFitz
la source
Salut NickFitz, l'un de mes défis ici est que ce script a été écrit à l'origine en 1993 - d'où les références à Netscape 4. J'ai eu de l'aide pour le mettre à jour et cela a fonctionné jusqu'à ce qu'il soit inséré dans sa page désignée.
forrest
Je doute qu'il ait été écrit en 1993, car Brendan Eich n'a inventé le JS qu'en 1995 fr.wikipedia.org/wiki/Javascript#History ;-) Je recommande fortement d'utiliser document.getElementByIdet de supprimer les autres éléments.
NickFitz
Je pense qu'il serait prudent de le faire fonctionner dans IE avant de travailler sur la compatibilité du navigateur, sinon il ne saura pas si ses problèmes de compatibilité de navigateur seront corrigés car cela ne fonctionnera toujours pas.
Andy E
Mieux vaut le faire fonctionner en utilisant des techniques DOM standard, alors il n'y aura pas de problèmes de compatibilité de navigateur à
proprement
2

Votre code échoue sur cette ligne:

var RUnits = Math.abs(document.all.Capacity.RUnits.value);

J'ai essayé de le faire avec Firebug et ça échoue. cela devrait vous aider à comprendre le problème.

vous avez référencé jquery. vous pourriez aussi bien l'utiliser dans toutes ces fonctions. cela nettoiera considérablement votre code.

Patricia
la source
Cependant, il n'échoue pas dans IE sur cette ligne.
Andy E
parce que document.all est une chose IE. il devrait juste utiliser $ ('# RUints'). val () notation jquery b / c il inclut déjà jquery. cela prend en charge toutes les différences de navigateur et nettoie le code.
Patricia
2

J'ai un code de bouton de rappel de fonction intelligent:

<br>
<p id="demo"></p><h2>Intelligent Button:</h2><i>Note: Try pressing a key after clicking.</i><br>
<button id="button" shiftKey="getElementById('button').innerHTML=('You're pressing shift, aren't you?')" onscroll="getElementById('button').innerHTML=('Don't Leave me!')" onkeydown="getElementById('button').innerHTML=('Why are you pressing keys?')" onmouseout="getElementById('button').innerHTML=('Whatever, it is gone.. maybe')" onmouseover="getElementById('button').innerHTML=('Something Is Hovering Over Me.. again')" onclick="getElementById('button').innerHTML=('I was clicked, I think')">Ahhhh</button>
textmonster404
la source
1

RÉPONSE SIMPLE:

   onclick="functionName(ID.value);

Où ID est l'ID du champ de saisie.

AGrush
la source
-2

façon stupide:

onclick="javascript:CapacityChart();"

Vous devriez lire sur le javascript discret et utiliser une méthode de liaison de frameworks pour lier les rappels aux événements dom.

erenon
la source
@erenon: Oh allez. Ce n'est pas son problème, la notation est parfaitement fine, et il n'y a aucune raison d'entrer dans des liaisons et des cadres compliqués juste pour assigner un événement onclick.
Pekka
Merci d'être venu à ma défense Pekka. Je veux juste qu'un simple bouton fonctionne correctement.
forrest
3
Le javascript:protocole n'est pas nécessaire dans l' onclickévénement. L'événement onclick est déjà javascript. Le javascript:protocole sert à exécuter javascript dans l'attribut href d'un lien.
Web_Designer