Pourquoi mon JavaScript ne fonctionne-t-il pas dans JSFiddle?

114

Je ne peux pas trouver quel est le problème avec ce JSFiddle .

HTML:

<input type="button" value="test" onclick="test()">

JavaScript:

function test(){alert("test");}

Et quand je clique sur le bouton - rien ne s'est passé. La console dit "test non défini"

J'ai lu la documentation JSFiddle - là, il est dit que le code JS est ajouté <head>et le code HTML est ajouté <body>(donc ce code JS est antérieur au html et devrait fonctionner).

Larry Cinabre
la source
La suppression des parenthèses fonctionnerait également dans des circonstances normales sans violon, bien qu'il soit certainement un bon conseil de séparer le plus possible les js du HTML. Je ne m'autorise que le style = "display: none" CSS inline no-no.
Adrian Bartholomew

Réponses:

60

La fonction est définie dans un gestionnaire de charge et est donc dans une portée différente. Comme @ellisbben le note dans les commentaires, vous pouvez résoudre ce problème en le définissant explicitement sur l' windowobjet. Mieux encore, changez-le pour appliquer le gestionnaire à l'objet discrètement: http://jsfiddle.net/pUeue/

$('input[type=button]').click( function() {
   alert("test");   
});

Notez que l'application du gestionnaire de cette façon, au lieu d'être en ligne, maintient votre HTML propre. J'utilise jQuery, mais vous pouvez le faire avec ou sans framework ou en utilisant un framework différent, si vous le souhaitez.

Tvanfosson
la source
@Innuendo - jsFiddle utilise des cadres séparés pour les feuilles de code / html / style. vous auriez besoin de référencer le cadre dans l'appel de fonction, mais il n'y a pas vraiment de moyen facile de le faire puisque le cadre n'a pas de nom. C'est vraiment un problème à cause du fonctionnement de jsfiddle, mais c'est toujours une bonne idée de garder votre javascript complètement séparé.
tvanfosson
5
@ tvanfosson- votre solution fonctionne, mais jsfiddle n'utilise pas de cadres séparés pour afficher le résultat; voir jsfiddle.net/Yazpj/show . La raison pour laquelle cela n'a pas fonctionné au départ est que cela a testété défini à l'intérieur d'une onLoadfonction; l'utilisation window.test = function(){/*...*/}fait fonctionner parfaitement bien.
ellisbben le
@ellisbben - si j'utilise Firebug pour inspecter le DOM, chacun des 4 volets séparés existe dans un iframe séparé.
tvanfosson le
1
Oui, mais si vous examinez l'unique iframe utilisé pour montrer l'exemple, vous verrez qu'il met tout le code dans une seule page qui n'utilise pas de cadres, par conséquent, ces cadres ne peuvent pas casser votre exemple. Ajoutez showà n'importe quelle URL jsfiddle pour voir de quoi je parle: jsfiddle.net/Yazpj/show
ellisbben
100

Si vous ne spécifiez pas le paramètre d'enroulement, la valeur par défaut est "onLoad". Il en résulte que tout JavaScript est encapsulé dans une fonction exécutée après le chargement du résultat. Toutes les variables sont locales à cette fonction donc indisponibles dans la portée globale.

Changez le paramètre d'habillage sur "pas d'enveloppement" et cela fonctionnera:

http://jsfiddle.net/zalun/Yazpj/1/

J'ai basculé le framework sur "No Library" car vous n'en utilisez pas.

zalun
la source
22

Il existe un autre moyen, déclarez votre fonction dans une variable comme celle-ci:

test = function() {
  alert("test");
}

jsFiddle


Détails

EDIT (basé sur les commentaires de @nnnnnn)

@nnnnnn:

pourquoi dire test =(sans var) le réparerait?

Lorsque vous définissez une fonction comme celle-ci:

var test = function(){};

La fonction est définie localement, mais lorsque vous définissez votre fonction sans var:

test = function(){};

testest défini sur l' windowobjet qui se trouve dans la portée de niveau supérieur.

pourquoi ça marche?

Comme @zalun dites:

Si vous ne spécifiez pas le paramètre d'enroulement, la valeur par défaut est "onLoad". Il en résulte que tout JavaScript est encapsulé dans une fonction exécutée après le chargement du résultat. Toutes les variables sont locales à cette fonction donc indisponibles dans la portée globale.

Mais si vous utilisez cette syntaxe:

test = function(){};

Vous avez accès à la fonction testcar elle est définie globalement


Références :

R3tep
la source
2
C'est vraiment l'approche la plus simple, c'est que vous testez juste un petit bout de code dans JSFiddle.
DOK
Mais pourquoi ça marche? Le lien "Plus d'informations" que vous avez fourni n'explique pas que le problème est lié à la portée, ni pourquoi dire test = (sans var) le résoudrait.
nnnnnn
@ R3tep bien votre premier lien qui est: l' alerte jsfiddle.net/R3tep/Yazpj/1406 ne fait rien pour moi. Je suis sur chrome.
Ced du
@ R3tep ouais ça marche avec console.log. Je vais poster une question sur SO car je crois que le fait que je n'ai pas de boîte d'alerte est lié à un autre problème que j'ai avec les iframes.
Ced du
1
@ R3tep Je pense que vous m'avez mal compris mais je ne suis pas sûr. Votre code est / était bon. Il y a un problème avec la façon dont JSFiddle est codé (valeur manquante dans l'attribut sandbox de l'iframe qu'ils utilisent pour afficher le résultat). Cela fait que cela ne fonctionnera pas sur certaines versions de chrome. J'ai envoyé un rapport de problème sur leur github. J'étais tellement intéressé par cela parce que je pensais que le problème que j'avais sur mon site Web était le même, mais non. À votre santé.
Ced
3

Remplacez le paramètre d'habillage dans le panneau Frameworks et extensions par "Pas d'habillage <body>"

Académie
la source
-1

Il n'y a aucun problème avec votre code, il suffit de choisir l'extension onLoad () à droite.

Omjjh
la source
-1
<script> 
function test(){
 alert("test");   
}
</script>

<input type="button" value="test" onclick="test()">
Musulman Munir
la source
-3
Select OnDomready

HTML:

<input id="dButton" type="button" value="test"/>

JavaScript:

addEventListener('load', init, false);

function init()
{
  oInput = document.getElementById('dButton');
  oInput.onclick = test;
}

function test(){
  alert("test");
}
Ivan
la source