4

Sorry bout all the code :S

The mouseenter/mouseleave binding on the element in HomeIconView continually keeps firing. Firebug runs out of lines for the console output in the mouseenter/mouseleave output. I simply want to achieve a rollover effect. I have to assume it is how I am using backbone. I have only started using this week. I've only tested in Firefox so far.

When the "HomeView" view is rendered, the "HomeIconView" views are dynamically inserted into the "HomeView" view. There's no prob with the "events" of HomeIconView being called, the problem is they are continually being called! Apparently, it doesn't matter if the mouse is actually entering or leaving. Backbone, after the initial mouseenter and up until the final mouseleave, just keeps iterating through renderRollOver() and renderRollOut() even when there is no mouse movement. :(

I've spent days searching for a solution. All I can find are threads where people can't bind the events, not threads where people are experiencing over active bound function calls.

In general I am open to any suggestion of better coding practice but in particular, please help put me out of my misery on this event bind mouseenter/leave thing.

Again, sry bout all the code, I wanted to leave no ambiguity.

...

window.HomeIconView = Backbone.View.extend ({

model: new HomeIconModel,

template: _.template([
                '<a href="#">',
                    '<div class="homeIcon" id="homeIcon-<%= id %>">',
                        '<img src="<%= homeIconSrc %>">',
                    '</div>',
                '</a>'
                ].join('')),

events: { 'mouseenter': 'renderRollOver', 'mouseleave': 'renderRollOut' },

initialize: function(md) {

    _.bindAll(this, 'render');
    this.id = 'Icon-' + md.c.id.toString();
    this.model.save(md.c);
},

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

renderRollOver: function() {

    console.log('rollover');
        $('#homeRollOver, #homeRollOver2').css({ 'display': 'block', 'opacity': 0.125 });
        $('#home' + this.id).stop().animate( { opacity: 1 }, 1000);
        var elOffset = $('#home' + this.id).offset();
        var elOffsetL = elOffset.left - 
                        (
                            (
                                parseInt($('#homeRollOver').css('width')) - 
                                parseInt($('#home' + this.id).css('width'))
                            ) / 2
                        );
        var elOffsetT = elOffset.top -
                        (
                            (
                                parseInt($('#homeRollOver').css('height')) - 
                                parseInt($('#home' + this.id).css('height'))
                            ) / 2
                        );
        $('#homeRollOver, #homeRollOver2').css(
            { 'marginLeft': elOffsetL, 'marginTop': elOffsetT }
        );
},

renderRollOut: function() {
    console.log('rollout');
    $('#homeRollOver, #homeRollOver2').css('display', 'none');
    $('#home' + this.id).stop().animate({ opacity: 0.125 }, 1000 );
}
});

window.HomeView = Backbone.View.extend({

model: new PreloadHomeImages,

template: _.template([
            '<div id="homeIconWrapper"></div>',
            '<div id="homeRollOver"></div>',
            '<div id="homeRollOver2"></div>'
            ].join('')),

initialize: function() {
    _PAGE_H = $(document).height();
    _PAGE_W = $(document).width();
    this.preload();
    this.render();
},

preload: function() {
    var i = 0;
    _.each(this.model.get('icons'), function(icon) {
        var tmpimg = $('<img/>');
        tmpimg.src = icon.image;
        i++;
    });
    this.$el.css('paddingTop', (_PAGE_H - 180) / 2) ;
    $('#wrapper').css('height', _PAGE_H - 50);
},

render: function() {
    this.$el.html(this.template);
    var i = 0;
    _.each(this.model.get('icons'), function(icon) {
        var iconView = new HomeIconView({
                                model: new HomeIconModel, 
                                c: { 'id': i, 'homeIconSrc': icon.image }
                            });
        $('#homeIconWrapper').append(iconView.render);
        i++;
    });
    return this;
}
}); 
...
Shane
  • 63
  • 6
  • Your `mouseenter` action is probably obscuring the element that triggers it. That would mean that each `mouseenter` would trigger a `mouseleave` which would reveal the `mouseenter` element and trigger another `mouseenter` and around and around you go. Note that `#homeRollOver` is not inside HomeIconView. The usual solution is to fix the DOM hiearchy. I'll try to get back to this in a bit but someone else is more than welcome to take it from here. – mu is too short Sep 24 '12 at 04:27
  • Thank u. Your guess seemed spot on. What u described was exactly what was happening. But it seems that was not the prob! :S Updating the assignment of this.id in the HomeIconView->initialize with the value of a valid ID (not just an int) in the instantiation of the HomeIconView seems to have solved the problem. The resultant HTML is the same. – Shane Sep 24 '12 at 05:32
  • BTW, The reason I have #homeRollOver outside is because there is only one of them. It is an element using CSS3 rotate props. I thought having one image for rollover and positioning it onmouseenter would save some CPU cycles. It didn't save me any headaches though! Thanks again, what you said got me on the right track to finding the prob with the div ID. – Shane Sep 24 '12 at 05:33
  • Cool, you can put that down as an answer and accept it (I think you have to wait 24h to accept it though). Every time I've had this problem it has been the situation I described above. – mu is too short Sep 24 '12 at 06:06

1 Answers1

1

The HomeIconView required a valid ID when being instantiated.

Later on when trying to implement the rollover I experienced the problem mu_is_too_short described, in that the z-index of the elements were causing the mouseenter/leave to also continually trigger. Both answers are right. Thanks again @mu_is_too_short.

Example;

http://3d.rededitor.net/site2/

Shane
  • 63
  • 6