Проблемы с прокруткой с помощью приложения ExtJS 5 внутри IFrame

Hy,

это то, что выглядит моя тестовая страница:

enter image description here

Синяя область - это родительская страница, а зеленая область - IFrame, которая запускает приложение ExtJS (простое окно просмотра с меткой внутри).

Если сайт выполнен на сенсорном устройстве (IPad, Android Tablet и т.д.), невозможно прокручивать страницу путем "вытирания" на IFrame (зеленая область). Чтобы прокрутить страницу, нужно протирать синюю область.

Это правильно работало в ExtJS v4.2.1 (см. ссылки ниже).

Test-сайты:

https://skaface.leo.uberspace.de/ScrollTest/Ext510/ (не работает, как ожидалось, используя ExtJS v5.1.1)
https://skaface.leo.uberspace.de/ScrollTest/Ext421/ (работает как ожидалось, тот же код, но с помощью ExtJS v4.2.1)

Код проверки:

Родительский сайт (index.html):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" style="height: 100%;">
<head>
    <title>Test</title>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">
</head>
<body style="margin: 50px; background-color: blue;">
    <iframe src="frame.html" width="100%" height="1400" style="border: none;"></iframe>
</body>
</html>

IFrame (frame.html):

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
<html xmlns="http://www.w3.org/1999/xhtml" style="height: 100%;">
<head>
    <title>Test</title>
    <meta http-equiv="content-type" content="text/html; charset=utf-8"/>
    <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1">

    <link rel="stylesheet" type="text/css" href="#" onclick="location.href='https://extjs.cachefly.net/ext/gpl/5.1.0/packages/ext-theme-neptune/build/resources/ext-theme-neptune-all-debug.css'; return false;" />
    <script type="text/javascript" src="https://extjs.cachefly.net/ext/gpl/5.1.0/build/ext-all-debug.js"></script>

    <script type="text/javascript">
        Ext.onReady(function() {
            Ext.create('Ext.container.Viewport', {
                style: { 'background-color': 'yellowgreen' },
                layout: 'fit',
                items: [{
                    xtype: 'label',
                    text: 'Ext version: ' + Ext.versions.extjs.version,
                    margin: 16
                }]
            });
        });
    </script>
</head>
<body>
</body>
</html>

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

Спасибо и наилучшие пожелания

Ps: Я уже опубликовал отчет об ошибке на форумах sencha, но так как я не получал никакой помощи там до тех пор, пока знаю, я также пытаюсь удачи в stackoverflow...

Ответ 1

После многократного поиска внутри рамки я наконец нашел решение, которое, по крайней мере, работает для меня и состоит из двух шагов:

1) ExtJS задает свойство CSS touch-action для окна просмотра (базовый элемент html IFrame) и его тело для значения none. Я просто перезаписал его значением auto:

.x-viewport, .x-viewport > .x-body {
    touch-action: auto;
}

2) Класс Ext.container.Viewport вызывает Ext.plugin.Viewport.decorate(this); в своем обратном вызове создания, который добавляет слушателя к событию touchmove самого окна просмотра.

Все, что прослушиватель делает, вызывает preventDefault(); события, что является причиной того, что прокрутка больше не работает на родительской странице или самой IFrame. Мое исправление просто удаляет preventDefault() и вместо этого возвращает false из обработчика события touchmove, чтобы событие запустило цепочку браузеров:

Ext.define('Cbn.overrides.container.Viewport', {
    override: 'Ext.container.Viewport'
}, function() {
    Ext.override(this, {
        onRender: function() {
            this.mon(Ext.getDoc(), {
                touchmove: function(e) {
                    // e.preventDefault(); // Original ExtJS code
                    return false;
                },
                translate: false,
                delegated: false
            });
            this.callParent(arguments);
        }
    });
});

Я не совсем уверен, имеют ли эти 2 исправления какие-либо негативные последствия, но пока они, похоже, выполняют эту работу для меня.

Одна вещь, которую я действительно понял, заключается в том, что использование компонентов с конфигурацией scrollable: true внутри IFrame-App все еще создает проблемы, но поскольку я могу избежать этого почти везде, для меня до сих пор не проблема...

Рабочий тестовый сайт: https://skaface.leo.uberspace.de/ScrollTest/Ext510_fixed/


Edit:
Скорректированное решение немного, чтобы не постоянно бросать необработанные ошибки JavaScript во время сенсорной прокрутки (см. Ошибка: не удалось выполнить "dispatchEvent" в "EventTarget" )

Ответ 2

Повлияет странно, я видел его перед использованием плагина niceScroll, и у многих других плагинов была такая же проблема с iframe, в любом случае проверьте это обходное решение

Я использовал Hammer.js плагин jQuery для обнаружения жестов касания на вашем iframe, если вы найдете любые вопросы, касающиеся чувствительности (поскольку я не знаю, какие ограничения вы ищете), вы можете настроить параметры hammer.js, найденные на их репо (например, порог панорамирования, указатели..etc)

и код очень прост:

<body id="mainbody"  style="margin: 50px; background-color: blue;">
    <iframe id="myframe"  src="frame.html" width="100%" height="1400" style="border: none;"></iframe>
</body>
<script>
var myBody
$('iframe').load(function(){
  myBody=$(this).contents().find("body");
  myBody.css({"height":"100%","overflow":"hidden"}).hammer({threshold:1}).bind("pan", myPanHandler);
});
function myPanHandler(ev)
{
    $("#mainbody").scrollTop($("#mainbody").scrollTop()-ev.gesture.deltaY)
console.log(($("#mainbody").scrollTop()-ev.gesture.deltaY*0.5)+".."+$("#mainbody").scrollTop())
}
</script>