10

Hy,

this is what my test page looks like:

enter image description here

The blue area is the parent page and the green area is an IFrame which runs an ExtJS application (simple viewport with a label inside).

If the site is executed on a touch device (IPad, Android Tablet etc) it's not possible to scroll the page by "wiping" on the IFrame (the green area). One has to wipe on the blue area to scroll the page.

This had been working correctly in ExtJS v4.2.1 (see links below).

Test-Sites:

https://skaface.leo.uberspace.de/ScrollTest/Ext510/ (not working as expected, using ExtJS v5.1.1)
https://skaface.leo.uberspace.de/ScrollTest/Ext421/ (working as expected, same code but using ExtJS v4.2.1)

The test code:

Parent site (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>

I'd really appreciate a workaround for this since it practically makes my sites useless on mobile devices even though they had been working perfectly fine with ExtJS 4.2.1.

Thanks & best regards

Ps.: I've already posted a bug report in the sencha forums, but since I didn't get any help there until know, I'm also trying my luck on stackoverflow...

Tarabass
  • 3,132
  • 2
  • 17
  • 35
suamikim
  • 5,350
  • 9
  • 40
  • 75
  • [Delegated Events and Gestures in Ext JS 5](https://www.sencha.com/blog/delegated-events-and-gestures-in-ext-js-5/) – davidcondrey Jul 09 '15 at 06:04
  • Why can't you just remove the outer container entirely and just show the inner content directly, using a 50px padding on the body or the like? – BoffinBrain Jul 09 '15 at 22:32
  • @davidcondrey Thanks for the link, I'm going to have a look at it next week. – suamikim Jul 10 '15 at 08:27
  • @BoffinbraiN This is just an oversimplified test case. My "real-life-application" is embedded in complex sites and it is impossible to prevent the usage of IFrames... – suamikim Jul 10 '15 at 08:28
  • @suamikim, let me know if that link was helpful. just curious. i'm not all that familiar with extjs so didn't want to say anything.. – davidcondrey Jul 12 '15 at 08:20
  • 1
    @davidcondrey While the article gives me at least an idea on why scrolling inside the IFrame isn't working anymore, it doesn't provide any kind of solution for my problem. Thanks for it anyway. I hope that it at least led me in the right direction... – suamikim Jul 13 '15 at 07:58

2 Answers2

1

The behavious is weird , I have seen it before using niceScroll plugin , and many other plugins had also same issue with iframe , anyway check this workaround

I have used Hammer.js jQuery plugin to detect touch gestures on your iframe , if you find any issues concerning sensetivity ( as I dont know what constraints you are looking for ) , you can adjust hammer.js options found on their repo ( like pan threshold , pointers ..etc )

and the code is very simple :

<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>
ProllyGeek
  • 15,517
  • 9
  • 53
  • 72
  • I didn't mark this answer as the accepted one by now since it feels like a pretty hacky solution and I'm still looking for something more elegant like fixing stuff directly in the ExtJS framework. Still, it at least provides a way which would probably work and therefore I've given the bounty. – suamikim Jul 13 '15 at 15:14
1

After a lot of digging around inside the framework, I finally found a solution which at least works for me and consists of 2 steps:

1) ExtJS sets the CSS property touch-action of the viewport (the base html element of the IFrame) and its body to the value none. I've simply overwritten it with the value auto:

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

2) The class Ext.container.Viewport calls Ext.plugin.Viewport.decorate(this); in it's creation callback, which adds a listener to the touchmove event of the viewport itself.

Everything that listener does is calling preventDefault(); of the event, which is the reason why scrolling doesn't work anymore on the parent page or the IFrame itself. My fix simply removes the preventDefault() and instead returns false from the touchmove event handler to let the event bubble up the browser chain:

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

I'm not quite sure if those 2 fixes have any negative implications but so far they seem to do the job for me.

One thing I did realize is that using components with the config scrollable: true inside the IFrame-App still makes problems but since I can avoid that pretty much everywhere it's no issue for me so far...

Working test-site: https://skaface.leo.uberspace.de/ScrollTest/Ext510_fixed/


Edit:
Adjusted solution a little to not constantly throw unhandled JavaScript errors during touch-scrolling (see Error: Failed to execute 'dispatchEvent' on 'EventTarget')

Community
  • 1
  • 1
suamikim
  • 5,350
  • 9
  • 40
  • 75