Fix iframe scrolling in iOS (#87)

Also some other small fixes for iOS/Android.
pull/5742/merge
Aleksander Machniak 7 years ago
parent d04d0a3078
commit aa542a35c1

@ -57,7 +57,7 @@ destination system.
RULES: RULES:
------ ------
- Supported browsers: IE11+, Edge, Last 2 versions for Chrome/Firefox/Safari, - Supported browsers: IE11+, Edge, Last 2 versions for Chrome/Firefox/Safari,
Android Browser 5+, iOS Safari 7+. Android Browser 5+, iOS Safari 9+.
- Minimum supported screen width is 240px (note that even if the device screen - Minimum supported screen width is 240px (note that even if the device screen
resolution is e.g.320x372 changing the text size in device settings will reduce resolution is e.g.320x372 changing the text size in device settings will reduce

@ -38,7 +38,6 @@ html {
body { body {
min-width: @page-min-width; min-width: @page-min-width;
height: 100%; height: 100%;
overflow: hidden;
color: @color-font; color: @color-font;
} }
@ -65,15 +64,24 @@ body > #layout {
background-color: @color-layout-content-background; background-color: @color-layout-content-background;
& > .formcontent, // e.g. Help plugin & > .formcontent, // e.g. Help plugin
& > iframe, & > .content {
& > .content,
& > .content > iframe {
height: 100%; height: 100%;
width: 100%; width: 100%;
overflow: auto; overflow: auto;
border: 0;
flex: 1; flex: 1;
} }
.iframe-wrapper {
width: 100%;
height: 100%;
flex: 1;
iframe {
width: 100%;
height: 100%;
border: 0;
}
}
} }
&.sidebar { &.sidebar {
@ -92,6 +100,9 @@ body > #layout {
&.menu { &.menu {
width: @layout-menu-width; width: @layout-menu-width;
// FIXME: we set background color here not in taskmenu.less, because
// otherwise background is partially white on Android/iOS
background-color: @color-taskmenu-background;
} }
& > .scroller { & > .scroller {

@ -240,6 +240,17 @@ fieldset.image-attachment {
bottom: @layout-header-height; bottom: @layout-header-height;
} }
// iOS: Fix scrolling of iframe, display scrollbars on scrollable elements
.ios-scroll {
padding: 0;
-webkit-overflow-scrolling: touch !important;
overflow: scroll !important;
&.iframe-wrapper {
margin-top: 1px; // FIXME: without this scrolling hides the wrapper neighbours' border
}
}
.quota-widget { .quota-widget {
width: 5rem; width: 5rem;
max-width: 8rem; max-width: 8rem;

@ -311,7 +311,6 @@ html.ms .propform {
flex-direction: column; flex-direction: column;
justify-content:flex-start; justify-content:flex-start;
overflow-y: hidden !important; overflow-y: hidden !important;
height: 100%;
.formcontent { .formcontent {
overflow-x: hidden; overflow-x: hidden;
@ -325,17 +324,28 @@ html.ms .propform {
margin-right: .5rem; margin-right: .5rem;
} }
} }
}
html.layout-small, // FIXME: iOS/Android frames have some problem with form buttons element
html.layout-phone { // when the form height is bigger than the iframe height
.formcontainer { // We got rid of the floating buttons effect to fix that,
// which is not perfect because Save button are visible only after
// the page is scrolled to the bottom
.webkit.tablet &,
.iframe.ipad &,
.iframe.iphone & {
display: block;
}
// We don't need buttons element on small devices
html.layout-small &,
html.layout-phone & {
.formbuttons { .formbuttons {
display: none; display: none;
} }
} }
} }
.formcontent { .formcontent {
padding: 1rem; padding: 1rem;

@ -97,17 +97,18 @@
} }
} }
} }
}
.ui-dialog iframe, iframe,
.ui-dialog-content.iframe { .ui-dialog-content.iframe {
padding: 0 !important; padding: 0;
overflow: hidden !important;
width: 100% !important; width: 100% !important;
height: 100%; height: 100%;
border: 0; border: 0;
overflow: hidden;
}
} }
/* FIXME: why do I need !important here? */ /* FIXME: why do I need !important here? */
@media screen and (max-width: @screen-width-xs) { @media screen and (max-width: @screen-width-xs) {

@ -12,7 +12,6 @@
/*** Taskmenu ***/ /*** Taskmenu ***/
#taskmenu { #taskmenu {
background-color: @color-taskmenu-background;
height: 100%; height: 100%;
a { a {

@ -84,8 +84,10 @@
</div> </div>
</div> </div>
<h2 id="aria-label-contact-frame" class="voice"><roundcube:label name="contactproperties" /></h2> <h2 id="aria-label-contact-frame" class="voice"><roundcube:label name="contactproperties" /></h2>
<div class="iframe-wrapper">
<roundcube:object name="addressframe" id="contact-frame" src="/watermark.html" title="contactproperties" <roundcube:object name="addressframe" id="contact-frame" src="/watermark.html" title="contactproperties"
aria-labelledby="aria-label-contact-frame" /> aria-labelledby="aria-label-contact-frame" />
</div>
</div> </div>
<!-- popup menus --> <!-- popup menus -->

@ -19,7 +19,7 @@
<div class="formbuttons"> <div class="formbuttons">
<roundcube:button command="edit" class="btn btn-primary edit" label="edit" condition="!ENV:readonly" /> <roundcube:button command="edit" class="btn btn-primary edit" label="edit" condition="!ENV:readonly" />
<roundcube:if condition="env:qrcode" /> <roundcube:if condition="env:qrcode" />
<roundcube:button command="qrcode" class="btn qrcode" label="qrcode" /> <roundcube:button command="qrcode" class="btn btn-secondary qrcode" label="qrcode" />
<roundcube:endif /> <roundcube:endif />
</div> </div>

@ -47,7 +47,9 @@
label="empty" title="empty" innerclass="inner" /> label="empty" title="empty" innerclass="inner" />
</div> </div>
</div> </div>
<div class="iframe-wrapper">
<roundcube:object name="folderframe" id="preferences-frame" src="/watermark.html" /> <roundcube:object name="folderframe" id="preferences-frame" src="/watermark.html" />
</div>
</div> </div>
<div id="search-filter" class="popupmenu form nolist toolbarmenu" data-editable="true"> <div id="search-filter" class="popupmenu form nolist toolbarmenu" data-editable="true">

@ -37,7 +37,9 @@
condition="config:identities_level:0<2" /> condition="config:identities_level:0<2" />
</div> </div>
</div> </div>
<div class="iframe-wrapper">
<roundcube:object name="identityframe" id="preferences-frame" src="/watermark.html" title="arialabelidentityeditfrom" /> <roundcube:object name="identityframe" id="preferences-frame" src="/watermark.html" title="arialabelidentityeditfrom" />
</div>
</div> </div>
<roundcube:include file="includes/footer.html" /> <roundcube:include file="includes/footer.html" />

@ -69,12 +69,14 @@
<roundcube:include file="includes/mail-menu.html" /> <roundcube:include file="includes/mail-menu.html" />
</div> </div>
<h2 id="aria-label-mailpreviewframe" class="voice"><roundcube:label name="arialabelmailpreviewframe" /></h2> <h2 id="aria-label-mailpreviewframe" class="voice"><roundcube:label name="arialabelmailpreviewframe" /></h2>
<div class="iframe-wrapper">
<roundcube:object name="messagecontentframe" <roundcube:object name="messagecontentframe"
id="messagecontframe" id="messagecontframe"
aria-labelledby="aria-label-mailpreviewframe" aria-labelledby="aria-label-mailpreviewframe"
src="/watermark.html" src="/watermark.html"
title="arialabelmailpreviewframe" title="arialabelmailpreviewframe"
/> />
</div>
</div> </div>
<!-- popup menus --> <!-- popup menus -->

@ -53,8 +53,10 @@
</div> </div>
</div> </div>
<h2 id="aria-label-messagepart" class="voice"><roundcube:label name="arialabelattachmentpreview" /></h2> <h2 id="aria-label-messagepart" class="voice"><roundcube:label name="arialabelattachmentpreview" /></h2>
<div class="iframe-wrapper">
<roundcube:object name="messagePartFrame" id="messagepartframe" title="arialabelattachmentpreview" <roundcube:object name="messagePartFrame" id="messagepartframe" title="arialabelattachmentpreview"
role="main" aria-labelledby="aria-label-messagepart" /> role="main" aria-labelledby="aria-label-messagepart" />
</div>
</div> </div>
<roundcube:if condition="env:is_message" /> <roundcube:if condition="env:is_message" />

@ -35,7 +35,9 @@
class="button delete disabled" classAct="button delete" /> class="button delete disabled" classAct="button delete" />
</div> </div>
</div> </div>
<div class="iframe-wrapper">
<roundcube:object name="responseframe" id="preferences-frame" src="/watermark.html" title="arialabelresonseeditfrom" /> <roundcube:object name="responseframe" id="preferences-frame" src="/watermark.html" title="arialabelresonseeditfrom" />
</div>
</div> </div>
<roundcube:include file="includes/footer.html" /> <roundcube:include file="includes/footer.html" />

@ -21,7 +21,9 @@
<a class="button icon back-list-button" href="#back"><span class="inner"><roundcube:label name="back" /></span></a> <a class="button icon back-list-button" href="#back"><span class="inner"><roundcube:label name="back" /></span></a>
<span class="header-title"></span> <span class="header-title"></span>
</div> </div>
<div class="iframe-wrapper">
<roundcube:object name="prefsframe" id="preferences-frame" src="/watermark.html" title="arialabelpreferencesform" /> <roundcube:object name="prefsframe" id="preferences-frame" src="/watermark.html" title="arialabelpreferencesform" />
</div>
</div> </div>
<roundcube:include file="includes/footer.html" /> <roundcube:include file="includes/footer.html" />

@ -18,6 +18,7 @@ function rcube_elastic_ui()
var ref = this, var ref = this,
mode = 'normal', // one of: large, normal, small, phone mode = 'normal', // one of: large, normal, small, phone
touch = false, touch = false,
ios = false,
is_framed = rcmail.is_framed(), is_framed = rcmail.is_framed(),
env = { env = {
config: { config: {
@ -288,6 +289,10 @@ function rcube_elastic_ui()
// move "Download all attachments" button into a better location // move "Download all attachments" button into a better location
$('#attachment-list + a.zipdownload').appendTo('.header-links'); $('#attachment-list + a.zipdownload').appendTo('.header-links');
if (ios = $('html').is('.ipad,.iphone')) {
$('.iframe-wrapper, .scroller').addClass('ios-scroll');
}
}; };
/** /**
@ -728,6 +733,10 @@ function rcube_elastic_ui()
// when loading content-frame in small-screen mode display it // when loading content-frame in small-screen mode display it
layout.content.find('iframe').on('load', function(e) { layout.content.find('iframe').on('load', function(e) {
var href = '', show = true; var href = '', show = true;
// Reset the scroll position of the iframe-wrapper
$(this).parent('.iframe-wrapper').scrollTop(0);
try { try {
href = e.target.contentWindow.location.href; href = e.target.contentWindow.location.href;
show = !href.endsWith(rcmail.env.blankpage); show = !href.endsWith(rcmail.env.blankpage);
@ -1015,6 +1024,16 @@ function rcube_elastic_ui()
} }
screen_resize_headers(); screen_resize_headers();
// On iOS and Android the content frame height is never correct, fix it
if (bw.webkit) {
$('.iframe-wrapper').each(function() {
var h = $(this).height();
if (h) {
$(this).children('iframe').height(h);
}
});
}
}; };
/** /**
@ -2489,6 +2508,11 @@ function rcube_elastic_ui()
setTimeout(function() { loader.remove(); }, 500); setTimeout(function() { loader.remove(); }, 500);
}) })
.parent().append(loader); .parent().append(loader);
// fix scrolling in iOS
if (ios) {
frame.parent().addClass('ios-scroll');
}
} }
}; };

Loading…
Cancel
Save