Подтвердить что ты не робот

Обнаруживать mousemove, когда над iframe?

У меня есть iframe, который занимает все окно (100% в ширину, 100% высокое), и мне нужно, чтобы главное окно было в состоянии обнаружить, когда мышь была перемещена.

Уже пробовал атрибут onMouseMove в iframe, и он явно не работал. Также попытался обернуть iframe в div следующим образом:

<div onmousemove="alert('justfortesting');"><iframe src="foo.bar"></iframe></div>

.. и это не сработало. Любые предложения?

4b9b3361

Ответ 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 использует этот метод для решения этой проблемы.