2012-02-16 2 views
6

Ho seguito un tutorial di Railscast su backbone.js e volevo estendere la funzionalità per includere il controllo della tastiera. Ho aggiunto il seguente al mio punto di vista spettacolo:In backbone.js come si associa una chiave al documento

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 

Sul mio modello di spettacolo ho il seguente:

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

Se seleziono il link con il tasto tab, poi iniziare a colpire chiavi casuali che ricevo uscita nella mia console javascript. Tuttavia se carico la pagina e non seleziono il collegamento e inizio a premere i tasti non ottengo alcun output nella mia console.

Come si associa l'evento al documento in modo che esso possa ascoltare qualsiasi tasto premuto durante il caricamento dello schermo?

+1

possibile duplicato di [backbone.js: filtro di una raccolta con il valore di un input] (http://stackoverflow.com/questions/9244773/backbone-js-filtering-a-collection-with-the-value- da-a-input) –

+0

è la stessa funzionalità ma dubito che possa essere vista come un duplicato, questa persona chiede in particolare come può aggirare l'ambito di una vista, associare un evento chiave al documento e non a un input singolo. il documento molto probabilmente al di fuori dell'ambito della vista. nel suo esempio si lega semplicemente a "keyup", il che significa che lo sta legando all'elemento contenitore della sua vista, che molto probabilmente non è l'intera pagina. – Sander

risposta

6

È necessario aggirare l'ambito del backbone per le viste. quando si sta facendo qualcosa di simile:

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

si sono vincolanti vostra funzione goBack all'evento keyup rilievo sul vostro elemento contenitore del vostro punto di vista. (Per impostazione predefinita il div in cui la vista è resa)

invece di fare che, se si desidera associare a qualcosa di fuori della vostra vista (che non disponga di un proprio vista! (*))

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; 
    } 

}); 

(*) osservazione come indicato sopra, è meglio farlo solo quando l'elemento che si desidera associare non ha la propria vista, se si dispone di una vista per la pagina intera (una vista app o qualcosa di simile che) si potrebbe legare la chiave di accesso lì, e basta sollevare un evento App.trigger('keypressed', e); per esempio.

è possibile quindi nella vista EntryShow, associare all'evento keypressed di quell'app.

App.bind('keypressed', goBack); 

tenere a mente che si dovrebbe fare qualcosa come un evento di ritardo o di raggruppamento tasti premuti insieme in alcune situazioni, come sparando ogni pressione del tasto che accade nel corpo, potrebbe essere un grande calo di prestazioni. specialmente sui browser più vecchi.

+0

Questo funziona per me sul carico iniziale di una vista. Ma quando l'utente naviga alla vista una seconda volta, l'associazione viene riapplicata e il metodo viene attivato due volte su ciascun evento "keyup". – wuliwong

+0

puoi risolverlo in 2 modi, puoi usare un gestore di visualizzazioni, come la marionetta di backbone (o quella che scrivi tu stesso) e separare l'evento premuto a chiave quando la vista si chiude. Oppure puoi lasciarlo vincolato, ma lavorare con qualche stato elaborato. quando esegui il bind all'evento keypressed lo fai solo una volta, controlla se la classe keypressed process è nel contenitore. se no, legalo ad esso, altrimenti non farlo. (dopo il binding è necessario impostare la classe in modo che la seconda volta che si visita non si leghi di nuovo.) – Sander

4

Gli eventi verranno esaminati per l'elemento di visualizzazione @el. Per catturare gli eventi sul document, si deve rotolare tu stesso:

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

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

dovrebbe fare il trucco.

+1

Questa risposta risolve la rimozione del binding ma 'remove()' non viene chiamato automaticamente, corretto? Hai bisogno di qualcosa che viene chiamato ogni volta che un utente si allontana da una vista. Invece, mi limito a rimuovere tutti i binding precedenti prima di applicarli nella mia vista corrente. È un po 'hacky, ma funziona. – wuliwong

+0

@wuliwong yep Non penso che 'remove()' venga chiamato automaticamente. Qual è l'opposto di 'initialize' che viene chiamato automaticamente quando l'utente si allontana dalla vista? Impossibile trovarne uno nel documento. Qualche soluzione? –