2012-01-30 22 views
6

Necesito enlazar dos eventos en mi backbone.js -view para alternar un menú. La idea es que si se hace clic en un botón con el id #toggler aparece el menú y cualquier clic fuera del elemento #menu ocultará el menú.Clics de enlace de eventos con backbone.js y jQuery

Lamentablemente no puedo hacer que esto funcione con el enlace de eventos de la red troncal sin tener el outsideMenuHandler() llamado en cada clic independientemente de si hice clic en el elemento #menu, o no.

¿Qué debo cambiar para que funcione?

Esto es lo que he hecho en Backbone.js, lo que no funciona como es debido:

myView = Backbone.View.extend({ 

    events: { 
     'click #menu': 'insideMenuHandler', 
     'click':  'outsideMenuHandler' 
    } 

    insideMenuHandler: function(e) {}, // Called when clicking #menu 
    outsideMenuHandler: function(e) {} // Called on every click both on and off #menu 

} 

Sólo como referencia, esto es lo que haría usando jQuery solo:

$(document).click(function(event) { 
    if ($(event.target).closest('#menu').get(0) == null) { 
     $("#menu").slideUp(); 
    } 
}); 

Respuesta

14

Hay un par de cosas que debe resolver.

En primer lugar, si sus rendimientos insideMenuHandlerfalse o llamadas e.stopPropogation() entonces su outsideMenuHandler no será llamado por los clics en #menu. Por ejemplo:

http://jsfiddle.net/ambiguous/8GjdS/

Pero eso no es todo el problema. Su outsideMenuHandler solo recibirá clics en su vista; por lo tanto, si alguien hace clic en la página fuera de su vista, no se llamará a su outsideMenuHandler y su menú no se desactivará. Si desea que el menú se apague cuando alguien hace clic fuera de #menu, deberá vincular manualmente al body y desvincularlo manualmente cuando se destruya su vista. Algo como esto:

var myView = Backbone.View.extend({ 
    events: { 
     'click #menu': 'insideMenuHandler' 
    }, 

    initialize: function() { 
     _.bindAll(this, 'insideMenuHandler', 'outsideMenuHandler'); 
    }, 

    render: function() { 
     // Both <body> and <html> for paranoia. 
     $('body, html').on('click', this.outsideMenuHandler); 
     // ... 
     return this; 
    }, 

    remove: function() { 
     // Clean up after ourselves. 
     $('body, html').off('click', this.outsideMenuHandler); 
     // ... 
    }, 

    // ... 
    outsideMenuHandler: function(e) { 
     // ... 
     return false; 
    } 
}); 

y luego asegúrese de quitar correctamente la vista. Por ejemplo:

http://jsfiddle.net/ambiguous/MgkWG/1/

+0

Muchas gracias por su respuesta. ¡Muy apreciado! Una pregunta rápida: según entiendo, permitir que un evento haga clic en 'false' evitará que se produzca un" evento predeterminado ", lo que significa que todos los demás clics se desactivarán cuando' outsideMenuHandler' devuelva 'false'. ¿Me estoy metiendo en problemas si dejo que mi 'outsideMenuHandler' vuelva 'verdadero' después de realizar mi lógica (ocultando mi menú)? – Industrial

+1

@Industrial: terminará con llamadas dobles a 'outsideMenuHandler' del enlace' body, html', pero eso podría no ser un problema. Probablemente pueda salirse con la única vinculación de 'outsideMenuHandler' a' html', pero querría que el navegador lo verifique para asegurarse de que se comporta correctamente en todos los navegadores que le interesan. –

-1

El problema es que vincula su evento al elemento DOM que defina como las vistas el. Entonces, si este no es el window.document como en su ejemplo de jquery, no puede notar ningún clic fuera de ellos. La forma más fácil en su ejemplo sería agregar los eventos manualmente con jquery y no con la red troncal.

Cuestiones relacionadas