javascript touch scroll effect

I am looking to enhance the scrolling capability of my app to make it touch-friendly. I have already implemented scrolling using the mouse wheel, drag, and click functions. I recently tried using the touch-scroll plugin from touch-scroll to enable touch scrolling on iPad.

However, I encountered an issue where, upon adding the code, the div became somewhat scrollable but exhibited an elastic effect that caused it to return to the top. I am in search of a solution to enable smooth and proper scrolling behavior.

Note I attempted to use iscroll-4 without success.

Note Additionally, I am utilizing the website template provided by .

Initialization of the plugin:

<script src="https://github.com/neave/touch-scroll/raw/master/touch-scroll.min.js"></script>
<script>
    $(document).ready(function() {
        if (!!('ontouchstart' in window)) {
            $('#customScrollBox .container').touchScroll();
        }
    });
</script> 

My JavaScript:

$(window).load(function() {
    $toolbar.data("imageViewMode",$defaultViewMode); //default view mode
    ImageViewMode($toolbar.data("imageViewMode"));
    //cache vars
    $customScrollBox=$("#customScrollBox");
    $customScrollBox_container=$("#customScrollBox .container");
    $customScrollBox_content=$("#customScrollBox .content");
    $dragger_container=$("#dragger_container");
    $dragger=$("#dragger");

    CustomScroller();

    function CustomScroller(){
        outerMargin=0;
        innerMargin=20;
        $customScrollBox.height($(window).height()-outerMargin);
        $dragger_container.height($(window).height()-innerMargin);
        visibleHeight=$(window).height()-outerMargin;
        if($customScrollBox_container.height()>visibleHeight){ //custom scroll depends on content height
            $dragger_container,$dragger.css("display","block");
            totalContent=$customScrollBox_content.height();
            draggerContainerHeight=$(window).height()-innerMargin;
            animSpeed=400; //animation speed
            easeType="easeOutCirc"; //easing type
            bottomSpace=1.05; //bottom scrolling space
            targY=0;
            draggerHeight=$dragger.height();
            $dragger.draggable({ 
                axis: "y", 
                containment: "parent", 
                drag: function(event, ui) {
                    Scroll();
                }, 
                stop: function(event, ui) {
                    DraggerOut();
                }
            });

            //scrollbar click
            $dragger_container.click(function(e) {
                var mouseCoord=(e.pageY - $(this).offset().top);
                var targetPos=mouseCoord+$dragger.height();
                if(targetPos<draggerContainerHeight){
                    $dragger.css("top",mouseCoord);
                    Scroll();
                } else {
                    $dragger.css("top",draggerContainerHeight-$dragger.height());
                    Scroll();
                }
            });

            //mousewheel
            $(function($) {
                $customScrollBox.bind("mousewheel", function(event, delta) {
                    vel = Math.abs(delta*10);
                    $dragger.css("top", $dragger.position().top-(delta*vel));
                    Scroll();
                    if($dragger.position().top<0){
                        $dragger.css("top", 0);
                        $customScrollBox_container.stop();
                        Scroll();
                    }
                    if($dragger.position().top>draggerContainerHeight-$dragger.height()){
                        $dragger.css("top", draggerContainerHeight-$dragger.height());
                        $customScrollBox_container.stop();
                        Scroll();
                    }
                    return false;
                });
            });

            function Scroll(){
                var scrollAmount=(totalContent-(visibleHeight/bottomSpace))/(draggerContainerHeight-draggerHeight);
                var draggerY=$dragger.position().top;
                targY=-draggerY*scrollAmount;
                var thePos=$customScrollBox_container.position().top-targY;
                $customScrollBox_container.stop().animate({top: "-="+thePos}, animSpeed, easeType); //with easing
            }

            //dragger hover
            $dragger.mouseup(function(){
                DraggerOut();
            }).mousedown(function(){
                DraggerOver();
            });

            function DraggerOver(){
                $dragger.css("background", "url(round_custom_scrollbar_bg_over.png)");
            }

            function DraggerOut(){
                $dragger.css("background", "url(round_custom_scrollbar_bg.png)");
            }
        } else { //hide custom scrollbar if content is short
            $dragger,$dragger_container.css("display","none");
        }
    }

    //resize browser window functions
    $(window).resize(function() {
        FullScreenBackground("#bgimg"); //scale bg image
        $dragger.css("top",0); //reset content scroll
        $customScrollBox_container.css("top",0);
        $customScrollBox.unbind("mousewheel");
        CustomScroller();
    });

    LargeImageLoad($bgimg);
});

Answer №1

If you haven't explored the possibility of using a purely CSS-based solution, you may find it worth investigating. iOS devices do not display scrollbars, so you could potentially update the CSS for your scrollable element to:

overflow-y: scroll;
-webkit-overflow-scrolling: touch;

By adjusting the height of the scrollable element, you can customize the scrollable area to suit your needs.

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

React - triggering a router link action before the link is assigned a value

In this scenario, the issue arises because the URL changes before the link receives a value. The state is being received directly through the component but by the time it happens, the component has already been clicked. This results in the value being as ...

Insert a fresh directive within an ng-repeat loop

I currently have an array of data that is being shown using a directive within an ng-repeat. Whenever the user clicks on a button, a new object is added to this array which requires a new instance of the directive to be executed. Here is my current HTML se ...

Removing Discord Channel with Discord.js

Currently in the process of developing a ticket system using discord.js Experiencing a challenge where upon a member reacting to the message with a specific emoji, the ticket is supposed to close. However, when running the code, it is throwing an error. i ...

What is the best way to include a new user in the memory database when there is no database or storage back-end?

During an online test, I was given the task of adding a user to a database stored in memory. The request body required JSON formatting as shown below: { "id": "aabbbccddeeefff", "name": "User One", "hobbies": [ "swim", "sing", "workout" ] } (Users ...

The MDBDataTable features header sections at both the top and bottom, but the filters UI seems to be

Currently, I am working with MDBDataTable and encountering an issue with the double heading that appears both on top and bottom of the table. I am unsure how to remove it. The code snippet in question is as follows: There is a function that retrieves and ...

Leveraging the power of the 'var' keyword in JavaScript when

I have a javascript code snippet that looks like this: var grade_type = document.getElementById("grade_type").value; gradesRef.set({ grade_type: firebase.firestore.FieldValue.arrayUnion(grade) }); However, when the data is stored i ...

Tips on creating unit tests for AngularJS attribute-type directives using Jasmine

I have a directive that doesn't use any template or templateUrl. How can I write a unit test for this directive? Below is the code for my directive. var app = angular.module('SampleDirective'); app.directive('sampleContent', [fun ...

Assistance from Meteor for storing Cached Cursors

I have a Template that features a select element allowing users to filter through a collection of Objects displayed on a table. The result of the select is stored in a ReactiveVar, which is then utilized in querying a Helper to retrieve the Objects for the ...

How to Use jQuery in Thymeleaf to Toggle All Checkboxes

Why isn't the function of selecting and deselecting all fields working correctly for me? Can anyone explain what may be causing this issue? ..... <head> <meta name="viewport" content="width=device-width, initial-scale=1.0&q ...

How to refresh a page in React when the browser's back button is pressed

In my React project using Material-UI, I have created a simple search form. On page A, users can input values in text boxes and select options from drop-down lists and checkboxes. The results are then displayed on page B. My issue arises when returning to ...

Tips for dynamically changing the number of visible ListItems in React using a single method

I recently stumbled upon the perfect solution at this link using material-ui. The chapter on "Nested list items" caught my attention, as it only has one nested item with a method for expanding more or less. In my sidebar, I have two nested items that both ...

"Encountering an issue with Express.json where it fails to parse the

Receiving JSON POST data from an IoT API that includes multipart form-data. Occasionally, an image file may be included but I only want to focus on the JSON part: POST { host: '192.168.78.243:3000', accept: '*/*', 'content-le ...

steps for linking a directive variable to a controller

Encountering an issue with 2-way binding in Angular where changes made to the input do not reflect in the controller. However, the initial value set by the controller does affect the directive. In the screenshot, a value was changed but vm.date still hold ...

Is the 'wait > remaining' condition ever satisfied in the throttle function of underscore.js?

Check out the library code at line 860: https://github.com/jashkenas/underscore/blob/master/underscore.js if (remaining <= 0 || remaining > wait) Under what circumstance would the second part of this statement be true? Background - This is my firs ...

Dynamically remove a MongoDB entry with precision

I'm having trouble deleting an entry in MongoDB based on the id variable. Even when I pass the id as a parameter to the method, it doesn't seem to work. I've double-checked the variable inside the method and I'm confident that it has th ...

The result of combining two JavaScript variables

When I multiply a variable by 2 and assign the value to another variable, why do I get 0? My goal is to toggle the visibility of blocks every time a button is pressed. Oddly enough, it works when I use count++ * 2. For code reference, please refer below: ...

What is the best way to modify the text color within a Navbar, especially when the Navbar is displayed within a separate component?

First question on StackOverflow. I have a Next App and the Navbar is being imported in the _app.js file. import Navbar from "../Components/Navbar"; function MyApp({ Component, pageProps }) { return ( <> <Navbar /> ...

Switch Bootstrap Tab

I have successfully implemented a bootstrap tab on my webpage and it is functioning as intended. Now, I am interested in adding an additional feature to the tabs. My question is, is it possible to toggle the content area if the same tab is clicked again? ...

Unable to store object data within an Angular component

This is a sample component class: export class AppComponent { categories = { country: [], author: [] } constructor(){} getOptions(options) { options.forEach(option => { const key = option.name; this.categories[k ...

Ways to verify that a javascript function generates an object and executes a method within that object

Currently, I am in the process of updating server code written in nodejs and incorporating unit tests into the mix. However, I have encountered a challenge that I need assistance with: classX.prototype.methodX = function () { // Create new session ...