javascriptandroidiosmobileiscroll

How to automatically detect the need for iScroll?


The iScroll project provides the “overflow:scroll for mobile WebKit”, and was started

[…] because webkit for iPhone does not provide a native way to scroll content inside a fixed size (width/height) div. So basically it was impossible to have a fixed header/footer and a scrolling central area.

We have developed a mobile-friendly Web application, using responsive design (etc.), that uses a layout that sometimes show a fixed header and footer on mobile devices, based on the core-layout library, which in turn uses angular-iscroll.

You can try out the core-layout demo on desktop and mobile, and try to turn the use of iScroll on and off. On desktop scrolling the different areas should work both with and without iScroll (given that the window is not too high so that scrolling is not necessary); on mobile, however, whether scrolling works without iScroll depends on the kind and version of the browser.

Recent versions of the mobile Safari browser, and Android browsers, have started to support overflow:scroll for such fixed-size div elements as described above. Therefore, some browsers still need the use of iScroll to work, while other browsers don't. Because using iScroll introduces some problems on it own, like proper click and touch event handling, I would like to turn off iScroll in all browsers that don't need it.

I would like to add support in angular-iscroll or core-layout for automatically detecting if there is any need to use iScroll or not for each browser opening the page. I know about feature detection libraries like modernizr, but it seems hard to determine the need for iScroll based on feature detection.

Does anyone know how such auto-detection can be implemented?

Another possibility is to use a white/black-list and check the browser version, but in that case I wonder if anyone has a reliable rule set for properly determining the need to use iScroll based on the user-agent string?

Disclosure: I'm the author of both angular-iscroll and core-layout.

Update 2016-01-10:

Since no one have suggested any answers yet, I thought that I could share some ideas I've had of how to solve this:

If anyone can come up with robust solutions based on one of those ideas (or a combination of them), then I'm just happy to help.

Also, I wonder why no one tries to come up with an answer; not even a comment that says this is too difficult/trivial/irrelevant/strange/outdated?


Solution

  • Since no one else have come up with a solution yet, I thought I could share mine, and hopefully, this answer can be edited and improved to more precisely decide for which devices iScroll must be used.

    I wrote the following Modernizr extension that makes use of platform.js to decide if native overflow: scroll div scrolling is supported:

    'use strict';
    
    var platform = require('platform'),
        Modernizr = require('modernizr');
    
    function _isChromeMobile(platform) {
        return platform.name === 'Chrome Mobile';
    }
    
    function _isAndroidBrowserWithRecentOS(platform) {
        return platform.name === 'Android Browser' &&
            versionCompare(platform.os.version, '4.0.4') >= 0;
    }
    
    module.exports = function _useNativeScroll(platform) {
        if (platform.name === 'Opera Mini') {
            return false;
        }
    
        if (platform.name === 'IE Mobile') {
            return versionCompare(platform.version, '11.0') >= 0
        }
    
        switch (platform.os.family) {
            case 'Android':
                // In Chrome we trust.
                return _isChromeMobile(platform) ||
                    _isAndroidBrowserWithRecentOS(platform);
            case 'iOS':
                // Buggy handling in older iOS versions.
                return versionCompare(platform.version, '5.1') >= 0;
            default:
                // Assuming desktop or other browser.
                return true;
        }
    };
    
    Modernizr.addTest('usenativescroll',
                      require('modernizr-usenativescroll'));
    

    Where compareVersion(), by Jon Papaioannou, is defined in How to compare software version number using js? (only number) or this gist with documentation.

    Now, this method unfortunately does not use feature detection, but can hopefully be further improved if anyone comes up with more facts about problematic devices or browser versions.

    Update 2016-01-27

    Thanks to a generous “free for Open Source” sponsorship from BrowserStack, I've been able to test core-layout, and thereby angular-iscroll, with a plethora of devices and browsers. Based on those tests, I've refined both angular-iscroll's auto-detect rules, and the above code.

    Update 2016-01-25

    Since version 3.1.0 angular-iscroll has this feature builtin. The result of the automatic detection is exposed via the boolean flags iScrollService.state.autoDetectedUseNativeScroll and iScrollServiceProvider.useNativeScroll; where the latter is available during the config phase of the app initialization.