web-dev-qa-db-fra.com

Backbone.js détectant l'événement de défilement

J'ai une vue suivante

var FullWindow = Backbone.View.extend({
  initialize: function() {
    _.bindAll(this, 'detect_scroll');
  },

  // bind the events
  events : {
    "scroll" : "detect_scroll"
  },

  detect_scroll: function() {
    console.log('detected');
  }
});

et je l'initialise via

var full_window = new FullWindow({el:$('body')});

Mais je ne pense pas que ça marche.

Quand je change les événements pour

events : {
  "click" : "detect_scroll"
},

C'est bien.

Qu'est-ce qui ne va pas?

21
ericbae

Je ne pense pas que l'élément body déclenchera un événement de défilement à moins que vous ne lui donniez explicitement une barre de défilement en définissant la propriété overflow sur scroll en CSS. À partir de la documentation jQuery:

L'événement de défilement est envoyé à un élément lorsque l'utilisateur fait défiler l'écran à un autre endroit de l'élément. Cela s'applique aux objets window, mais aussi aux cadres et aux éléments défilants avec la propriété CSS de débordement définie pour faire défiler (ou automatique lorsque la hauteur ou la largeur explicite de l'élément est inférieure à la hauteur ou à la largeur de son contenu).

En supposant que vous ne donniez pas explicitement à l'élément body une barre de défilement avec overflow:scroll et/ou une hauteur fixe, l'événement scroll que vous souhaitez écouter est probablement déclenché par l'objet window, et non par body.

Je pense que la meilleure approche consiste ici à supprimer la liaison d'événement Backbone (qui n'est en réalité qu'un raccourci et ne fonctionne que sur les événements de l'élément view.el) et à se lier directement à la fenêtre dans initialize():

initialize: function() {
    _.bindAll(this, 'detect_scroll');
    // bind to window
    $(window).scroll(this.detect_scroll);
}
30
nrabinowitz

Je pense que le problème est que Backbone utilise la délégation d'événements pour capturer des événements, c'est-à-dire qu'il attache des écouteurs au this.$el et que l'événement scroll ne bouillonne pas par définition. Ainsi, si l'événement scroll se produit pour un enfant (ou descendant) de this.$el, alors cet événement ne peut pas être observé à this.$el.

Cela fonctionne pour click, c'est simplement parce que click bouillonne.

11
qbolec

Les barres de défilement du corps et de la fenêtre sont différentes et vous devez vous assurer de ne pas faire défiler l'objet fenêtre. Voici un jiddle qui illustre le problème que vous rencontrez probablement. 

jsfiddle

Je ne suis pas sûr que vous puissiez changer l'objet 'el' en objet document.Window, mais je ne pense pas que ce serait une bonne solution de toute façon. Je dirais que votre meilleur pari est soit d'utiliser CSS comme je l'ai fait pour vous aider avec l'élément body ou de créer une div à l'intérieur du corps et de référencer ce verset avec la balise body. 

Bonne chance.

2
Kyle Rogers

J'ai eu le même problème et voici comment je l'ai mis en œuvre

var MyView = Backbone.View.extend({
el: $('body'),
initialize: function() {
    $(window).scroll(function() {
        if ($(window).scrollTop()!=0 && $(window).scrollTop() == $(document).height() - $(window).height()) {
            if (mpListModel.get('next')) {
                var res = confirm('Next page?');
                if (res==true) {
                    myView.fetch()
                }
            }
        }
    });
},
events: {},
fetch: function() {
    //fetch stuff
}

}); var myView = MyView ();

0
smishra