Проблемы с прокруткой с помощью приложения 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>