Reputation: 43
I'm puzzled about the result of this code. In my opinion, when the content of $("#title")
is "hello" and get a click, it executes function saygoodbye()
and add a new click-event anonymous function. It gets an outer alert. When the content is "goodbye" and get a click, both of these two functions should execute. It should get one outer alert and ONE inner alert.
But in fact, I get one outer alert and TWO inner alerts. Where is the other inner alert from?
var count = 0;
function saygoodbye(){
alert("ok is outer");
$("#title").html("goodbye");
$("#title").click(function() {
alert("ok is inner");
$('#title').html("hello");
$('#title').off("click");
});
}
<script src="//code.jquery.com/jquery-2.1.4.min.js" type="text/javascript"></script>
<h1 id="title" onclick="saygoodbye();">hello</h1>
Upvotes: 3
Views: 445
Reputation: 1248
That is because the event is getting registered from DOM. Register it dynamically, Then It works.
Remove onclick
attribute from markup.
var count = 0;
$('#title').click(saygoodbye);
function saygoodbye(){
alert("ok is outer");
$("#title").html("goodbye");
$("#title").click(function() {
alert("ok is inner");
$('#title').html("hello");
$('#title').off("click");
});
}
<script src="//code.jquery.com/jquery-2.1.4.min.js" type="text/javascript"></script>
<h1 id="title">hello</h1>
Read this SO thread to get an insight as to why to register events on the go (For your case). jQuery.click() vs onClick
EDIT:
First, In order to unbind events which are triggered thru element's attribute we need to use
document.getElementById("title").onclick = null;
Secondly, jQuery's .off() function will only unbind handlers that were added by jQuery's .on()
Documentation at http://api.jquery.com/off/
- "The .off() method removes event handlers that were attached with
.on()
".click()
- is a shorthand methods of.on()
So saygoodbye() doesn't get away, Here is the debugging.
click title.(having title hello)
click title (having title goodbye)
.off()
function works here and kills extra added 2
handlers.Hope this breakdown helps.
Upvotes: 2
Reputation: 413717
When you call .click()
, you're always adding a new handler; previously added handlers are not removed. They'll be removed when you call .off()
, but that doesn't happen until two handlers have already been attached. The library (jQuery that is) maintains lists of handlers and uses it's own internal event handler to actually handle the event from the browser. Thus even though there are only two real "click" events, by the time the jQuery handler is invoked there are two jQuery-registered handlers for the library to call.
In general, adding event handlers inside other event handlers is a questionable way of doing things. It's not exactly wrong, but it adds complexity. Here, on top of that, you're using two separate techniques to register event handlers. The "saygoodbye" function is attached to the DOM element's "onclick" property. The jQuery code, however, uses the DOM API attachEventHandler()
to register handlers. Those two mechanisms are separate. When a "click" happens, the browser will check the "onclick" property first and then call any handlers registered via the API.
Upvotes: 5