【问题标题】:Scrolling issues with ExtJS 5 app inside IFrameExtJS 5 应用程序在 IFrame 中的滚动问题
【发布时间】:2015-09-20 22:52:54
【问题描述】:

喂,

这是我的测试页面的样子:

蓝色区域是父页面,绿色区域是运行 ExtJS 应用程序的 IFrame(内部带有标签的简单视口)。

如果网站是在触摸设备(iPad、Android 平板电脑等)上执行的,则无法通过在 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.:我已经发布了一个错误报告 in the sencha forums,但由于在知道之前我没有得到任何帮助,所以我也在 stackoverflow 上试试运气......

【问题讨论】:

  • 为什么不能完全移除外部容器,直接显示内部内容,在 body 上使用 50px 的 padding 之类的?
  • @davidcondrey 谢谢你的链接,我下周去看看。
  • @BoffinbraiN 这只是一个过于简单的测试用例。我的“现实生活中的应用程序”嵌入在复杂的网站中,无法阻止 IFrame 的使用......
  • @davidcondrey 虽然这篇文章至少让我了解了为什么在 IFrame 内滚动不再起作用,但它并没有为我的问题提供任何解决方案。无论如何感谢它。我希望它至少能引导我朝着正确的方向前进……

标签: javascript iframe extjs extjs5


【解决方案1】:

行为很奇怪,我在使用 niceScroll 插件之前已经看到它,并且许多其他插件也与 iframe 有相同的问题,无论如何检查 this workaround

我已经使用 Hammer.js jQuery 插件来检测你的iframe 上的触摸手势,如果你发现任何关于感知的问题(因为我不知道你在寻找什么限制),你可以调整在他们的 repo 中找到的hammer.js 选项(比如 pan threshold ,pointers ..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>

【讨论】:

  • 我现在还没有将此答案标记为已接受的答案,因为它感觉像是一个非常老套的解决方案,我仍在寻找更优雅的东西,比如直接在 ExtJS 框架中修复东西。尽管如此,它至少提供了一种可能可行的方法,因此我给予了赏金。
【解决方案2】:

在框架内部进行了大量挖掘之后,我终于找到了一个至少对我有用的解决方案,包括两个步骤:

1) ExtJS 将视口(IFrame 的基本 html 元素)及其主体的 CSS 属性 touch-action 设置为值 none。 我只是用值auto 覆盖它:

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

2) Ext.container.Viewport 类在它的创建回调中调用Ext.plugin.Viewport.decorate(this);,它为视口本身的touchmove 事件添加了一个监听器。

监听器所做的一切都是调用事件的preventDefault();,这就是滚动在父页面或 IFrame 本身上不再起作用的原因。 我的修复只是删除了preventDefault(),而是从touchmove 事件处理程序中返回false,让事件在浏览器链中冒泡:

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 个修复是否有任何负面影响,但到目前为止,它们似乎为我完成了这项工作。

我确实意识到,在 IFrame-App 中使用配置为 scrollable: true 的组件仍然会产生问题,但由于我几乎可以在任何地方避免这种情况,所以到目前为止对我来说都不是问题......

工作测试站点:https://skaface.leo.uberspace.de/ScrollTest/Ext510_fixed/


编辑:
稍微调整了解决方案,以免在触摸滚动期间不断抛出未处理的 JavaScript 错误(请参阅Error: Failed to execute 'dispatchEvent' on 'EventTarget'

【讨论】:

    猜你喜欢
    • 2015-04-05
    • 1970-01-01
    • 1970-01-01
    • 2010-10-24
    • 2014-12-28
    • 2017-12-27
    • 1970-01-01
    • 1970-01-01
    • 2011-06-27
    相关资源
    最近更新 更多