iScroll 4 experiencing issue with scrolling on input fields

I am currently in the process of developing a mobile application that is compatible with Android 2.2+, Blackberry 9+, and iOS 4+. Our technology stack includes Phonegap, jQuery, and iScroll (among other tools).

One of the screens in our app resembles the layout described above - displayed on the Safari browser within the iOS 5 simulator.

This particular screen features a standard input form with a fixed header, and various block-level elements that extend across the full width of the device screen, while maintaining minimal padding.

As indicated earlier, our app utilizes iScroll. We have initialized it on this specific page using code derived from the iScroll 'forms' sample.

// ...

window.scroller = new iScroll(id, {
    useTransform: false,
    onBeforeScrollStart: function(e) {
        var target = e.target;
        while (target.nodeType != 1) target = target.parentNode;
        if(target.tagName != 'select'
            && target.tagName != 'input'
            && target.tagName != 'textarea') {
            e.preventDefault();
        }
    }
});

// Disable touch scrolling (Req'd for iScroll)
window.document.addEventListener('touchmove', function(e) {
    e.preventDefault();
}, false);

// ...

Upon observation, it has come to my attention that the content scrolls smoothly when the user interacts with the background area, but fails to respond when attempting to scroll by touching one of the input fields. This issue renders the screen practically unusable, prompting me to seek a solution.

During my investigation, I identified a line in iScroll that seems to be causing this behavior;

if (nodeName == "TEXTAREA" || nodeName == "INPUT" || nodeName == "SELECT" ) return; 

(line 179 in iscroll.js), there is an ongoing issue regarding this bug, along with a proposed fix through a pull request. However, the referenced fixes do not seem to work for me on iOS 5.1 and Android 4.0.4 due to discrepancies in line numbers mentioned by the bug author.

Hence, my query - is there a way to enable scrolling (using iScroll) when interacting with an input element? If not, iScroll becomes impractical in such scenarios. Currently, I am exploring two options:

  • Implementing the Overthrow shim which promises similar functionality to iScroll - although concerns about compatibility issues with Android pose a challenge.
  • Abandoning iScroll altogether and losing the fixed header feature.

In this day and age of technological advancements, it is surprising that such basic functionality remains elusive on mobile browsers!

Answer №1

Though this ticket may be dated, I stumbled upon it while tackling the same issue on my end. My current setup involves iScroll v4 on iOS.

In my quest for a solution, I came across some code snippets that proved helpful during the configuration of the iScroll object:

        myScroll = new iScroll(id, {
            useTransform: false,
            onBeforeScrollStart: function (e) {
                var target = e.target;
                while (target.nodeType != 1) target = target.parentNode;

                if (target.tagName != 'SELECT' && target.tagName != 'INPUT' && target.tagName != 'TEXTAREA') {
                    e.preventDefault();
                }
            }
        });

However, two issues surfaced as I implemented this code:

a) The useTransform attribute disrupted the layout of a form where radio buttons were being dynamically hidden to display visually appealing ones, similar to what's illustrated in this guide (). While unsure of the exact cause, commenting out useTransform resolved the issue.

b) Following interactions with inputs triggering the virtual keyboard, the page failed to return to its initial scroll position post keyboard dismissal. To address this, I integrated an "onBlur" event to reposition the window accordingly and found success with this final refinement:

    myScroll = new iScroll(id, {
        //useTransform: false,
        onBeforeScrollStart: function (e) {
            var target = e.target;
            while (target.nodeType != 1) target = target.parentNode;

            if (target.tagName != 'SELECT' && target.tagName != 'INPUT' && target.tagName != 'TEXTAREA') {
                e.preventDefault();
            } else {
                $(target).bind('blur', function(){
                    window.scrollTo(0,0);
                    myScroll.refresh();
                });
            }
        }
    });

Hoping this information proves beneficial!

Answer №2

When setting up my iScroll, I encountered the same issue and found a solution that worked well for me:

var ISCROLL_MOVE;

var ISCROLL_MOVE_LIMIT=10;

// ... functions to include when setting up iScroll
onScrollStart: function(e) {
                ISCROLL_MOVE=0;
            },
            onScrollMove: function(e) {
                ISCROLL_MOVE_LIMIT++;
            }

If you have form elements within your iScroll, like so:

var selectField = document.getElementById('mySelectField');

selectField.addEventListener('touchend' /*'mousedown'*/, function(e) {

        if (SCROLL_MOVE<SCROLL_MOVE_LIMIT)
            this.focus();

    }, false);

This code triggers when a touch event occurs, allowing scrolling of iScroll pages even when interacting with form elements. It keeps track of the amount of scrolling the user is doing (SCROLL_MOVE). If the scrolling exceeds 10 (a good threshold set by SCROLL_MOVE_LIMIT), the field won't focus; otherwise, it will.

Let me know if you need further clarification.

Answer №3

Eliminate the need for preventDefault():

window.scroller = new iScroll(id, {
    useTransform: true,
    onBeforeScrollStart: function(e) {
        var element = e.target;
        while (element.nodeType != 1) element = element.parentNode;
        if(element.tagName != 'select'
            && element.tagName != 'input'
            && element.tagName != 'textarea') {

            // you can delete this block of code:
            e.preventDefault();
        }
    }
});

Answer №5

I found the perfect solution to this problem. If you are utilizing iscroll.js, you can easily resolve it by making some edits to the iscroll.js file.

In my case, I made adjustments to the _move(e) function definition. Here is a snippet of the code that was modified within the function:

that.moved = true;
   that._pos(newX, newY);
   that.dirX = deltaX > 0 ? -1 : deltaX < 0 ? 1 : 0;
that.dirY = deltaY > 0 ? -1 : deltaY < 0 ? 1 : 0;
if (timestamp - that.startTime > 300) {
   that.startTime = timestamp;
   that.startX = that.x;
   that.startY = that.y;
}
if (that.options.onScrollMove) that.options.onScrollMove.call(that, e);

//The above code should be enclosed within an else condition, while the following if statement should come after:

enter code here
if (e.srcElement.localName == 'textarea') {
  var scrollHeight = e.srcElement.scrollHeight;
  var scrollTop = e.srcElement.scrollTop;
  if (scrollTop >= 0 && screenTop <= scrollHeight) {
       that.dirY = that.dirY * 5;
       e.srcElement.scrollTop = scrollTop + that.dirY;
  }
}

//I have tested this on an iPad and it works perfectly for me.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Using Javascript to Conceal Button for Unauthenticated Users

Our website is currently running on an outdated e-commerce CMS platform, which limits my options due to my beginner level skills in JavaScript and jQuery. One specific issue we are facing is the need to hide Prices and Add to Cart buttons for users who ar ...

"Exploring the Power of Asynchronous Promises within a Switch Statement in

My current controller setup is as follows: app.controller('myController', function ($scope, myService) { $scope.pageData = {}; myService.promiseGetDataFromServer() .then(function (response) { $scope.pageData = response ...

Is there a way to programmatically incorporate an additional language into my system?

I am looking to incorporate an additional language into my app. I have created a second string file in my Values folder like this: .. values -strings -strings.xml -strings.xml(fr) Currently, the display language of my app is based on the phon ...

Missing ng-required fields not displaying the has-error validation in AngularJS forms

While editing any part of their address, the user should see a red invalid border around each field to indicate that the full form is required. However, for some reason I can't seem to get the 'Address' field to display this border. The set ...

Using jQuery to retrieve the initial object in an array following an Ajax request

I need to retrieve the first object returned by an AJAX call before looping through it with the each() function. Here's the current code that successfully loops through the data: $.each(obj.DATA, function(indexInArray, value) { var depts ...

Achieve a seamless redirection to the 404 component in Angular without altering the browser URL, while ensuring that the browsing

Whenever my backend sends a 404 error (indicating that the URL is valid, but the requested resource is not found, such as http://localhost:4200/post/title-not-exist), I need Angular to automatically redirect to my NotFoundComponent without altering the URL ...

Cease the progress of a Sequelize promise within an Express.js application

Exploring the realm of promises is a new adventure for me, and I'm still trying to grasp their full potential in certain situations. It's refreshing to see Sequelize now supporting promises, as it greatly enhances the readability of my code. One ...

Tips for storing mustache templates for rendering in Node.js

My data is stored in the following format: let data = {"list" :[ { "email": "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="98f9fafb8afef0f9f5e8f4fdb6fbf7f5">[email protected] ...

My HTML form submission to the node.js file is stuck in an endless loading loop

As I work on setting up a basic form submission on my server to collect contact information, I run into an issue. The data is successfully received by my node.js server file upon submission but when I attempt to submit the form, the page tries to load the ...

How can you load elements via AJAX?

Using AJAX, I successfully load content from a PHP page. Now, my challenge is to access and interact with the dynamically loaded elements (such as buttons, forms, or divs). The code snippet that is causing issues: jQuery(document).ready(function() { $( ...

Show users who liked a post from 2 different collections in Meteor

How do I retrieve a list of users who have "liked" this post from a collection and display it in a template? Collections: likes: { "_id": 1234, "userId": "1dsaf8sd2", "postId": "123445" }, { "_id": 1235, "userId": "23f4g4e4", "pos ...

What is the best way to retrieve environment variables from an NPM package in an Angular 5 application

Is there a method for my node module, created from an Angular 5 application, to access the environment variable from the Angular 5 application (environments/environment.ts)? Perhaps Angular 5 exports its environment variables to JavaScript global variables ...

Display JSON values in sequence using Material-UI animations

I have received an array of JSON data from the API that looks like this: "fruits": [ { "id": "1", "fruit": "APPLE", }, { "id": "2", "fruit": ...

Hovering over the top menu items in AngularJS will reveal dropdown submenus that will remain visible even when moving the cursor

I am facing an issue where my top menu has links that display a dropdown of additional menu items upon hovering. I have attempted to use onmouseover and onmouseleave events to control the visibility of the sub menu. However, I have encountered a problem ...

Tips for organizing a multi-dimensional array based on various column indexes

I am looking to organize a multidimensional array by multiple column index. Take, for instance, the test data provided below: var source = [ ["Jack","A","B1", 4], ["AVicky","M", "B2", 2], [ ...

I'm struggling to make this background show up in a div

Anyone able to help me figure this out? I can't seem to get the achtergrond_homepage.png as a background in rounded corners. Edit: It seems like the gray color is always on top. Could it be controlled in the JavaScript part? This is the CSS: @ch ...

The context of the Nuxt.js3 plugin loses its definition

Currently, I am working on a project that involves Nuxt.js3 and supabase integration. In my plugins/supabase.server.js file (I am still unsure whether using server or client is the best approach), I want to call "supabase = createClient(~~)" from index.vu ...

Load information into a different entity

I need help with adding new values to an existing object. When I receive some form data from noteValue, I also have additional input data in my component under person that I would like to integrate into noteValue before saving it. let noteValue = form.va ...

Triggering AJAX call from several buttons within a single page in Django

Hey there! I'm currently working on implementing a voting feature using Ajax in my Django-based website. The issue I'm facing is that users can only vote on the first entry, but I want them to be able to vote on all entries. Can you assist me wit ...

Is it possible to animate the padding of an Android View from the outside

Currently, I am working on animating a shaking button. The outer LinearLayout contains padding, but unfortunately, when the shaking animation starts, it does not show in the padding area. Is there any way to ensure that the animation occurs above all oth ...