Pergunta

I've been following along with a Railscast tutorial of backbone.js and I wanted to extend the functionality to include keyboard control. I added the following to my show view:

class Raffler.Views.EntryShow extends Backbone.View
  template: JST['entries/show']

  events:
    'click .back': 'showListing'
    'keyup': 'goBack'

  showListing: ->
    Backbone.history.navigate("/", trigger: true)

  goBack: (e) ->
    console.log e.type, e.keyCode

  render: ->
    $(@el).html(@template(entry: @model))
    this

On my show template I have the following:

<a href="#" class="back">Back</a>
<%= @entry.get('name') %></td>

If I select the back link using the tab key, then start hitting random keys I get output in my javascript console. However if I load the page and do not select the link and just start hitting keys I get no output in my console.

How do I bind the event to the document so that it will listen to any keys pressed when loading the screen?

Foi útil?

Solução

You will need to work around backbone's scope for views. when you are doing something like this:

  events:
    'click .back': 'showListing'
    'keyup': 'goBack'

you are binding your goBack function to the keyup event raised on your container element of your view. (by default the div in which the view is rendered)

instead of doing that, if you want to bind to something outside your view (which doesn't have it's own view!(*))

Raffler.Views.EntryShow = Backbone.View.extend({
  template: JST['entries/show'],

  events: {
    'click .back': 'showListing'
  },

  initialize: function () {
    $('body').keyup(this.goBack);
  },

  showListing: function () {
    Backbone.history.navigate("/", trigger: true);
  },

  goBack: function (e) {
    console.log e.type, e.keyCode;
  },

  render: function () {
    $(this.el).html(this.template(entry: @model));
    return this;
  }

});

(*)remark as marked above, you best do this only when the item you want to bind to does not have it's own view, if you have a view for your full page (an app view or something like that) you could bind the keyup in there, and just raise an event App.trigger('keypressed', e); for example.

you can then in your EntryShow view, bind to that App's keypressed event.

App.bind('keypressed', goBack);

keep in mind that you should do something as a delayed event or grouping keypresses together in some situations, as firing every keypress that happens in the body, might be a big performance hit. especially on older browsers.

Outras dicas

Your events will be scoped to your view element @el. To capture events on the document, you have to roll that yourself:

initialize: ->
  $(document).on "keyup", @goBack

remove: ->
  $(document).off "keyup", @goBack

Should do the trick.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top