116

I can't find out what is the problem with this JSFiddle.

HTML:

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

JavaScript:

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

And when I click on button - nothing happened. The console says "test not defined"

I've read the JSFiddle documentation - there it says that JS code is added to <head> and HTML code is added to <body> (so this JS code is earlier than html and should work).

TylerH
  • 20,799
  • 66
  • 75
  • 101
Larry Foobar
  • 11,092
  • 15
  • 56
  • 89
  • Removing the parentheses would also work under normal non fiddle circumstances though it is definitely good advice to separate js from HTML as much as possible. I only allow myself the style =" display:none" CSS inline no-no. – Adrian Bartholomew Dec 11 '12 at 19:45
  • related: [JavaScript not running on jsfiddle.net](http://stackoverflow.com/questions/5468350/javascript-not-running-on-jsfiddle-net) – Bergi Mar 11 '13 at 16:06
  • If you’re looking for the _opposite_ problem — i.e. the code works in JSFiddle, but not locally — see [Using document.getElementById() inside object, works in JSFiddle, TypeError in actual. Why?](/q/15572630/4642212). Both behaviors have the same cause: JSFiddle automatically wraps JS code in a function that is executed as soon as the DOM is ready, which also causes `onclick` to be out of scope. – Sebastian Simon Dec 03 '22 at 23:10

7 Answers7

101

If you do not specify the wrap setting it defaults to "onLoad". This results with all JavaScript being wrapped in a function run after result has been loaded. All variables are local to this function thus unavailable in the global scope.

Change the wrapping setting to "no wrap" and it'll work:

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

I switched the framework to "No Library" as you don't use any.

zalun
  • 4,619
  • 5
  • 31
  • 33
60

The function is being defined inside a load handler and thus is in a different scope. As @ellisbben notes in the comments, you can fix this by explicitly defining it on the window object. Better, yet, change it to apply the handler to the object unobtrusively: http://jsfiddle.net/pUeue/

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

Note applying the handler this way, instead of inline, keeps your HTML clean. I'm using jQuery, but you could do it with or without a framework or using a different framework, if you like.

tvanfosson
  • 524,688
  • 99
  • 697
  • 795
  • @Innuendo - jsFiddle uses separate frames for code/html/style sheets. you'd need to reference the frame in the function call, but there isn't really an easy way to do that since the frame doesn't have a name. It's really a problem because of the way jsfiddle works, but it's still a good idea to keep your javascript completely separate. – tvanfosson Mar 25 '11 at 13:31
  • 5
    @tvanfosson- your solution works, but jsfiddle doesn't use separate frames to show the result; see http://jsfiddle.net/Yazpj/show/. The reason it didn't work initially is that `test` was defined inside of an `onLoad` function; using `window.test = function(){/*...*/}` makes it work perfectly well. – ellisbben Sep 02 '11 at 15:18
  • @ellisbben - if I use Firebug to inspect the DOM, each of the 4 separate panes exists in a separate iframe. – tvanfosson Sep 02 '11 at 15:31
  • 1
    Yes, but if you examine the single iframe used to show the example, you'll see that it puts all of the code in a single page that does not use frames, hence those frames cannot break your example. Append `show` to any jsfiddle URL to see what I'm talking about: jsfiddle.net/Yazpj/show – ellisbben Sep 02 '11 at 15:41
22

There is another way, declare your function into a variable like this :

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

jsFiddle


Details

EDIT (based on the comments of @nnnnnn)

@nnnnnn :

why saying test = (without var) would fix it ?

When you define a function like this :

var test = function(){};

The function is defined locally, but when you define your function without var :

test = function(){};

test is defined on the window object which is at the top level scope.

why does this work?

Like @zalun say :

If you do not specify the wrap setting it defaults to "onLoad". This results with all JavaScript being wrapped in a function run after result has been loaded. All variables are local to this function thus unavailable in the global scope.

But if you use this syntax :

test = function(){};

You have an access to the function test because it's defined globally


References :

Community
  • 1
  • 1
R3tep
  • 12,512
  • 10
  • 48
  • 75
  • 2
    This is really the simplest approach is you're just testing a tiny bit of code in JSFiddle. – DOK Mar 29 '14 at 00:18
  • But *why* does this work? The "More information" link you provided doesn't explain that the problem is related to scope, or why saying `test = ` (without `var`) would fix it. – nnnnnn May 20 '15 at 22:30
  • @R3tep well your first link which is : http://jsfiddle.net/R3tep/Yazpj/1406/ alert doesn't do anything for me. I'm on chrome. – Ced Sep 11 '15 at 14:11
  • @R3tep yeah it works with console.log. I'll post a question on SO because I believe the fact that I've no alert box is linked to another problem I've with iframes. – Ced Sep 11 '15 at 14:26
  • @R3tep For info I found out why it doesn't work. Your chrome isn't updated so you might get the problem too in the future when you update. I added allow-modals to the sandbox and it made it work. Keep it in the back of your mind if you happen to have the same problem than me. Cheers. – Ced Sep 12 '15 at 01:25
  • 1
    @R3tep I think you misunderstood me but I'm not sure. Your code is/was good. There is an issue with how JSFiddle is coded (missing value in sandbox attribute of the iframe they are using to display the result). That makes it such it won't work on some version of chrome. I sent an issue report on their github. I was that much interested in it because I thought the issue I'm having on my website was the same but no. Cheers. – Ced Sep 12 '15 at 22:55
3

Change wrap setting in the Frameworks & Extensions panel, to "No wrap-in <body>"

Sebastian Simon
  • 18,263
  • 7
  • 55
  • 75
Academia
  • 3,984
  • 6
  • 32
  • 49
-1

There is no problem with your code.Just choose the extension onLoad() from right side.

Omjjh
  • 17
  • 3
-1
<script> 
function test(){
 alert("test");   
}
</script>

<input type="button" value="test" onclick="test()">
-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");
}
Anders
  • 8,307
  • 9
  • 56
  • 88
Ivan
  • 1
  • 3