Search code examples
javascriptbackbone.jsbackbone-events

Backbone event doesn't always happen on `el`


I'm working on my own version of a Backbone TodoMVC App. Here's my code so far.


The Backbone events hash allows us to attach event listeners to either el-relative custom selectors, or directly to el if no selector is provided. An event takes the form of a key-value pair 'eventName selector': 'callbackFunction' and a number of DOM event-types are supported, including click, submit, mouseover, dblclick and more.

http://addyosmani.github.io/backbone-fundamentals/

'dblclick': 'showEdit' doesn't seem to be happening on el for me.

When I double click somewhere in the inner .view-mode div, $(e.target) is that .view-mode div.

clicking on .view-mode

But when I click outside of .view-mode but inside of the li, $(e.taret) is what it should be.

clicking outside of .view-mode but inside of the li

Why is this?


Code:

todo.js

var app = app || {};

app.TodoView = Backbone.View.extend({
  tagName: 'li',

  className: 'list-group-item',

  template: _.template( $('#todo-template').html() ),

  render: function() {
    this.$el.html( this.template(this.model.toJSON()) );
    this.$el.find('.edit-mode').hide();
    this.$el.find('.remove-todo').hide();
    return this;
  },

  events: {
    'click input[type="checkbox"]': 'check',
    'mouseenter': 'showRemove',
    'mouseleave': 'hideRemove',
    'click .remove-todo': 'remove',
    'dblclick': 'makeEditable'
  },

  check: function(e) {
    var id = $(e.target).data('id');
    var model = app.todos.get(id);
    model.save({
      completed: true
    });
  },

  showRemove: function(e) {
    $(e.target).find('.remove-todo').show();
  },

  hideRemove: function(e) {
    $(e.target).find('.remove-todo').hide();
  },

  remove: function(e) {
    var $el = $(e.target);
    var id = $(e.target).data('id');
    var model = app.todos.get(id);
    model.destroy({
      success: function(model) {
        app.todos.remove(model);
        $el.closest('li').remove();
      },
      error: function() {
        alert('Unable to remove todo.');
      }
    });
  },

  makeEditable: function(e) {
    console.log($(e.target).html());
    $(e.target).find('.view-mode').hide();
    $(e.target).find('.edit-mode').show();
  }
});

todo template

<script type='text/template' id='todo-template'>
  <div class='view-mode'>
    <input 
      type='checkbox'
      data-id='<%= id %>'
      <% if (completed) { %>checked<% } %>
    >
    <%= title %>
    <a data-bypass class='remove-todo' data-id='<%= id %>'>&times;</a>
  </div>
  <div class='edit-mode'>
    <p>Edit Mode</p>
  </div>
</script>

Solution

  • e.target refers to the node on which the event occurred. Event propagation means this may be descendent of the node that your handler is attached to.

    To get the node that the event handler is attached to, use e.currentTarget.

    See Event.currentTarget on MDN.