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

Iframe предотвращает прокрутку iScroll на мобильном Safari

Я использую iScroll на моем мобильном веб-сайте (используя iPhone здесь) для прокрутки внутри div.

В этом div, у меня есть iframe с фиксированной высотой, как это:

<body>
  <div id="iscroller">
    <iframe id="theIframe"></iframe>
    Other stuff
  </div>
</body>

Теперь, прокручивая в div, все работает так, как ожидалось, но я не могу прокручивать, когда прокручивающий жест начинается с iframe.

Проблема описана здесь довольно хорошо: https://github.com/cubiq/iscroll/issues/41

Итак, я использовал обходное решение css из этого сообщения, применив pointer-events:none к iframe.

Теперь прокрутка отлично работает , но. Я не могу щелкнуть ссылки, определенные в iframe, потому что все события click/touch в iframe, кажется, заблокированы из-за pointer-events: none.

Итак, я подумал:

"Хорошо, пока пользователь прокручивает, мне нужно pointer-events:none. Если он не прокручивая (и вместо этого щелкая), я должен установить pointer-events:autoчтобы пропускать события щелчка/касания."

Итак, я сделал это:

CSS

#theIframe{pointer-events:none}

JavaScript

$("#theIframe").bind("touchstart", function(){
  // Enable click before click is triggered
  $(this).css("pointer-events", "auto");
});

$("#theIframe").bind("touchmove", function(){
  // Disable click/touch events while scrolling
  $(this).css("pointer-events", "none");
});

Даже добавление этого не работает:

$("#theIframe").bind("touchend", function(){
  // Re-enable click/touch events after releasing
  $(this).css("pointer-events", "auto");
});

Независимо от того, что я делаю: прокрутка не работает или щелчок по ссылке внутри iframe не работает.

Не работает. Любые идеи?

4b9b3361

Ответ 1

Я нашел идеальное решение. Отлично работает на iOS и Android.

Основная идея состоит в том, чтобы поместить div-слой поверх этого iframe. Таким образом, прокрутка работает плавно.

Если пользователь хочет нажать/кликнуть на элементе на этом iframe, я просто поймаю, что нажимаю на этот слой, сохраняю координаты x и y и запускаю событие click для содержимого iframe в этих координатах:

HTML:

<div id="wrapper">
    <div id="layer"></div>
    <iframe id="theIframe"></iframe>
</div>
Other stuff

CSS

#layer{
    position:absolute;
    opacity:0;
    width:100%;
    height:100%;
    top:0;
    left:0;
    right:0;
    bottom:0;
    z-index:2
}

JavaScript:

$('#layer').click(function(event){
    var iframe = $('#theIframe').get(0);
    var iframeDoc = (iframe.contentDocument) ? iframe.contentDocument : iframe.contentWindow.document;

    // Find click position (coordinates)
    var x = event.offsetX;
    var y = event.offsetY;

    // Trigger click inside iframe
    var link = iframeDoc.elementFromPoint(x, y);
    var newEvent = iframeDoc.createEvent('HTMLEvents');
    newEvent.initEvent('click', true, true);
    link.dispatchEvent(newEvent);
});

Ответ 2

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

Я принимаю несколько вещей, например, только один контейнер iscroll, представленный как ID. Это не проверено надлежащим образом и нуждается в рефакторе. Он работает в моем проекте, но я немного изменил его для примера, но, думаю, вы легко поймете, что вам нужно сделать:

var $iscroll = $('#iscroll');

document.addEventListener('touchstart', function(e) {

if ($iscroll.find('iframe').length > 0){

    $.each($iscroll.find('iframe'), function(k,v){

        var $parent = $(v).parent().first();

        if ($parent.find('.preventTouch').length == 0){

            $('<div class="preventTouch" style="position:absolute; z-index:2; width:100%; height:100%;"></div>')
                .prependTo($parent);

        };

        $parent
            .css('position', 'relative').css('z-index', 1);

    });

    $iscroll.find('.preventTouch').on('click', function(e){
        e.preventDefault();
        e.stopPropagation();
        return false;
    });

};

};

document.addEventListener('touchend', function(e) {

if ($iscroll.find('iframe').length > 0){

    setTimeout(function(){

        var $iscroll = $('#iscroll');

        $iscroll.find('.preventTouch').remove();
        $iscroll.find('iframe').css('z-index', '');
        $iscroll.find('.preventTouch').off('click');

    }, 400);

};

};

Спасибо, что посмотрели!