As an easter egg for a part of one of my sites, I have in my footer #left tag a "Easter" egg that changes each time you click it, revealing funny messages:
$('#left').append(" <span><a href='#' id='dontclick1'>Don't click.</a></span>");
// time for some fun
$('#dontclick1').click(function () {
$('#left span').html("<a href='#' id='dontclick2'>I told you not to click.</a>");
return false;
});
$('#dontclick2').click(function () {
$('#left span').html('<a href="#" id="dontclick3">Now you will suffer.</a>');
return false;
});
$('#dontclick3').click(function () {
$('#left span').html('<a href="#" id="dontclick4">Shame!</a>');
return false;
});
$('#dontclick4').click(function () {
$('#left span').html('<a href="#" id="dontclick5">You shouldn\'t click.</a > ');
return false;
});
$('#dontclick5').click(function () {
$('#left span').html('<a href="#" id="dontclick6">But you did. Sigh.</a>');
return false;
});
In my footer, the append adds the message dynamically so people without JavaScript won't see something unclickable. However, the first time it's clicked, it changes to the second message, but it won't work after that.
What am I doing wrong? Is it because of the return false
inside there? Without it, it jumps to the top of the page. I'm confused.
As an easter egg for a part of one of my sites, I have in my footer #left tag a "Easter" egg that changes each time you click it, revealing funny messages:
$('#left').append(" <span><a href='#' id='dontclick1'>Don't click.</a></span>");
// time for some fun
$('#dontclick1').click(function () {
$('#left span').html("<a href='#' id='dontclick2'>I told you not to click.</a>");
return false;
});
$('#dontclick2').click(function () {
$('#left span').html('<a href="#" id="dontclick3">Now you will suffer.</a>');
return false;
});
$('#dontclick3').click(function () {
$('#left span').html('<a href="#" id="dontclick4">Shame!</a>');
return false;
});
$('#dontclick4').click(function () {
$('#left span').html('<a href="#" id="dontclick5">You shouldn\'t click.</a > ');
return false;
});
$('#dontclick5').click(function () {
$('#left span').html('<a href="#" id="dontclick6">But you did. Sigh.</a>');
return false;
});
In my footer, the append adds the message dynamically so people without JavaScript won't see something unclickable. However, the first time it's clicked, it changes to the second message, but it won't work after that.
What am I doing wrong? Is it because of the return false
inside there? Without it, it jumps to the top of the page. I'm confused.
5 Answers
Reset to default 13Err... that's a pretty horrible way of doing what you want, but you will fix it by replacing all the .click
with .live('click'
- at the time of you appending the events to all the elements, dontclick2
, 3
, etc. do not yet exist. Read up on live for more, or search around this site as this problem es up quite often.
EDIT:
I couldn't resist. While John's answer provides a decent way for doing what you want, I am not a huge fan of mixing the Javascript with the markup like this. Whenever you want to add new funny messages and such you will have to be messing around with Javascript arrays and such which is kind of uncool.
The best way to do this (at least in my humble opinion) would be to have markup like this in your page:
<ul id="easter_messages" style="display: none;">
<li>Don't click</li>
<li>I told you not to click.</li>
<li>Now you will suffer.</li>
<li>Shame!</li>
<li>You shouldn't click.</li>
<li>But you did. Sigh.</li>
</ul>
This would be a semantically correct representation of what you have. You could use CSS like this on it:
#easter_messages ul, #easter_messages li { margin: 0; padding: 0; }
#easter_messages li { cursor: pointer; list-style-type: none; display: inline; }
And finally, use this jQuery code:
$('#easter_messages').show().find('li').hide().click(function() {
var $li = $(this).next('li');
if($li.length == 1) {
$(this).hide();
$li.show();
}
}).filter(':first').show();
This code would essentially show the list, bind a click handler that finds the next list element relative to the one being clicked on, if it finds one it hides itself and shows that one, and then outside the click we show the first one to get things started.
And this is an example of it in action.
You can use live()
as others have mentioned. For an alternative let me suggest a little more elegant solution using an array of messages and a single click
handler.
$('#left').append(" <a href='#' id='dontclick'>Don't click.</a>");
// time for some fun
var messageNumber = 0;
$("#dontclick").click(function() {
var messages = [
"I told you not to click.",
"Now you will suffer.",
"Shame!",
"You shouldn't click.",
"But you did. Sigh."
];
$(this).text(messages[messageNumber]);
// Cycle to the next message unless we're already there.
if (messageNumber < messages.length - 1) {
messageNumber += 1;
}
return false;
});
I've changed it so you just create the <a id='dontclick'>
once, and it doesn't need a number any more. The click
handler is only registered once and each time it's called it displays a different message in the #dontclick
link. The $(this)
in the $(this).text(...)
line, by the way, refers to $("#dontclick")
. It's just a little shorter to write $(this)
.
Because you're setting event hadlers to elements that don't yet exist.
Try
.live("click", function() {
});
instead .click(function() { ...
I'd leave a ment, but I don't have the rep yet, so I'll say it here. :)
.live() is a GREAT way to handle this sort of thing, but it requires jQuery 1.3. If you're stuck in jQuery 1.2.6, the answer as suggested by Daniel Moura is the proper approach. :)
The elements are created after a binding click event. You should bind after the element is created.
$('#dontclick2').click(function () {
$('#left span').html('<a href="#" id="dontclick3">Now you will suffer.</a>');
$('#dontclick3').click(function () {
$('#left span').html('<a href="#" id="dontclick4">Shame!</a>');
return false;
});
return false;
});