Предотвращение прокрутки родительской страницы при переходе мыши по встроенному iframe в Firefox.

... без ограничения прокрутки внутри iframe или необходимости конкретно указывать/отмечать все прокручиваемые элементы.

Представьте виджеты Google Maps, встроенные в родительскую страницу. Когда вы увеличиваете виджет, вы не хотите, чтобы родительская страница прокручивалась, очевидно.

Я подумал, что ответ на мой предыдущий вопрос решил проблему:

При прокрутке внутри iframe тело ничего не знает о что там происходит. Но когда скроллер iframe достигнет дна или сверху, он проходит прокрутку к телу.

Отмените событие, которое распространяется из iframe.

Но решение не работает в Firefox, потому что Firefox не будет - по дизайну - распространяет события, захваченные iframe на родительскую страницу, но странно он будет прокручивать родительскую страницу. См. jsfiddle здесь.

$('body').bind('mousewheel DOMMouseScroll', onWheel);

function onWheel (e){
    if (e.target === iframe)
        e.preventDefault();
    console.log(e);
}

Итак, как я могу предотвратить прокрутку страницы, когда пользователь увеличивает содержимое во встроенном iframe, в Firefox?

Ответ 1

Так как это ошибка в Firefox, обходной путь заключается в том, чтобы работать непосредственно с событием scroll вместо mousewheel/DOMMouseScroll.

То, как я это сделал: когда пользователь вводит указатель мыши на iframe, я устанавливаю флаг true, и когда он покидает мышь, я возвращаю его на false.

Затем, когда пользователь пытается выполнить прокрутку, но стрелка мыши находится внутри iframe, я предотвращаю прокрутку родительского окна. Но, к сожалению, вы не можете предотвратить прокрутку окна с помощью обычного метода e.preventDefault(), поэтому нам по-прежнему нужен еще один обходной путь здесь, заставляя окно прокручиваться точно до позиций X и Y, которые уже были раньше.

Полный код:

(function(w) {
    var s = { insideIframe: false } 

    $(iframe).mouseenter(function() {
        s.insideIframe = true;
        s.scrollX = w.scrollX;
        s.scrollY = w.scrollY;
    }).mouseleave(function() {
        s.insideIframe = false;
    });

    $(document).scroll(function() {
        if (s.insideIframe)
            w.scrollTo(s.scrollX, s.scrollY);
    });
})(window);

Я создал немедленно выполненную функцию, чтобы предотвратить определение переменной s в глобальной области.

Работа скрипта: http://jsfiddle.net/qznujqjs/16/


Изменить

Поскольку ваш вопрос не был помечен jQuery (хотя внутри него вы показали код с использованием библиотеки), решение с vanilla JS так же просто, как и выше:

(function(w) {
    var s = { insideIframe: false } 

    iframe.addEventListener('mouseenter', function() {
        s.insideIframe = true;
        s.scrollX = w.scrollX;
        s.scrollY = w.scrollY;
    });

    iframe.addEventListener('mouseleave', function() {
        s.insideIframe = false;
    });

    document.addEventListener('scroll', function() {
        if (s.insideIframe)
            w.scrollTo(s.scrollX, s.scrollY);
    });
})(window);

Ответ 2

Учитывая все предпосылки, я считаю, что следующий способ - это самый надежный способ сделать эту работу в Firefox.

Оберните iframe с помощью div, который немного короче, чтобы включить вертикальную прокрутку в нем:

<div id="wrapper" style="height:190px; width:200px; overflow-y: auto; overflow-x: hidden;">
  <iframe id="iframeid" height="200px" width="200px" src="about:blank">
  </iframe>
</div>

Теперь вы можете центрировать iframe по вертикали и переставлять его каждый раз обертка получает событие scroll (это произойдет, когда пользователь попытается прокрутить края кадра):

var topOffset = 3;

wrapper.scrollTop(topOffset);

wrapper.on("scroll", function(e) {
    wrapper.scrollTop(topOffset);
});

Объедините это с предыдущим исправлением для Chrome, и оно должно охватывать все основные браузеры. Вот рабочий пример - http://jsfiddle.net/o2tk05ab/5/

Единственной нерешенной проблемой будет видимая вертикальная полоса прокрутки на обертке div. Есть несколько способов сделать это, например - Скрыть полосу прокрутки, но все еще можно прокручивать

Ответ 3

Я думаю, что это решит вашу проблему он решил шахту

    var myElem=function(event){
  return $(event.toElement).closest('.slimScrollDiv')
}

$(document).mouseover(function(e){
     window.isOnSub=myElem(e).length>0



})

$(document).on('mousewheel',function(e){
  if(window.isOnSub){  
console.log(e.originalEvent.wheelDelta);      
    if( myElem(e).prop('scrollHeight')-myElem(e).scrollTop()<=myElem(e).height()&&(e.originalEvent.wheelDelta<0)){

      e.preventDefault()
    } 


}

})

заменить ".slimScrollDiv" на селектор элементов, который вы хотите использовать запретить родительский свиток, когда ваша мышь находится на нем

http://jsbin.com/cutube/1/edit?html,js,output