iScroll lite find when I have reached the end of the scroll or bottom of the element

巧了我就是萌 提交于 2019-12-04 08:51:51

Since this question is pretty old. This solution is for any future references.

Using iScroll v4.2.5:

var scroll = new iScroll('scroll-wrapper');
scroll.options.onScrollEnd = function(){
    if(Math.abs(this.maxScrollY) - Math.abs(this.y) < 10){
        // RUN CODE if scroll is 10px from the bottom.
    }
};

After along day, i have implemented a smooth infinite scroll and pull to refresh sample app using iscroll4. these two functionality were implemented in one sample app i created. hope its useful to this mobile app developer community.

first it is assumed that:

  1. you are familiar with iscroll4 functions (Not much of a necessity cos am not a guru either).
  2. you know how to make ajax calls to a json file or json/php file

my app summary:

when user loads my app, it makes an ajax call to json/php file on my server and some values are returned.

Problem nature: i want infinite scrolling alongside pull to refresh functions and i dont want to use any other framework apart from iscroll4.

my solution:

 <!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0, user-scalable=0, minimum-scale=1.0, maximum-scale=1.0">
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="apple-mobile-web-app-status-bar-style" content="black">
<link href="http://fonts.googleapis.com/css?family=Headland+One%7COpen+Sans:400,300&amp;subset=latin,cyrillic" rel="stylesheet" type="text/css"></link>
  <link href="css/mystylesheet.css" rel="stylesheet">
<style>

/**
 *
 * Horizontal Scrollbar
 *
 */
.myScrollbarH {
    position:absolute;
    z-index:100;
    height:8px;
    bottom:1px;
    left:2px;
    right:7px
}

.myScrollbarH > div {
    position:absolute;
    z-index:100;
    height:100%;

    /* The following is probably what you want to customize */
    background:-webkit-gradient(linear, 0 0, 100% 0, from(#226BF4), to(#226B8F));
    background-image:-moz-linear-gradient(top, #226BF4, #226B8F);
    background-image:-o-linear-gradient(top, #226BF4, #226B8F);

    border:1px solid #226BF4;

    -webkit-background-clip:padding-box;
    -moz-background-clip:padding-box;
    -o-background-clip:padding-box;
    background-clip:padding-box;

    -webkit-box-sizing:border-box;
    -moz-box-sizing:border-box;
    -o-box-sizing:border-box;
    box-sizing:border-box;

    -webkit-border-radius:4px;
    -moz-border-radius:4px;
    -o-border-radius:4px;
    border-radius:4px;

    -webkit-box-shadow:inset 1px 1px 0 rgba(255,255,255,0.5);
    -moz-box-shadow:inset 1px 1px 0 rgba(255,255,255,0.5);
    -o-box-shadow:inset 1px 1px 0 rgba(255,255,255,0.5);
    box-shadow:inset 1px 1px 0 rgba(255,255,255,0.5);
}


/**
 *
 * Vertical Scrollbar
 *
 */
.myScrollbarV {
    position:absolute;
    z-index:100;
    width:8px;bottom:7px;top:2px;right:1px
}

.myScrollbarV > div {
    position:absolute;
    z-index:100;
    width:100%;

    /* The following is probably what you want to customize */
    background:-webkit-gradient(linear, 0 0, 100% 0, from(#226BF4), to(#226B8F));
    background-image:-moz-linear-gradient(top, #226BF4, #226B8F);
    background-image:-o-linear-gradient(top, #226BF4, #226B8F);

    border:1px solid #226BF4;

    -webkit-background-clip:padding-box;
    -moz-background-clip:padding-box;
    -o-background-clip:padding-box;
    background-clip:padding-box;

    -webkit-box-sizing:border-box;
    -moz-box-sizing:border-box;
    -o-box-sizing:border-box;
    box-sizing:border-box;

    -webkit-border-radius:4px;
    -moz-border-radius:4px;
    -o-border-radius:4px;
    border-radius:4px;

    -webkit-box-shadow:inset 1px 1px 0 rgba(255,255,255,0.5);
    -moz-box-shadow:inset 1px 1px 0 rgba(255,255,255,0.5);
    -o-box-shadow:inset 1px 1px 0 rgba(255,255,255,0.5);
    box-shadow:inset 1px 1px 0 rgba(255,255,255,0.5);
}

/**
 *
 * Pull down styles
 *
 */
#pullDown, #pullUp {
    background:#fff;
    height:40px;
    line-height:40px;
    padding:5px 10px;
    border-bottom:1px solid #ccc;
    font-weight:bold;
    font-size:14px;
    color:#888;
}
#pullDown .pullDownIcon, #pullUp .pullUpIcon  {
    display:block; float:left;
    width:40px; height:40px;
    background:url(images/pull-icon@2x.png) 0 0 no-repeat;
    -webkit-background-size:40px 80px; background-size:40px 80px;
    -webkit-transition-property:-webkit-transform;
    -webkit-transition-duration:250ms;  
}
#pullDown .pullDownIcon {
    -webkit-transform:rotate(0deg) translateZ(0);
}
#pullUp .pullUpIcon  {
    -webkit-transform:rotate(-180deg) translateZ(0);
}

#pullDown.flip .pullDownIcon {
    -webkit-transform:rotate(-180deg) translateZ(0);
}

#pullUp.flip .pullUpIcon {
    -webkit-transform:rotate(0deg) translateZ(0);
}

#pullDown.loading .pullDownIcon, #pullUp.loading .pullUpIcon {
    background-position:0 100%;
    -webkit-transform:rotate(0deg) translateZ(0);
    -webkit-transition-duration:0ms;

    -webkit-animation-name:loading;
    -webkit-animation-duration:2s;
    -webkit-animation-iteration-count:infinite;
    -webkit-animation-timing-function:linear;
}

@-webkit-keyframes loading {
    from { -webkit-transform:rotate(0deg) translateZ(0); }
    to { -webkit-transform:rotate(360deg) translateZ(0); }
}

</style>
</head>
<body style="overflow: hidden;" onload="do_refresh();">
<div class="wrap">
<div id="wrapper">
        <div id="scroller">
        <div id="pullDown">
            <span class="pullDownIcon"></span><span class="pullDownLabel">Pull down to refresh...</span>
        </div>

    <div class="content">
    <input type="hidden" id="last_id">              
            <div id="responsecontainer"></div>
        </div>

        <span class="load_more_loading" ></span>
    </div>
    </div>
</div>


       <script type="text/javascript" src="js/jquery-1.9.1.min.js"></script>
        <script src="js/iscroll.js"></script>
<script src="js/pulltorefresh.js"></script>
<script src="js/infinitescroll.js></script>

<script src="js/myinitialloadscript.js"></script>
    <script src="js/mymobileframework.js"></script> <!--independent of this script. eg. whormhole from mosync-->

    </body>
        </html>

next is to create the myinitialloadscript.js script. this allows content to be loaded into the app for the first time on that page.

  function do_refresh()
    {


    var url = "http://localhost/public_html/landing.php?token=908765789897867567687989089786768980&validator=jhjhjjhjhkhj"; //just url params
    // -------------------------------------------

    $.ajax({
            type: 'GET',
            url: url,
            contentType: "application/json; charset=utf-8",
            dataType: "jsonp",
            // Evaluate text as a json expression
            converters: {"text jsonp": jQuery.parseJSON},
            timeout:30000,
            async: true,
            jsonp: true,
            jsonpCallback: "myJsonMethod",
            beforeSend: function()
            {


//add loading image i dint bcos the image or values becomes double in a case of network delay
            $("#responsecontainer").html("images/loader.gif").show();
            },
            success: function(data)
            {
           ajax.parseJSONP(data);
            },
            error: function(jqXHR, textStatus, errorThrown)
            {
            console.log(errorThrown);
            alert("Could Not Refresh.");
            $("#responsecontainer").html("");//remove loading image
            //$("#responsecontainer").load("refresh_h.html"); //load a page with refresh option.
            }
        });
    $.ajaxSetup({ cache: false }); //fetch data from db not cache content
    }


//if data is fectched successfully then

    var ajax = {  

        parseJSONP:function(data){



            $.each(data, function(i, row) {
            if (i==0){
            $("#responsecontainer").html('');
            }

            var ul = '<li>'+row.myjsondatakey+'</li>'; //could be <div></div> This only displays your values from db in a styled manner
            $(ul).appendTo('#responsecontainer');// append the value to the responsecontainer

//Now watch closely. remember it was assumed you have a json file or json/php file, and in
//most cases you get your json data format from PHP file. so we assume its from a php file.
//also note that php calls to db can have a LIMIT. so in this case my PHP file data LIMIT 
//was set to 5. because of infinite scrolling, i need to know the id of the last element 
//from my returned data. so i write the following. note that my row.id_comments which is my
 //value i want to get was written into an input whose visibility is hidden. this is to 
//enable me over write its value when the last id changes.
            if (i==4)
            {
            //set last id value
            $('#last_id').val(row.id_comments);
            } 

    });
    }
    }

next is to implement pulltorefresh.js much woun't be said about this because the example in iscroll4 is clear.

var myScroll,
    pullDownEl, pullDownOffset,
    pullUpEl, pullUpOffset,
    generatedCount = 0;

function pullDownAction () {
        var el;
        el = document.getElementById('responsecontainer');

var url = "http://localhost/public_html/landing.php?token=78654567897654356789976546789&valid=jhjhjjhjhkhj";

        $.ajax({
        type: 'GET',
        url: url,
        contentType: "application/json; charset=utf-8",
        dataType: "jsonp",
        // Evaluate text as a json expression
        converters: {"text jsonp": jQuery.parseJSON},
        timeout:30000,
        async: true,
        jsonp: true,
        jsonpCallback: "myJsonMethod",
        error: function(){
        myScroll.refresh(); //do nofin
        },
        success: function(data){
        //console.dir('success');
        ajax.parseJSONP(data);
        }
        });
$.ajaxSetup({ cache: false }); //fetch data from db not cache content


var ajax = {  

    parseJSONP:function(data){
        $.each(data, function(i, row) {

        if (i==0){
        $("#responsecontainer").html('');
        }

        var ul = '<li>'+row.myjsondatakey+'</li>';
        $(ul).appendTo(el);


if (i==4)
            {
            //set last id value
            $('#last_id').val(row.id_comments);
            } 
        myScroll.refresh(); // Remember to refresh when contents are loaded (ie: on ajax completion)

});
}
}
}



    function loaded() {
        pullDownEl = document.getElementById('pullDown');
        pullDownOffset = pullDownEl.offsetHeight;

        myScroll = new iScroll('wrapper', {
           scrollbarClass: 'myScrollbar',
            useTransition: true,
            topOffset: pullDownOffset,
            onRefresh: function () {
                if (pullDownEl.className.match('loading')) {
                    pullDownEl.className = '';
                    pullDownEl.querySelector('.pullDownLabel').innerHTML = 'Pull down to refresh...';
                } 
            },
            onScrollMove: function () {
                if (this.y > 5 && !pullDownEl.className.match('flip')) {
                    pullDownEl.className = 'flip';
                    pullDownEl.querySelector('.pullDownLabel').innerHTML = 'Release to refresh...';
                    this.minScrollY = 0;
                } else if (this.y < 5 && pullDownEl.className.match('flip')) {
                    pullDownEl.className = '';
                    pullDownEl.querySelector('.pullDownLabel').innerHTML = 'Pull down to refresh...';
                    this.minScrollY = -pullDownOffset;
                } 
            },

//here is where infinite scroll comes in
                onScrollEnd: function () {
                //infinite scroll started
                if(Math.abs(this.maxScrollY) - Math.abs(this.y) < 10)
                {
                // Do infinite if scroll is 10px from the bottom.
                doInfinite_scroll();
                }

                //infinite scroll ended

                if (pullDownEl.className.match('flip')) {
                    pullDownEl.className = 'loading';
                    pullDownEl.querySelector('.pullDownLabel').innerHTML = 'Loading...';                
                    pullDownAction();   // Execute custom function (ajax call?)
                } 
            }
        });

        setTimeout(function () { document.getElementById('wrapper').style.left = '0'; }, 800);
    }


    document.addEventListener('touchmove', function (e) { e.preventDefault(); }, false);

    document.addEventListener('DOMContentLoaded', function () { setTimeout(loaded, 200); }, false);

and last but not the least the main infinitescroll.js recall that we had previously placed a call to this function in pulltorefresh.js where we said if scroll bar is 10px to the end inifite scroll should be triggered. Then we have this as the shot to be fired.

function doInfinite_scroll()
{
        var last_id = $('#last_id').val();
        var searching = false;
        if (!searching) { // only initiate a new ajax request if this variable is false this is to avoid data duplication.
        var el;
        el = document.getElementById('responsecontainer');
        var url = "http://localhost/public_html/landing_more.php?last_id="+last_id+"&token=9876543456789765432456789876543&valid=jhjhjjhjhkhj";
        // -------------------------------------------

        $.ajax({
        type: 'GET',
        url: url,
        contentType: "application/json; charset=utf-8",
        dataType: "jsonp",
        // Evaluate text as a json expression
        converters: {"text jsonp": jQuery.parseJSON},
        timeout:30000,
        async: true,
        jsonp: true,
        jsonpCallback: "myJsonMethod",
        error: function(){
        myScroll.refresh(); //do nofin
        },
        beforeSend: function()
        {
        //add loading image i dint bcos the image or values becomes double in a case of network delay
        searching = true; // set variable to true
        },
        success: function(data){
        searching = false; // set variable to false
       //console.dir('success');
        ajax.parseJSONP(data);

        }
        });
        $.ajaxSetup({ cache: false });//fetch data from db not cache content
        var ajax = {  

        parseJSONP:function(data){
        $.each(data, function(i, row) {


        var ul = '<ul>'+row.comments+'</ul>';
        if (i==1) //bcos its php data limit was set to 2 so its always N-1 i.e yourlimit - 1
        {
        //resset lastdeed id value
        $('#lastdeed_id').val(row.id_comments); //update the value in the hidden input field to enable the next set of data load properly
        } 
        $(ul).appendTo(el);
        myScroll.refresh();     // Remember to refresh when contents are loaded (ie: on ajax completion)

});
}
}
}
}

so just in case you are lost with what the php file should look like here you go. This file is landing.php

<?php
// Prevent caching.
header('Cache-Control: no-cache, must-revalidate');
header('Expires: Mon, 01 Jan 1996 00:00:00 GMT');

if ((isset($_GET['token'])) && (isset($_GET['valid']))) {

@require_once('connect/connectionfile.php');  

$token=htmlspecialchars($_GET['token'],ENT_QUOTES);
$token= mysql_real_escape_string($token);
$valid=htmlspecialchars($_GET['valid'],ENT_QUOTES);
$valid= mysql_real_escape_string($valid);


//now validating the token
$sql="SELECT * FROM bla WHERE blabla='$token'";
$result=mysql_query($sql);

//if token exists
if(mysql_num_rows($result))
{
 header('Content-type: application/json');
//valid token
 $fakevalue = mysql_fetch_assoc($result);
 $uid = $fakevalue['id'];
 $results = array();
 $query = "SELECT * FROM bla bal WHERE bla bla bla DESC LIMIT 0, 5";
 $rsult = mysql_query($query);
 while($value = mysql_fetch_assoc($rsult, MYSQL_ASSOC))
 $results[] = $value;
 {
 echo "myJsonMethod".'('.json_encode($results).')'; //ECHO RESULTS IN JSONP FORMAT

}

}
else 
{
 //Invalid token
 header('Content-type: application/json');
 echo "myJsonMethod({\"token\":".utf8_encode(json_encode('failed'))."})";
}
}
else {
    header('Content-type: application/json');
    echo "myJsonMethod({\"token\":".utf8_encode(json_encode('Invalid token check parameters'))."})";
    }
?>

this next file is for infinite scrolling and it is called landing_more.php

<?php
// Prevent caching.
header('Cache-Control: no-cache, must-revalidate');
header('Expires: Mon, 01 Jan 1996 00:00:00 GMT');

if ((isset($_GET['token'])) && (isset($_GET['validator']))) {

@require_once('connect/connectionfile.php');  


$token=htmlspecialchars($_GET['token'],ENT_QUOTES);
$token= mysql_real_escape_string($token);
$validator=htmlspecialchars($_GET['validator'],ENT_QUOTES);
$validator= mysql_real_escape_string($validator);
$last_id=htmlspecialchars($_GET['last_id'],ENT_QUOTES);
$last_id=mysql_real_escape_string($last_id);


//now validating the token
$sql="SELECT * FROM bla WHERE blabla='$token'";
$result=mysql_query($sql);

//if token exists
if(mysql_num_rows($result))
{
 header('Content-type: application/json');
//valid token
 $fakevalue = mysql_fetch_assoc($result);
 $uid = $fakevalue['id'];
 $results = array();
 $query = "SELECT * FROM bla bla WHERE bla && bla bla && a.id_comments < '$last_id' ORDER BY a.id_comments DESC LIMIT 0, 2";
 $rsult = mysql_query($query);
 while($value = mysql_fetch_assoc($rsult, MYSQL_ASSOC))
 $results[] = $value;
 {
 echo "myJsonMethod".'('.json_encode($results).')'; //ECHO RESULTS IN JSONP FORMAT

}

}
else 
{
 //Invalid token
 header('Content-type: application/json');
 echo "myJsonMethod({\"token\":".utf8_encode(json_encode('failed'))."})";
}
}
else {
    header('Content-type: application/json');
    echo "myJsonMethod({\"token\":".utf8_encode(json_encode('Invalid token check parameters'))."})";
    }
?>
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!