Question

I'm using Backbone together with require.js and jQuery. What I'm trying to do is to simply bind an event to a container which should show (mouseover) or hide (mouseout) a video. The event fires but unfortunately too many times (I've several children inside .intro-content). I tried using ev.stopPropagation() (as seen in the code) and ev.stopImmediatePropagation but this doesn't prevent the bubbling. What am I doing wrong?

View:

define([
  'jquery',
  'underscore',
  'backbone',
  'global'
], function($, _, Backbone, Global){

    var VideoView = Backbone.View.extend({

        el: $('#splitlayout'),

        events: {
            'mouseover .side-left .intro-content': 'checkVideoState',
            'mouseout .side-left .intro-content': 'checkVideoState'
        },        

        render: function(){

            this.playVideo('video', '0GsrOOV0gQM');
            this.delegateEvents();

        },

        initialize: function() {

            _.bindAll(this);
            this.render();

        },

        checkVideoState: function(ev) {

            ev.stopPropagation();

            if(!$('#video').hasClass('active') && ev.type == 'mouseover') {

                this.showVideo();

            } else if($('#video').hasClass('active') && ev.type == 'mouseout') {

                this.hideVideo();

            }

        },

        showVideo: function() {
            console.log('test');
            $('#video').addClass('active');
            player.playVideo();
        },

        hideVideo: function() {
            console.log('test');
            $('#video').removeClass('active');
            player.pauseVideo();
        },

        playVideo: function(container, videoId) {

            var self = this;

            if (typeof(YT) == 'undefined' || typeof(YT.Player) == 'undefined') {
                window.onYouTubeIframeAPIReady = function() {
                    self.loadPlayer(container, videoId);
                };

                $.getScript('//www.youtube.com/iframe_api');
            } else {
                self.loadPlayer(container, videoId);
            }

        },

        loadPlayer: function(container, videoId) {

            player = new YT.Player(container, {
                videoId: videoId,
                playerVars: {
                    controls: 0,
                    loop: 1,
                    modestbranding: 0,
                    rel: 0,
                    showinfo: 0
                },
                events: {
                    'onReady': this.onPlayerReady
                }
            });

        },

        onPlayerReady: function() {

            player.setPlaybackQuality('hd720');
            player.seekTo(8,false);
            player.pauseVideo();

        }

    });

    return VideoView;

});
Was it helpful?

Solution

You probably initialized your view twice.

Here is an example of double events http://jsfiddle.net/rph4R which you can fix with removing last line new VideoView();.

To check this you may add

console.log('initialize');

to the VideoView.initialize() method and check on console or use debugger or console.trace() to see full call stack.

You can also check search for this code in your files and count it

new VideoView();

OTHER TIPS

You are receiving the event multiple times because you have multiple children in your container. Every time the mouse moves over a new child in the container a new event will be triggered. Basically, you want to use mouseenter instead. Have a look at the example at the bottom of the JQuery documentation.

This event type can cause many headaches due to event bubbling. For instance, when the mouse pointer moves over the Inner element in this example, a mouseover event will be sent to that, then trickle up to Outer. This can trigger our bound mouseover handler at inopportune times. See the discussion for .mouseenter() for a useful alternative.

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