Question

I have a view I am able to load. However the events do not fire. Here is the view:

MapModalView = Backbone.View.extend({
events: {
    'click #closeMapModal': 'closeModal',
    'click #modal_streetview': 'renderStreet'
},
initialize: function(){
    this.el = $('.modal_box');
    this.template = _.template($('#map-modal-template').html());
    _.bindAll(this, 'renderMap', 'renderPin');
},

render: function(){
    $(this.el).show().append(this.template({
        model: this.model
    }));
    this.renderMap();
    this.renderPin();
},
renderMap: function(){
    this.thisLat = _this.model.get('lat');
    this.thisLng = _this.model.get('lng');
    this.modalMap = new google.maps.Map(document.getElementById('modalMap'), {
        zoom : 12,
        center : new google.maps.LatLng(this.thisLat, this.thisLng), // VANCOUVER
        mapTypeId : google.maps.MapTypeId.ROADMAP
    });
},
renderPin: function(){
    marker = new google.maps.Marker({
        position : new google.maps.LatLng(this.thisLat, this.thisLng),
        map : this.modalMap,
        animation : google.maps.Animation.DROP,
        icon : '/img/lazy-pin.png'
    });        
},
renderStreet: function(e){
    e.preventDefault();
    this.modalMap.getStreetView().setPosition(this.modalMap.center);
    this.modalMap.getStreetView().setVisible(true);
},
closeModal: function(e){
    alert('hello');
    e.preventDefault();
    $(this.el).hide().find('div').remove();
}

})

I removed one of the event functions because it wasn't important. Anyways, this view is initialized in my router:

    this.mapModalView = new MapModalView();

And I have a tooltip view, which has an event inside of it, that calls the render function from ModalMapView. Here is that View:

ToolTipView = Backbone.View.extend({
initialize: function() {
    this.template = _.template($('#toolTip').html());
    this.mapTemplate = _.template($('#map-modal-template').html());
    this.model.bind('change:tooltip', this.toggleTooltip, this);
    return this;
},

events: {
    'mouseenter': 'toolTipOn',
    'mouseleave': 'toolTipOff',
    'click #show-restaurant-map': 'mapModal'
},

mapModal: function(){
    router.mapModalView.render(this.model);
},

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

}

});

I removed the functions that I didnt think would be important again above.

Also, here is my template:

<script type="text/template" id="map-modal-template">
<div id="map_modal">
    <button title="Close" id="closeMapModal" class="right">Close</button>
    <h3>Restaurant Map &amp; Access Information</h3>
    <ul>
        <li><a href="#" title="Map View" id="modal_mapview">Map</a></li>
        <li><a href="#" title="Street View" id="modal_streetview">Street View</a></li>
        <li><a href="#" title="Parking &amp; Access Info" id="modal_parking">Parking &amp; Access Info</a></li>
    </ul>
    <div id="modalMap"></div>
</div>
</script>

and of course, my HTML markup on the page I am working on:

<div class="modal_box"></div>
Was it helpful?

Solution

Try this:

render: function() {
    $(this.el).show().append(this.template({
        model: this.model
    }));
    this.renderMap();
    this.renderPin();
    this.delegateEvents();
},

OTHER TIPS

I don't see any _this defined anywhere so I would expect everything to stop running as soon as you call renderMap and that would prevent your events from doing anything.

I do see this:

MapModalView = Backbone.View.extend({
    //...
    _this: this,

but that doesn't create a _this in the object's scope, that just creates a default this._this for your view instances; furthermore, when MapModalView is being built, this will probably be window so all you're doing is giving each MapModalView an reference to window in this._this.

I think all your _this references should be this and perhaps you want to add:

_.bindAll(this, 'renderMap, 'renderPin');

to MapModalView's initialize method to make sure those two always have the right this when you call them.


And now for the underlying problem now that we have mostly functional code.

Backbone views have an el:

All views have a DOM element at all times (the el property), whether they've already been inserted into the page or not.

and they have an $el:

A cached jQuery (or Zepto) object for the view's element.

The delegateEvents method operators on this.$el. You don't specify an el (or id, tagName, ...) as part of your view's definition so Backbone initializes your el to an empty <div> and then initializes this.$el = $(this.el). Your constructor changes this.el:

this.el = $('.modal_box');

but you don't do anything with this.$el so it still refers to the empty <div>. Remember that delegateEvents uses this.$el and that's not pointing at anything useful so your events don't get bound to anything in the DOM.

If you insist on setting this.el inside your initialize, then you'll have to set this.$el as well:

initialize: function() {
    this.el  = '.modal_box';
    this.$el = $(this.el);
    //...

Demo: http://jsfiddle.net/ambiguous/D996h/

Or you could use setElement() to set el and $el for you.

The usual approach is to set el as part of the view's definition:

MapModalView = Backbone.View.extend({
    el: '.modal_box',
    //...

Demo: http://jsfiddle.net/ambiguous/NasSN/

Or you can pass the el to the view when you instantiate it:

m = new MapModalView({el: '.modal_box'});
m.render();

Demo: http://jsfiddle.net/ambiguous/9rsdC/

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top