Running into a weird bug – so I have an attribute defined as 'data-tagtype' on my button
elems in my HTML. When a user clicks on a button, the following method gets called:
onClickTag: function(e) {
if (!this.playerLoaded) {
return false;
}
var type = $(e.target).data('tagtype');
var seconds = this.getCurrentTime();
console.log(type);
if (type) {
this.model.addTag({
type: type,
seconds: seconds
});
}
},
This works most of the time, but for some reason sometimes type
is undefined for (seemingly) random elements. The corresponding HTML is here:
<button id="tag-love" class="tagger disabled" data-tagtype="love"><i class="fa fa-heart fa-fw"></i></button>
<button id="tag-important" class="tagger disabled" data-tagtype="important"><i class="fa fa-exclamation fa-fw"></i> Important</button>
<button id="tag-more" class="tagger disabled" data-tagtype="more"><i class="fa fa-ellipsis-h fa-fw"></i> More</button>
<button id="tag-confused" class="tagger disabled" data-tagtype="confused"><i class="fa fa-question fa-fw"></i> Confused</button>
It's weird because there doesn't seem to be a pattern with respect to which ones return undefined when. Sometimes all of them work and sometimes one of them returns undefined for a couple of seconds, but then if I keep clicking it returns the proper value.
The View is definitely rendered/loaded into the DOM before any of these methods get called.
Any ideas? Does Backbone do something maybe?
Running into a weird bug – so I have an attribute defined as 'data-tagtype' on my button
elems in my HTML. When a user clicks on a button, the following method gets called:
onClickTag: function(e) {
if (!this.playerLoaded) {
return false;
}
var type = $(e.target).data('tagtype');
var seconds = this.getCurrentTime();
console.log(type);
if (type) {
this.model.addTag({
type: type,
seconds: seconds
});
}
},
This works most of the time, but for some reason sometimes type
is undefined for (seemingly) random elements. The corresponding HTML is here:
<button id="tag-love" class="tagger disabled" data-tagtype="love"><i class="fa fa-heart fa-fw"></i></button>
<button id="tag-important" class="tagger disabled" data-tagtype="important"><i class="fa fa-exclamation fa-fw"></i> Important</button>
<button id="tag-more" class="tagger disabled" data-tagtype="more"><i class="fa fa-ellipsis-h fa-fw"></i> More</button>
<button id="tag-confused" class="tagger disabled" data-tagtype="confused"><i class="fa fa-question fa-fw"></i> Confused</button>
It's weird because there doesn't seem to be a pattern with respect to which ones return undefined when. Sometimes all of them work and sometimes one of them returns undefined for a couple of seconds, but then if I keep clicking it returns the proper value.
The View is definitely rendered/loaded into the DOM before any of these methods get called.
Any ideas? Does Backbone do something maybe?
Share Improve this question edited Feb 27, 2014 at 22:47 mu is too short 435k71 gold badges859 silver badges818 bronze badges asked Feb 27, 2014 at 20:40 DennisDennis 2333 silver badges12 bronze badges1 Answer
Reset to default 12The problem is that Backbone views use event delegation for their event handling. That means that e.target
will be the the element that is clicked rather than the element that is responding to the event. If you click on the <i>
, e.target
will be that <i>
but if you click on the text, e.target
will be the <button>
; the <i>
doesn't have the data attribute you're looking for but the <button>
does. That means that sometimes $(e.target).data('tagtype')
will be undefined
.
You can see this behavior in a simple example:
<div id="x">
<button type="button" data-tagtype="love"><i>icon</i> text</button>
</div>
and a minimal view:
var V = Backbone.View.extend({
el: '#x',
events: {
'click button': 'clicked'
},
clicked: function(ev) {
console.log(
$(ev.target).data('tagtype'),
$(ev.currentTarget).data('tagtype')
);
}
});
Demo: http://jsfiddle/ambiguous/pe77p/
If you click on <i>icon</i>
, you'll get undefined love
in the console but if you click on the text
, you'll get love love
in the console.
That little demo also contains the solution: use e.currentTarget
instead of e.target
.