J'ai une fenêtre de boîte modale (pop-up) qui contient un iframe,
et à l'intérieur de ce iframe il y a un div qui est scrollable.
Lorsque je fais défiler la DIV interne de l'iframe et qu'elle a atteint sa limite supérieure ou inférieure,
la fenêtre du navigateur commence à défiler. c'est un comportement indésirable.
J'ai essayé quelque chose comme ça, qui tue le défilement de la fenêtre principale quand
onMouseEnter lorsque la souris entre dans la zone de la fenêtre contextuelle:
e.preventDefault () ne fonctionne pas comme il se doit pour une raison quelconque ...
$("#popup").mouseenter(function(){
$(window).bind("scroll", function(e){
e.preventDefault();
});
}).mouseleave(function(){
$(window).unbind("scroll");
});
On dirait que maintenant en 2013 e.preventDefault();
est suffisant ...
body{
height: 600px;
overflow: auto;
}
section{
width: 50%;
height: 50%;
overflow: auto;
background: lightblue;
overscroll-behavior: none; /* <--- the trick */
}
section::before{
content: '';
height: 200%;
display: block;
}
<section>
<input value='end' />
</section>
Appliquez simplement cette propriété de style à l'élément sur lequel le défilement doit être "verrouillé" et l'événement de défilement ne sera pas transmis à un élément parent pouvant également comporter un défilement.
body{
height: 600px;
overflow: auto;
}
section{
width: 50%;
height: 50%;
overflow: auto;
background: lightblue;
}
section::before{
content: '';
height: 200%;
display: block;
}
<section>
<input value='end' />
</section>
Désolé, autant que je sache, il est impossible d'annuler tout type d'événement de défilement.
Cancelable No
Bubbles No
Je pense que vous devrez laisser cela aux auteurs du navigateur pour le réparer. Firefox (3.5 sous Linux, en tout cas) semble avoir un meilleur comportement pour moi: il ne fait défiler le parent que si l’enfant est déjà au bas/haut au moment où vous démarrez en utilisant la molette.
Si nous ne pouvons pas empêcher le défilement de la fenêtre, pourquoi ne pas l'annuler? C'est-à-dire capturer l'événement de défilement puis revenir à une position fixe.
Le code suivant verrouille l’axe des Y tant que l’on survole $("#popup")
:
// here we store the window scroll position to lock; -1 means unlocked
var forceWindowScrollY = -1;
$(window).scroll(function(event) {
if(forceWindowScrollY != -1 && window.scrollY != forceWindowScrollY) {
$(window).scrollTop(forceWindowScrollY);
}
});
$("#popup").hover(function() {
if(forceWindowScrollY == -1) {
forceWindowScrollY = $(window).scrollTop();
}
}, function() {
forceWindowScrollY = -1;
});
J'utilise ceci pour la boîte de suggestion de requête sur http://bundestube.de/ (entrez quelques caractères dans la zone de recherche supérieure pour rendre le volet déroulant visible):
Cela fonctionne parfaitement dans Chrome/Safari (Webkit) et avec quelques problèmes de défilement dans Firefox et Opera. Pour une raison quelconque, cela ne fonctionne pas avec mon installation IE. Je suppose que cela a à voir avec la méthode de survol de jQuery, qui semble ne pas fonctionner correctement dans 100% des cas.
Je sais que c’est une question assez ancienne, mais comme c’est l’un des meilleurs résultats dans google ... j’ai dû annuler d’une manière ou d’une autre le scroll bullbling sans jQuery et ce code fonctionne pour moi:
function preventDefault(e) {
e = e || window.event;
if (e.preventDefault)
e.preventDefault();
e.returnValue = false;
}
document.getElementById('a').onmousewheel = function(e) {
document.getElementById('a').scrollTop -= e. wheelDeltaY;
preventDefault(e);
}
mon plugin jQuery:
$('.child').dontScrollParent();
$.fn.dontScrollParent = function()
{
this.bind('mousewheel DOMMouseScroll',function(e)
{
var delta = e.originalEvent.wheelDelta || -e.originalEvent.detail;
if (delta > 0 && $(this).scrollTop() <= 0)
return false;
if (delta < 0 && $(this).scrollTop() >= this.scrollHeight - $(this).height())
return false;
return true;
});
}
C'est comme ça que j'ai résolu le problème:
J'appelle le suivant quand j'ouvre le popup:
$('body').css('overflow','hidden');
Puis, quand je ferme le popup, j'appelle ça:
$('body').css('overflow','auto');
Le popup est censé être modal, donc aucune interaction n'est requise avec le corps sous-jacent
Fonctionne assez bien
Apparemment, vous pouvez définir overflow:hidden
pour empêcher le défilement . Je ne sais pas comment ça se passerait si la doc avait déjà défilé. Je suis aussi sur un ordinateur portable sans souris, donc pas de test de roue scrolly pour moi ce soir :-) Cela vaut probablement le coup.
Voici ce que je fais:
$('.noscroll').on('DOMMouseScroll mousewheel', function(ev) {
var prevent = function() {
ev.stopPropagation();
ev.preventDefault();
ev.returnValue = false;
return false;
}
return prevent();
});
Utilisez CSS overflow:hidden
pour masquer la barre de défilement, car cela ne fera rien s’ils le font glisser.
Fonctionne sur plusieurs navigateurs
Je voudrais ajouter un peu de code mis à jour que j'ai trouvé pour fonctionner mieux:
var yourElement = $('.my-element');
yourElement.on('scroll mousewheel wheel DOMMouseScroll', function (e) {
var delta = e.originalEvent.wheelDelta || -e.originalEvent.detail;
if (delta > 0 && $(this).scrollTop() <= 0)
return false;
if (delta < 0 && $(this).scrollTop() >= this.scrollHeight - $(this).outerHeight())
return false;
return true;
});
La différence entre celle-ci et celle déjà mentionnée ci-dessus réside dans l'ajout de plus d'événements et l'utilisation de outerHeight () au lieu de height () pour éviter le crash si l'élément a un remplissage!
Nouveau web dev ici. Cela a fonctionné comme un charme pour moi à la fois sur IE et Chrome.
static preventScrollPropagation(e: HTMLElement) {
e.onmousewheel = (ev) => {
var preventScroll = false;
var isScrollingDown = ev.wheelDelta < 0;
if (isScrollingDown) {
var isAtBottom = e.scrollTop + e.clientHeight == e.scrollHeight;
if (isAtBottom) {
preventScroll = true;
}
} else {
var isAtTop = e.scrollTop == 0;
if (isAtTop) {
preventScroll = true;
}
}
if (preventScroll) {
ev.preventDefault();
}
}
}
Ne laissez pas le nombre de lignes vous tromper, c'est assez simple - juste un peu prolixe pour la lisibilité (code auto-documentant ftw right?)
vous pouvez essayer le volet jscroll dans l’iframe pour remplacer le défilement par défaut.
http://www.kelvinluck.com/assets/jquery/jScrollPane/jScrollPane.html
Je ne suis pas sûr, mais essayez
À partir de 2018, e.preventDefault est suffisant.
$('.elementClass').on("scroll", function(e){
e.preventDefault();
});
Cela empêchera le défilement vers le parent.
$('.scrollable').on('DOMMouseScroll mousewheel', function (e) {
var up = false;
if (e.originalEvent) {
if (e.originalEvent.wheelDelta) up = e.originalEvent.wheelDelta / -1 < 0;
if (e.originalEvent.deltaY) up = e.originalEvent.deltaY < 0;
if (e.originalEvent.detail) up = e.originalEvent.detail < 0;
}
var prevent = function () {
e.stopPropagation();
e.preventDefault();
e.returnValue = false;
return false;
}
if (!up && this.scrollHeight <= $(this).innerHeight() + this.scrollTop + 1) {
return prevent();
} else if (up && 0 >= this.scrollTop - 1) {
return prevent();
}
});