Предотвращение прокрутки родительской страницы при переходе мыши по встроенному 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