Как прокрутить горизонтальную полосу прокрутки в iFrame из родительского кадра?

Есть ли какой-либо кроссбраузерный способ прокрутки горизонтальной полосы прокрутки IFrame со сверхшироким контентом с Javascript внутри родительского кадра. Также мне нужно, чтобы он был привязан к событию колеса мыши.

Ответ (подробности см. в документации Марселя Корпеля ниже)

var myIframe = document.getElementById("iframeWithWideContent");

myIframe.onload = function () {
  var mouseWheelEvt = function (e) {
    var event = e || window.event;
    if(event.wheelDelta)
        var d = 1;
    else
        var d = -1;
    // the first is for Gecko, the second for Chrome/WebKit
    var scrEl = this.parentNode || event.target.parentNode;

    if (document.body.doScroll)
      document.body.doScroll(event.wheelDelta>0?"left":"right");
    else if ((event.wheelDelta || event.detail) > 0)
        scrEl.scrollLeft -= d*60;
    else
        scrEl.scrollLeft += d*60;
    event.preventDefault();

    return false;
  };

  if ("onmousewheel" in this.contentWindow.document)
    this.contentWindow.document.onmousewheel = mouseWheelEvt;
  else
    this.contentWindow.document.body.addEventListener("DOMMouseScroll", mouseWheelEvt, true);
};

person Mohammad    schedule 25.05.2010    source источник


Ответы (1)


В вашем примере есть как минимум две ошибки:

if ("iframeWithWideContent" in document.body){
  document.body.onmousewheel = mouseWheelEvt;
}else{
  document.body.addEventListener("DOMMouseScroll", mouseWheelEvt);
}

Здесь вы проверяете присутствие iframeWithWideContent в document.body и полагаетесь на это условие, чтобы использовать либо …onmousewheel, либо …addEventListener. Они совершенно не связаны. Более того, addEventListener требует дополнительного аргумента.

В качестве ответа вы ссылка на описание, Firefox не поддерживает onmousewheel (в любом случае это нестандартно), поэтому вы должны определить, присутствует это свойство или нет:

if ("onmousewheel" in document.body)
  document.body.onmousewheel = mouseWheelEvt;
else
  document.body.addEventListener("DOMMouseScroll", mouseWheelEvt, true);

На всякий случай, если вы не знали, это (более или менее) правильный способ обнаружение функции (на самом деле, мне следовало проверить, DOMMouseScroll был доступен до его применения).

Согласно этому ответу, contentWindow является Объект окна iframe.

Обновление: я сделал еще один тестовый пример и убедился, что он работает в Firefox и Chrome (возможно, он работает и в других браузерах на основе WebKit).

iframescrolling.html:

<!DOCTYPE html>
<html>
 <head>
  <meta charset=utf-8>
  <title>&lt;iframe&gt; horizontal scrolling test</title>
  <style>
    *      { padding: 0; margin: 0; border: 0 }
    #large { background: #aaa; height: 5000px; width: 5000px }
  </style>
 </head>
 <body>
  <iframe id="iframeWithWideContent" src="iframecontent.html" width="500" height="300"></iframe>
  <div id="large"></div>
  <script>
    var myIframe = document.getElementById("iframeWithWideContent");

    myIframe.onload = function () {
      var mouseWheelEvt = function (e) {
        var event = e || window.event;

        // the first is for Gecko, the second for Chrome/WebKit;
        var scrEl = this.parentNode || event.target.parentNode;

        if(event.wheelDelta)
          var d = 60;
        else
          var d = -60;


        if (document.body.doScroll)
          document.body.doScroll(event.wheelDelta>0?"left":"right");
        else if ((event.wheelDelta || event.detail) > 0)
          scrEl.scrollLeft -= d;
        else
          scrEl.scrollLeft += d;

        event.preventDefault();

        return false;
      };

      if ("onmousewheel" in this.contentWindow.document)
        this.contentWindow.document.onmousewheel = mouseWheelEvt;
      else
        this.contentWindow.document.body.addEventListener("DOMMouseScroll", mouseWheelEvt, true);
    };
  </script>
 </body>
</html>

И iframecontent.html:

<!DOCTYPE html>
<html>
 <head>
  <meta charset=utf-8>
  <title>iframe</title>
  <style>
    *     { padding: 0; margin: 0; border: 0 }
    #long { background: #ccc; height: 500px; width: 5000px }
  </style>
 </head>
 <body>
  <div id="long">long 5000px div</div>
 </body>
</html>

Я тестировал это только в Firefox 3.6.3 и Chromium 5.0.342.9, работающих в Linux. Чтобы предотвратить ошибки в Chrome (о доступе к iframe из другого домена или с использованием другого протокола), вы должны загрузить эти файлы или использовать локальный тестовый сервер (localhost).

Еще одно замечание: я очень сомневаюсь, что это будет работать во всех (основных) браузерах. По крайней мере, этого нет в Opera (которая полностью соответствует стандартам).

Обновление 2. При дальнейшем тестировании направления прокрутки в Firefox и Chrome были противоположными. Я соответствующим образом скорректировал свой код, используя предложения Мохаммеда.

Я также тестировал это в IE 7, но, хотя IE поддерживает onmousewheel, это не работало должным образом. На данный момент мне немного скучно, так что, может быть, я попробую адаптировать пример для IE в другой раз.

person Marcel Korpel    schedule 25.05.2010
comment
Марсель Корпель, ты гений! Это работает отлично, и пока мы можем извинить Opera :) Я добавил небольшое обновление в ваш код, которое исправляет направления между браузерами Firefox и Chrome (потому что прокрутка перемещается в противоположных направлениях с тем же движением колеса мыши). Я добавил обновленный код в вопрос. Обновите свой ответ, и я помечу его как правильный! :) - person Mohammad; 26.05.2010