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

Hy,

Вот как выглядит моя тестовая страница:

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

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

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

Тест-сайты:

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="https://extjs.cachefly.net/ext/gpl/5.1.0/packages/ext-theme-neptune/build/resources/ext-theme-neptune-all-debug.css" />
    <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, но так как я не получил никакой помощи, пока не узнал, я также пытаюсь везти на stackru...

2 ответа

Решение

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

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);
        }
    });
});

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

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

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


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

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

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

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

<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>
Другие вопросы по тегам