views:

52

answers:

4

Can someone tell me why the following is not working?

<head>
<script language="javascript" src="/assets/js/jquery-1.3.2.js"></script>
<script type="text/javascript">
$("button").bind("click", function() {
    alert("You clicked " + $(this).attr("id"));
});
</script>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>Untitled Document</title>
</head>

<body>
<button id="button1">Click Me!</button>&nbsp;<button id="button2">Click Me!</button>&nbsp;<button id="button3">Click Me!</button>&nbsp;<button id="button4">Click Me!</button>&nbsp;<button id="button5">Click Me!</button>
</body>

Nothing is happening when I click on any of the buttons.

Dave

+1  A: 

You need to bind the click handler when the DOM is ready:

$(function() {
    $("button").bind("click", function() {
        alert("You clicked " + $(this).attr("id"));
    });
});
Darin Dimitrov
This is unrelated to the question.
Alex Sexton
Why wouldn't it be?
Darin Dimitrov
Is it just me or is this answer identical to Alex's? The only difference is `$(document).ready(function(){` and `$(function(){` But they both do the **exact same thing**.
brianpeiris
Yes, both do absolutely the same thing.
Darin Dimitrov
At the time I made that comment, the code block was different. Now this is correct (after an edit), it uses the shortcut document ready function.
Alex Sexton
+5  A: 

Try:

 $(document).ready(function() {
    $("button").bind("click", function() {
       alert("You clicked " + $(this).attr("id"));
    });
 });

Edit: As stated by Alex Sexton, the use of live instead of bind is also preferable when you have to apply the same function to more than 2 elements of the same type.
Follow the link for more infos, credits to him.

Alex Bagnolini
Yea, this gets at the heart of the problem. The document is not ready. Another solution would be to simply put the block of javascript at the bottom of the page instead of the top.
Alex Sexton
A: 

Because your javasript code is executed before html body is loaded. You should call your JS after html is fully loaded. You can do it so:

$(function() { // it's called when document loads
    $("button").bind("click", function() {
        alert("You clicked " + $(this).attr("id"));
    });
});

But it's good practice not to inject your code into global scope. You can do it so:

(function() { // it helps you not to inject your code into global scope
    $(function() { // it's called when document loads
        $("button").bind("click", function() {
            alert("You clicked " + $(this).attr("id"));
        });
    });
})();
giolekva
Your first code block does not inject anything into the global scope, so your second code block is redundant
brianpeiris
You are right in this situation, but for more complicated situations where it's needed global variables and so on it's better practice to create your own scope and write code inside it. I think using such approach even is such cases is better.
giolekva
I'd have to disagree with you giolekva. The only way you would leak inside of the function prior to wrapping it with another function is by declaring a global variable. Wrapping it in a function wouldn't help you, no matter how many times you do it.
Alex Sexton
I'm not JS geek and maybe you're right, but I've learnt it from one of the speeches by John Resig who's author of jQuery.
giolekva
+1  A: 

Another solution would be to use event delegation, so it doesn't matter that the buttons don't exist yet.

$("button").live("click", function() {
    alert("You clicked " + $(this).attr("id"));
});
Alex Sexton
This has the added benefit of performing better in situations where there are multiple buttons (according to http://paulirish.com/perf/ any more than 3 elements with the same handler would have improved speed with $.live).
Alex Sexton