Обнаруживать mousemove, когда над iframe?
У меня есть iframe, который занимает все окно (100% в ширину, 100% высокое), и мне нужно, чтобы главное окно было в состоянии обнаружить, когда мышь была перемещена.
Уже пробовал атрибут onMouseMove
в iframe, и он явно не работал. Также попытался обернуть iframe в div следующим образом:
<div onmousemove="alert('justfortesting');"><iframe src="foo.bar"></iframe></div>
.. и это не сработало. Любые предложения?
Ответы
Ответ 1
Если ваша цель не Opera 9 или ниже, а IE 9 или ниже, вы можете использовать атрибут css pointer-events: none
.
Я нашел лучший способ просто игнорировать iframe. Я добавляю класс с этим атрибутом в iframe в событие onMouseDown
и удаляю событие onMouseUp
.
Прекрасно подходит для меня.
Ответ 2
Iframes захватывает события мыши, но вы можете перенести события в родительскую область, если выполняется междоменная политика. Вот как:
// This example assumes execution from the parent of the the iframe
function bubbleIframeMouseMove(iframe){
// Save any previous onmousemove handler
var existingOnMouseMove = iframe.contentWindow.onmousemove;
// Attach a new onmousemove listener
iframe.contentWindow.onmousemove = function(e){
// Fire any existing onmousemove listener
if(existingOnMouseMove) existingOnMouseMove(e);
// Create a new event for the this window
var evt = document.createEvent("MouseEvents");
// We'll need this to offset the mouse move appropriately
var boundingClientRect = iframe.getBoundingClientRect();
// Initialize the event, copying exiting event values
// for the most part
evt.initMouseEvent(
"mousemove",
true, // bubbles
false, // not cancelable
window,
e.detail,
e.screenX,
e.screenY,
e.clientX + boundingClientRect.left,
e.clientY + boundingClientRect.top,
e.ctrlKey,
e.altKey,
e.shiftKey,
e.metaKey,
e.button,
null // no related element
);
// Dispatch the mousemove event on the iframe element
iframe.dispatchEvent(evt);
};
}
// Get the iframe element we want to track mouse movements on
var myIframe = document.getElementById("myIframe");
// Run it through the function to setup bubbling
bubbleIframeMouseMove(myIframe);
Теперь вы можете прослушивать mousemove на элементе iframe или любом из его родительских элементов - событие будет пузыриться, как вы ожидали.
Это совместимо с современными браузерами. Если вам нужно работать с IE8 и ниже, вам нужно будет использовать специальные для IE замены createEvent
, initMouseEvent
и dispatchEvent
.
Ответ 3
Страница внутри вашего iframe - это полный документ. Он будет использовать все события и не будет иметь немедленного соединения с ним родительским документом.
Вам нужно будет поймать события мыши из javascript внутри дочернего документа, а затем передать это как-то родительскому.
Ответ 4
MouseEvent.initMouseEvent()
теперь устарел, поэтому ответ @Ozan немного устарел. В качестве альтернативы тому, что было в его ответе, я сейчас делаю это так:
var bubbleIframeMouseMove = function( iframe ){
iframe.contentWindow.addEventListener('mousemove', function( event ) {
var boundingClientRect = iframe.getBoundingClientRect();
var evt = new CustomEvent( 'mousemove', {bubbles: true, cancelable: false})
evt.clientX = event.clientX + boundingClientRect.left;
evt.clientY = event.clientY + boundingClientRect.top;
iframe.dispatchEvent( evt );
});
};
Где я устанавливаю clientX
и clientY
, вам нужно передать любую информацию из события окна содержимого в событие, которое мы будем отправлять (т.е. если вам нужно передать что-то вроде screenX
/screenY
, сделайте это там).
Ответ 5
Я столкнулся с аналогичной проблемой, где у меня был div, который я хотел перетащить через iFrame. Проблема заключалась в том, что если указатель мыши перемещался за пределы div, на iFrame, события mousemove были потеряны, а div прекратил перетаскивание. Если это то, что вы хотите сделать (в отличие от того, что пользователь просто махал мышью над iFrame), я нашел предложение в другом вопросительном потоке, которое кажется, хорошо работает, когда я это пробовал.
На странице, содержащей и те вещи, которые вы хотите перетащить, также входят следующие:
<div class="dragSurface" id="dragSurface">
<!-- to capture mouse-moves over the iframe-->
</div>
Задайте начальный стиль таким образом:
.dragSurface
{
background-image: url('../Images/AlmostTransparent.png');
position: absolute;
z-index: 98;
width: 100%;
visibility: hidden;
}
Z-индекс '98' состоит в том, что я устанавливаю div, который я хочу перетащить, чтобы быть z-index: 99, а iFrame - в z-index: 0.
Когда вы обнаруживаете mousedown в подлежащем перетаскиванию объекте (а не divSurface div), вызовите следующую функцию как часть обработчика событий:
function activateDragSurface ( surfaceId )
{
var surface = document.getElementById( surfaceId );
if ( surface == null ) return;
if ( typeof window.innerWidth != 'undefined' )
{ viewportheight = window.innerHeight; }
else
{ viewportheight = document.documentElement.clientHeight; }
if ( ( viewportheight > document.body.parentNode.scrollHeight ) && ( viewportheight > document.body.parentNode.clientHeight ) )
{ surface_height = viewportheight; }
else
{
if ( document.body.parentNode.clientHeight > document.body.parentNode.scrollHeight )
{ surface_height = document.body.parentNode.clientHeight; }
else
{ surface_height = document.body.parentNode.scrollHeight; }
}
var surface = document.getElementById( surfaceId );
surface.style.height = surface_height + 'px';
surface.style.visibility = "visible";
}
Примечание. Я вырезал большую часть этого кода из другого кода, который я нашел в Интернете! Большая часть логики находится здесь, чтобы установить размер dragSurface для заполнения кадра.
Итак, например, мой обработчик onmousedown выглядит следующим образом:
function dragBegin(elt)
{
if ( document.body.onmousemove == null )
{
dragOffX = ( event.pageX - elt.offsetLeft );
dragOffY = ( event.pageY - elt.offsetTop );
document.body.onmousemove = function () { dragTrack( elt ) };
activateDragSurface( "dragSurface" ); // capture mousemoves over the iframe.
}
}
Когда перетаскивание останавливается, ваш обработчик onmouseup должен включать вызов этого кода:
function deactivateDragSurface( surfaceId )
{
var surface = document.getElementById( surfaceId );
if ( surface != null ) surface.style.visibility = "hidden";
}
Наконец, вы создаете фоновое изображение (AlmostTransparent.png в моем примере выше) и делаете что-либо, кроме полностью прозрачного. Я сделал изображение 8x8 с альфа = 2.
Я тестировал это только в Chrome до сих пор. Мне нужно заставить его работать в IE, а также попытаться обновить этот ответ тем, что я там обнаружил!
Ответ 6
В своем "родительском" фрейме выберите "дочерний" iframe и определите интересующее вас событие, в вашем случае mousemove
Это пример кода, который будет использоваться в вашем "родительском" фрейме
document.getElementById('yourIFrameHere').contentDocument.addEventListener('mousemove', function (event) {
console.log(, event.pageX, event.pageY, event.target.id);
}.bind(this));
Ответ 7
<script>
// dispatch events to the iframe from its container
$("body").on('click mouseup mousedown touchend touchstart touchmove mousewheel', function(e) {
var doc = $("#targetFrame")[0].contentWindow.document,
ev = doc.createEvent('Event');
ev.initEvent(e.originalEvent.type, true, false);
for (var key in e.originalEvent) {
// we dont wanna clone target and we are not able to access "private members" of the cloned event.
if (key[0] == key[0].toLowerCase() && $.inArray(key, ['__proto__', 'srcElement', 'target', 'toElement']) == -1) {
ev[key] = e.originalEvent[key];
}
}
doc.dispatchEvent(ev);
});
</script>
<body>
<iframe id="targetFrame" src="eventlistener.html"></iframe>
</body>
Ответ 8
Я нашел относительно простое решение для подобной проблемы, с которой я столкнулся, когда я хотел изменить размер iframe и долгое время, когда рядом с ним сидел div. Как только мышь пошла, iframe jquery перестанет обнаруживать мышь.
Чтобы исправить это, у меня был div, который сидел с iframe, заполняя одну и ту же область теми же стилями, за исключением z-индекса div (установленного в 0) и iframe (установленного в 1). Это позволило использовать iframe, как правило, при изменении размера.
<div id="frameOverlay"></div>
<iframe></iframe>
При изменении размера индекс z z будет установлен на 2, а затем обратно на 0. Это означало, что iframe все еще был видимым, но наложение блокировало его, позволяя обнаруживать мышь.
Ответ 9
Этот код работает, хотя и не очень хорошо:
<div id="test" onmousemove="alert('test');">
<iframe style="width:200px; height:200px; border:1px solid black;">
<p>test</p>
</iframe>
</div>
Событие вызывает триггер для каждого движения мыши, но только для некоторых из них. Я не знаю, есть ли внутри этого события встроенный буфер событий.
Ответ 10
вы можете добавить наложение поверх iframe при запуске drag (событие onmousedown) и удалить его при завершении перетаскивания (в событии mouserup).
jquery UI.layout plugin использует этот метод для решения этой проблемы.