使用Lungo.js支持HTML5实现相仿微博的“拖拽刷新”功能

使用Lungo.js支持HTML5实现类似微博的“拖拽刷新”功能

       最近要在手机端的HTML5里面实现一个类似新浪微博的“Pull & Refresh”的功能,时间紧迫,一时找不到比较好用的框架,发现Lungo还不错,于是试用了一下,发现还不错,轻量小巧。

       Lungo很多函数与JQuery差不多,比如mix()isOwnProperty()、toType(),另外因为我使用BootStrap,很多功能与Lungo重复,因此Lungo的很多组件我用不上,没有细致的研究。不过,最坑爹的是,我要用的Pull & Refresh它只支持从顶部下拉刷新,不支持从底部往上刷新!

       好吧!暂时找不到其它框架,那就自己动手修改一下吧使用Lungo.js支持HTML5实现相仿微博的“拖拽刷新”功能

 

       由于Lungo的css与Bootstrap的css冲突了,没有全部引用Lungo的css,并且自己加了不少样式,所以单独出来,只包含Pull & Refresh的部分,代码如下:

/* Pull & Refresh */
body>section.show {
    -webkit-box-ordinal-group: 2;
    -moz-box-ordinal-group: 2;
    -ms-box-ordinal-group: 2;
    -o-box-ordinal-group: 2;
    box-ordinal-group: 2;
    display: -webkit-box;
    display: -moz-box;
    display: -ms-box;
    display: -o-box;
    display: box;
    position: relative;
}

body>aside.show>article.active.pull,
body>section.show>article.active.pull,
body>aside.hide>article.active.pull,
body>section.hide>article.active.pull,
body>aside.hiding>article.active.pull,
body>section.hiding>article.active.pull
    {
    -webkit-transition-property: transform;
    -moz-transition-property: transform;
    -ms-transition-property: transform;
    -o-transition-property: transform;
    transition-property: transform;
    -webkit-transition-duration: 500ms;
    -moz-transition-duration: 500ms;
    -ms-transition-duration: 500ms;
    -o-transition-duration: 500ms;
    transition-duration: 500ms
}

section.show>[data-control="pull"]>.loading {
    position: relative;
    width: 25px;
    color: #ff8612;
    font-size: 12px;
    line-height: 1; /* 1倍行距,否则不能居边对齐 */
}

section.hide>[data-control="pull"] {
    display: none
}

section.show>[data-control="pull"] {
    position: absolute;
    z-index: -1;
    top: 0;
    line-height: 60px;
    width: 100%;
    height: 80px;
    padding: 10px 0;
    text-align: center;
}

section.show>[data-control="pull"]>.icon {
    display: inline-block;
    width: 25px;
    color: #ff8612;
    font-size: 12px;
    line-height: 1;
    -webkit-backface-visibility: hidden;
    -moz-backface-visibility: hidden;
    -ms-backface-visibility: hidden;
    -o-backface-visibility: hidden;
    backface-visibility: hidden;
    -webkit-transition: all .2s ease-in-out;
    -o-transition: all .2s ease-in-out;
    transition: all .2s ease-in-out;
}

section.show>[data-control="pull"]>.loading {
    display: none;
    left: 0%
}

section.show>[data-control="pull"]>.msg {
    position: relative;
    color: #ff8612;
    font-size: 12px;
    font-weight: normal;
    line-height: 1; /* 1倍行距,否则不能居边对齐 */
    display: inline-block;
}

section.show>[data-control="pull"].rotate>.icon {
    -webkit-transform: rotate(-180deg);
    -moz-transform: rotate(-180deg);
    -ms-transform: rotate(-180deg);
    -o-transform: rotate(-180deg);
    transform: rotate(-180deg);
    -webkit-transition: all .2s ease-in-out;
    -o-transition: all .2s ease-in-out;
    transition: all .2s ease-in-out;
}

section.show>[data-control="pull"].refresh>.icon {
    display: none
}

section.show>[data-control="pull"].refresh>.loading {
    display: inline-block
}

section.show>[data-control="pull"].pulling-down {
    top: 0;
    bottom: auto;
}
section.show>[data-control="pull"].pulling-up {
    top: auto;
    bottom: 0;
}

section.show>[data-control="pull"].pulling-down .pullup.icon {
    display: none;
}
section.show>[data-control="pull"].pulling-up .pulldown.icon {
    display: none;
}

section.show>[data-control="pull"].pulling-down>.icon,
 section.show>[data-control="pull"].pulling-down>.loading,
 section.show>[data-control="pull"].pulling-down>.msg {
    vertical-align: top;
}

section.show>[data-control="pull"].pulling-up>.icon,
 section.show>[data-control="pull"].pulling-up>.loading,
 section.show>[data-control="pull"].pulling-up>.msg {
    vertical-align: bottom;
}

/* Pull & Refresh end */

 

    然后,重新实现了Pull组件,要用的话可以将如下代码替换Lungo.js中与Pull相关的那部分,JavaScript代码如下:

/**
 * Creates a instance of Pull & Refresh Element。<br>
 * 增加功能:在原来的Pull Down & Refresh的基础上,支持Pull Up & Refresh。
 * 
 * @namespace Lungo.Element
 * @class Pull
 * @version 1.0
 * 
 * @author Ignacio Olalde <ina@tapquo.com> || @piniphone
 * @author Javier Jimenez Villar <javi@tapquo.com> || @soyjavi
 * @author fbchen <fbchen@fourbin.com>
 */
(function() {
    // 修改loading的样式
    Lungo.Attributes['loading'] = {
        selector : "*",
        html : '<span class="loading {{value}}"></span>'
    };
    Lungo.Attributes['pull'] = {
        selector : "*",
        html : '<div data-control="pull" data-icon="pulldown {{value}}" data-loading="fa fa-spinner fa-spin"><span class="msg"></span></div>'
    };
    
    Lungo.Element.Pull = function(element_selector, config_data) {
        var ANIMATION_TIME, CONFIG_BASE, CONTAINER, CURRENT_DISTANCE, ELEMENT,
            MAX_HEIGHT, REFRESHING, REFRESHING_HEIGHT, PULLING_DOWN,
            hide, _blockGestures, _getTouchY, _handlePullEnd, _handlePulling, _moveElementTo,
            _refreshStart, _setContainerLoading, _setContainerOnPulling, _setContainerTitle,
            UP = void 0,
            DOWN = void 0,
            isOwnProp = Lungo.Core.isOwnProperty,
            pullUpIcon;
        REFRESHING_HEIGHT = 68;
        MAX_HEIGHT = 80;
        ANIMATION_TIME = 300;
        CURRENT_DISTANCE = 0;
        PULLING_DOWN = true;
        REFRESHING = false;
        ELEMENT = $$(element_selector);
        CONTAINER = ELEMENT.siblings("div[data-control=\"pull\"]");
        CONFIG_BASE = {
            onPull : "Pull down to refresh",
            onRelease : "Release to...",
            onRefresh : "Loading...",
            callback : void 0
        };
        
        // 分出pull down、pull up的配置,为了向后兼容,默认都是pull down
        UP = Lungo.Core.mix(CONFIG_BASE, config_data['up']);
        DOWN = Lungo.Core.mix(CONFIG_BASE, config_data['down']);
        if (!isOwnProp(config_data, 'up') && !isOwnProp(config_data, 'down')) {
            DOWN = Lungo.Core.mix(CONFIG_BASE, config_data);
        }
        
        // 注入data-pullup图标
        pullUpIcon = UP.icon || ELEMENT.parent().data('pullup');
        if (pullUpIcon) {
            CONTAINER.prepend('<span class="pullup icon ' + pullUpIcon + '"></span>');
        }
        
        hide = function() {
            _moveElementTo(0, true);
            setTimeout((function() {
                        REFRESHING = false;
                        CONTAINER.attr("class", "");
                        return ELEMENT[0].removeEventListener("touchmove",
                                _blockGestures, true);
                    }), ANIMATION_TIME);
            return CURRENT_DISTANCE = 0;
        };
        _moveElementTo = function(posY, animate) {
            var newPos;
            newPos = Math.abs(posY) > MAX_HEIGHT ? (posY < 0 ? -1 * MAX_HEIGHT : MAX_HEIGHT) : posY;
            if (animate) {
                ELEMENT.addClass("pull");
            } else {
                ELEMENT.removeClass("pull");
            }
            ELEMENT.style("-webkit-transform", "translate(0, " + newPos + "px)");
            if (animate) {
                return setTimeout((function() {
                            return ELEMENT.removeClass("pull");
                        }), ANIMATION_TIME);
            }
        };
        _refreshStart = function(event) {
            REFRESHING = true;
            ELEMENT[0].addEventListener("touchmove", _blockGestures, true);
            _setContainerTitle(_getConf().onRefresh);
            _setContainerLoading(true);
            _moveElementTo(PULLING_DOWN ? REFRESHING_HEIGHT : -1 * REFRESHING_HEIGHT, true);
            if (_getConf().callback) {
                return _getConf().callback.apply(this);
            }
        };
        _setContainerTitle = function(title) {
            return CONTAINER.find(".msg").html(title);
        };
        _setContainerLoading = function(op) {
            _setContainerPosition();
            if (op) {
                return CONTAINER.addClass("refresh");
            } else {
                return CONTAINER.removeClass("refresh");
            }
        };
        _setContainerOnPulling = function(op) {
            _setContainerPosition();
            if (op) {
                return CONTAINER.addClass("rotate");
            } else {
                return CONTAINER.removeClass("rotate");
            }
        };
        _setContainerPosition = function() {
            if (PULLING_DOWN) {
                CONTAINER.removeClass("pulling-up").addClass("pulling-down");
            } else {
                CONTAINER.removeClass("pulling-down").addClass("pulling-up");
            }
        }
        _getConf = function() {
            return PULLING_DOWN ? DOWN : UP;
        };
        _blockGestures = function(touchEvent) {
            return touchEvent.preventDefault();
        };
        _handlePulling = function(event) {
            _moveElementTo(PULLING_DOWN ? CURRENT_DISTANCE : -1 * CURRENT_DISTANCE, false);
            _setContainerLoading(false);
            if (CURRENT_DISTANCE > REFRESHING_HEIGHT) {
                _setContainerTitle(_getConf().onRelease);
                return _setContainerOnPulling(true);
            } else {
                _setContainerTitle(_getConf().onPull);
                return _setContainerOnPulling(false);
            }
        };
        _handlePullEnd = function(event) {
            if (CURRENT_DISTANCE > REFRESHING_HEIGHT) {
                _refreshStart();
            } else {
                hide();
            }
            return this;
        };
        _getTouchY = function(event) {
            if ($$.isMobile()) {
                return event.touches[0].pageY;
            } else {
                return event.pageY;
            }
        };
        (function() {
            var INI_Y, STARTED, dt;
            STARTED = false;
            INI_Y = 0;
            return ELEMENT.bind("touchstart", function(event) {
                        if (ELEMENT[0].scrollTop <= 1) {
                            STARTED = true;
                            INI_Y = _getTouchY(event);
                        }
                        return true;
                    }).bind("touchmove", function(event) {
                        var current_y;
                        if (!REFRESHING && STARTED) {
                            current_y = _getTouchY(event);
                            dt = current_y - INI_Y;
                            PULLING_DOWN = dt > 0;
                            CURRENT_DISTANCE = Math.abs(dt);
                            _handlePulling(event);
                            if (event.cancelable !== false) {
                                event.preventDefault();
                            }
                        }
                        return true;
                    }).bind("touchend", function() {
                        if (STARTED) {
                            _handlePullEnd();
                        }
                        STARTED = false;
                        return true;
                    });
        })();
        return {
            hide : hide
        };
    };

}).call(this);

 

     最后是HTML测试页面,模拟手机端的“拖拽”功能,可以用Chrome打开,用浏览器自带的“开发者工具”,切换到Device模式调试。HTML页面如下:

    

<!DOCTYPE html>
<html lang="zh-cn">
<head>
    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <title>Pull &amp; Refresh</title>

    <!-- Bootstrap -->
    <link type="text/css" rel="stylesheet" href="./js/bootstrap3.2/css/bootstrap.min.css">
    <link type="text/css" rel="stylesheet" href="./css/font-awesome-4.2.0/css/font-awesome.min.css">
    <link type="text/css" rel="stylesheet" href="./css/zyb/app.css">
    <style type="text/css">
    .article {
        background-color: beige;
    }
    h1 {
        background-color: azure;
        margin-bottom: 0;
        margin-top: 100px;
    }
    </style>
</head>
<body>
<h1>测试下拉刷新功能</h1>


<!-- 内容列表 -->
<section id="articleList" data-transition="slide" data-pull="fa fa-long-arrow-down" data-pullup="fa fa-long-arrow-up">
    <article class="article">
        <div title="下拉文章内容刷新">
            文章内容<br>
            文章内容<br>
            文章内容<br>
            文章内容<br>
        </div>
    </article>
</section>

<script type="text/javascript" src="./js/jquery/jquery-1.11.1.min.js"></script>
<script type="text/javascript" src="./js/bootstrap3.2/js/bootstrap.min.js"></script>
<!-- 支持 Pull & Refresh -->
<script type="text/javascript" src="./js/quojs-2.3.6/quo.js"></script>
<script type="text/javascript" src="./js/lungo-2.2.1/lungo-1.js"></script>
<script>
$(function(){
    
    Lungo.init({});
    var pull_example = new Lungo.Element.Pull('#articleList article', {
        down: {
        	onPull: '下拉刷新',      // Text on pulling
            onRelease: '释放更新',   // Text on releasing
            onRefresh: '加载中...',  // Text on refreshing
            callback: function() { // Action on refresh
                //alert('Pull & Refresh completed!');
                setTimeout(function() {
                    pull_example.hide();
                }, 3000);
            }
        },
        up: {
            onPull: '上推刷新',      // Text on pulling
            onRelease: '释放更新',   // Text on releasing
            onRefresh: '加载中...',  // Text on refreshing
            callback: function() { // Action on refresh
                //alert('Pull & Refresh completed!');
                setTimeout(function() {
                    pull_example.hide();
                }, 3000);
            }
        }
    });
    
});
</script>
</body>
</html>

 

    效果如下:

    
使用Lungo.js支持HTML5实现相仿微博的“拖拽刷新”功能


 
使用Lungo.js支持HTML5实现相仿微博的“拖拽刷新”功能


 
使用Lungo.js支持HTML5实现相仿微博的“拖拽刷新”功能