handlebars+iscroll异步加载页面

本文介绍使用Handlebars模板引擎与iScroll库实现移动端网页异步加载功能的方法。通过Java后端处理业务类型列表,并将其传递给前端;前端采用Handlebars模板引擎解析数据并展示,结合iScroll实现流畅的滚动体验及上下拉刷新加载功能。

handlebars+iscroll异步加载页面

一、Java代码:

List<Map> mapList = new ArrayList();
for(TSType s : businessTypeList){
    Map map = new HashMap();
    map.put("id", s.getId());
    map.put("typecode", s.getTypecode());
    map.put("typename", MutiLangUtil.getMutiLangInstance().getLang(s.getTypename()));
    mapList.add(map);
}
net.sf.json.JSONArray jsonArray = net.sf.json.JSONArray.fromObject(mapList);
request.setAttribute("businessTypeList", jsonArray.toString());

return new ModelAndView("com/letv/gcr_mobile/task_to_sign/myToSignTaskList");

二、JSP页面:
1.myToSignTaskList.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8"%>
<%@ taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<%@ taglib prefix="fn" uri="http://java.sun.com/jsp/jstl/functions"%>
<%@ taglib prefix="fmt" uri="http://java.sun.com/jsp/jstl/fmt"%>
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">

<html>
    <head>
        <title>我的待签收事项</title>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <%@include file="/webpage/letv_common/mobile/letv_gcr_mobile_head_boot.jsp"%>

        <script type="text/javascript" src="<%=basePath%>/webpage/com/letv/gcr_mobile/task_to_sign/js/myToSignTaskList.js"></script>
        <script type="text/javascript">
            var date_fmt = "yyyy-MM-dd hh:mm:ss";
            Handlebars.registerHelper('dateFormat', function(date, format,options) {
                return new Date().StringFormat(date,date_fmt);
            });

            var businessTypeList = ${businessTypeList};
            Handlebars.registerHelper('businessType_Value', function(businessType, options) {
                var typename = businessType;
                $.each(businessTypeList, function(i, n) {
                    if (businessType == n.typecode) {
                        typename = n.typename;
                        return false
                    }
                });
                return typename;
            });
        </script>
        <script id="myToSignTaskList_template" type="text/x-handlebars-template">
            {{#each this}}
                <li task_id="{{id}}">
                    <div class="c_b">
                        <div class="checkboxOne">
                            <input type="checkbox" value="{{bpmBizNum}}" id="checkboxInput_{{id}}" name="" />
                            <label for="checkboxInput_{{id}}"></label>
                        </div>
                    </div>
                    <div class="tit">{{bpmBizTitle}}-{{bpmBizNum}}</div>
                    <div class="row"><!-- 内容线 --><t:mutiLang langKey="common.business.line"/>: {{businessType_Value businessType}}<span class="pre50"></span></div>
                    <div class="row"><!-- 环节开始时间 --><t:mutiLang langKey="common.start.time.of.current.node"/>{{dateFormat startTime}}</div>
                    <div class="row"><!-- 提交人 --><t:mutiLang langKey="common.Submitter"/>:{{originator}}</div>
                    <div class="row"><!-- 事项发起时间 --><t:mutiLang langKey="common.matters.start.time"/>:{{dateFormat startTime}}</div>
                </li>
            {{/each}}
        </script>
    </head>

    <body>
        <form id="pageForm" method="post" name="contract_search_form" action="<%=basePath%>/task_to_sign_MobileController.do?my_to_sign_task_list_page">
            <!-- 隐藏域 -->
            <input type="hidden" id="sortStartTime" name="sort_start_time" value="desc" />
            <input type="hidden" id="sortBusinessType" name="sort_business_type" value="desc" />
            <input type="hidden" id="sortBpmBizTitle" name="sort_bpm_biz_title" value="desc" />

            <!-- 顶部导航 start-->
            <%@include file="/webpage/com/letv/gcr_mobile/my_task/my_task_top.jsp"%>
            <!-- 顶部导航 end-->

            <!-- 内容主体 start -->
            <div class="wrapper">

                <!-- 一级页签 -->
                <c:set var="task_type" value="TaskToSign" />
                <%@include file="/webpage/com/letv/gcr_mobile/my_task/my_task_tab.jsp"%>

                <!-- 按条件排序(图标灰色调叠加class名为 .icon-gray) -->
                <div class="filter" style="display: block;">
                    <ul>
                        <li id="by_time" class="cur"><!-- 按日期 --><t:mutiLang langKey="common.by_time"/><em class="arrow-b"></em></li>
                        <li id="by_business_line"><!-- 按内容线 --><t:mutiLang langKey="common.by_business_line"/><em></em></li>
                        <li id="by_item_type"><!-- 按事项类型 --><t:mutiLang langKey="common.by_item_type"/><em></em></li>
                    </ul>
                </div>

                <c:set var="wrapper_top" value="125" />
                <%@include file="/webpage/letv_common/mobile/letv_mobile_pull_down.jsp"%>
                <div id="pageQueryList">
                    <section>
                        <ul id="my_to_sign_task_list" class="list_mywork qs r7_3">

                        </ul>
                    </section>
                </div>
                <%@include file="/webpage/letv_common/mobile/letv_mobile_pull_up.jsp"%>
                <%@include file="/webpage/letv_common/mobile/letv_mobile_page_cond.jsp"%>
            </div>
            <!-- 内容主体 end -->

            <!-- 底部签收 start -->
            <div class="footer">
                <div class="f_fx">
                    <div class="inner">
                        <div id="div_sign_task" class="ft_cont">
                            <em class="img icon-qs"></em>
                            <span class="blue">签收</span>
                        </div>
                    </div>
                </div>
            </div>
            <!-- 底部签收 end -->
        </form>

        <!--加载  -->
        <%@include file="/webpage/letv_common/mobile/letv_gcr_mobile_load.jsp"%>
    </body>
</html>

2.letv_mobile_pull_down.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<div id="wrapper" style="top:${wrapper_top}px; bottom:${wrapper_bottom}px;">
    <div id="scroller">
        <div id="pullDown" style="text-align: center; display:none;">
            <span class="pullDownIcon"></span>
            <span class="pullDownLabel">下拉刷新数据...</span>
        </div>

3.letv_mobile_pull_up.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false"%>
        <div id="pullUp" style="text-align: center;display: none;">
            <span class="pullUpIcon"></span>
            <span class="pullUpLabel">上拉加载更多数据...</span>
        </div>
    </div>
</div>

4.letv_mobile_page_cond.jsp

<%@ page language="java" contentType="text/html; charset=UTF-8" pageEncoding="UTF-8" isELIgnored="false"%>
<%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core"%>
<input type="hidden" id="currentPage" name="page" value="1" />
<input type="hidden" id="defaultRows" name="rows" value="5" />
<script type="text/javascript">
    var myScroll, pullDownEl, pullDownOffset, pullUpEl, pullUpOffset, generatedCount = 0;

    function pullDownAction() { // 下拉函数统一调用
        /* 
        setTimeout(function() { // 下拉时间结束,执行
            //页面重新加载
            var posturl = $("#pageForm").attr("action");
            window.location.href = posturl;
        }, 1000); */
    }

//  function pullUpAction() {
//      setTimeout(function() { // <-- Simulate network congestion, remove setTimeout from production!
//          var el, li, i;
//          el = document.getElementById('pageQueryList');
//          for (i = 0; i < 3; i++) {
//              li = document.createElement('li');
//              li.innerText = 'Generated row ' + (++generatedCount);
//              el.appendChild(li, el.childNodes[0]);
//          }
//          myScroll.refresh(); // Remember to refresh when contents are loaded (ie: on ajax completion)
//      }, 1000); // <-- Simulate network congestion, remove setTimeout from production!
//  }

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

        myScroll = new iScroll('wrapper',{
            useTransition : true,
            topOffset : pullDownOffset,
            onRefresh: function () {
                if (pullDownEl.className.match('loading')) {
                    pullDownEl.className = '';
                    pullDownEl.querySelector('.pullDownLabel').innerHTML = '下拉刷新';
                } else if (pullUpEl.className.match('loading')) {
                    pullUpEl.className = '';
                    pullUpEl.querySelector('.pullUpLabel').innerHTML = '上拉加载更多';
                }
            },
            onScrollMove: function () {
                if (this.y > 5 && !pullDownEl.className.match('flip')) {
                    pullDownEl.className = 'flip';
                    pullDownEl.querySelector('.pullDownLabel').innerHTML = '松开刷新';
                    this.minScrollY = 0;
                } else if (this.y < 5 && pullDownEl.className.match('flip')) {
                    pullDownEl.className = '';
                    pullDownEl.querySelector('.pullDownLabel').innerHTML = '下拉刷新';
                    this.minScrollY = -pullDownOffset;
                } else if (this.y < (this.maxScrollY - 10) && !pullUpEl.className.match('flip')) {
                    pullUpEl.style.display = 'block';
                    pullUpEl.className = 'flip';
                    pullUpEl.querySelector('.pullUpLabel').innerHTML = '松开刷新';
                    this.maxScrollY = this.maxScrollY;
                } else if (this.y > (this.maxScrollY + 10) && pullUpEl.className.match('flip')) {
                    pullUpEl.style.display = 'block';
                    pullUpEl.className = '';
                    pullUpEl.querySelector('.pullUpLabel').innerHTML = '上拉加载更多';
                    this.maxScrollY = pullUpOffset;
                }
            },
            onScrollEnd: function () {
                if (pullDownEl.className.match('flip')) {
                    pullDownEl.className = 'loading';
                    pullDownEl.querySelector('.pullDownLabel').innerHTML = '加载中';              
                    pullDownAction();   // Execute custom function (ajax call?)
                } else if (pullUpEl.className.match('flip')) {
                    pullUpEl.className = 'loading';
                    pullUpEl.querySelector('.pullUpLabel').innerHTML = '加载中';
                    pullUpEl.style.display = 'none';
                    pullUpAction(); // 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);
</script>

三、JavaScript代码:

$(function() {
    // 加载第1页数据
    getData(1);

    $("#by_time").click(function() { // 按时间排序
        $("#sortStartTime").attr("value", "desc");
        $("#sortBusinessType").attr("value", "");
        $("#sortBpmBizTitle").attr("value", "");

        $(".filter .cur").removeClass('cur');
        $(this).addClass('cur');
        $(".filter em").removeClass('arrow-b');
        $(this).find('em').addClass('arrow-b');

        $("#my_to_sign_task_list").html("");
        selectBool = true;
        getData(1);
    });

    $("#by_business_line").click(function() { // 按内容线排序
        $("#sortStartTime").attr("value", "");
        $("#sortBusinessType").attr("value", "desc");
        $("#sortBpmBizTitle").attr("value", "");

        $(".filter .cur").removeClass('cur');
        $(this).addClass('cur');
        $(".filter em").removeClass('arrow-b');
        $(this).find('em').addClass('arrow-b');

        $("#my_to_sign_task_list").html("");
        selectBool = true;
        getData(1);
    });

    $("#by_item_type").click(function() { // 按事项类型排序
        $("#sortStartTime").attr("value", "");
        $("#sortBusinessType").attr("value", "");
        $("#sortBpmBizTitle").attr("value", "desc");

        $(".filter .cur").removeClass('cur');
        $(this).addClass('cur');
        $(".filter em").removeClass('arrow-b');
        $(this).find('em').addClass('arrow-b');

        $("#my_to_sign_task_list").html("");
        selectBool = true;
        getData(1);
    });



    $("#div_sign_task").click(function() { // 签收
        var ids = "";
        $("input:checkbox[id^='checkboxInput_']:checked").each(function(i) {
            //alert($(this).attr("checked"));
            if(i==0) {
                ids = $(this).val();
            } else {
                ids += (";" + $(this).val());
            }
        });
        //alert(ids);

        var locationUrl = ROOF.Utils.projectName()+"/task_to_sign_MobileController.do?my_to_sign_task_list_page&ids="+ids;
        alert(locationUrl);
        //window.location.href = locationUrl;
    })
});

// 分页查询数据标志
var selectBool = true;

// 分页加载数据
function pullUpAction(c) { // 上拉函数重写,letv_mobile_page_cond.jsp里面用
    setTimeout(function() { // 上拉时间结束,执行
        var c = parseInt($("#currentPage").val());
        getData(c);
    }, 1000);
}

// 异步加载第c页的数据
function getData(c) {
    if(!selectBool) {
        return;
    }
    $("#currentPage").val(c);
    loadDiv();
    $.ajax({ 
        type: 'post', 
        dataType : "json", 
        url: ROOF.Utils.projectName() + "/task_to_sign_MobileController.do?query_my_to_sign_task_list",
        data: $("#pageForm").serialize(),
        success: function(d) {
            if(d.obj.results.length == 0) {
                selectBool = false;
                if(d.obj.pageCount==0){//没有记录
                    var v_mobile_search_message = "暂无数据!";
                    var sb = "<div style='width:100%;height:100px; line-height:100px;text-align:center'>"+v_mobile_search_message+"</div>";
                    $("#pageQueryList").html(/*"暂无数据"*/sb);
                } else {
                    var v_mobile_last_page = "已是最后一页!";
                    alert(/*"已是最后一页!"*/v_mobile_last_page);
                }
            } else {
                // 加载新数据
                var source = $("#myToSignTaskList_template").html();
                var template = Handlebars.compile(source);
                $("#my_to_sign_task_list").append(template(d.obj.results));
                $("#currentPage").val(c+1);
            }
            loadDiv();
            myScroll.refresh();
        }, 
        error:function(d) {
            alert(d.statusText);
            loadDiv();
        }
    }); 
}

四、引用的自定义js:

// 对Date的扩展,将 Date 转化为指定格式的String 
// 月(M)、日(d)、小时(h)、分(m)、秒(s)、季度(q) 可以用 1-2 个占位符, 
// 年(y)可以用 1-4 个占位符,毫秒(S)只能用 1 个占位符(是 1-3 位的数字) 
// 例子: 
// (new Date()).Format("yyyy-MM-dd hh:mm:ss.S") ==> 2006-07-02 08:09:04.423 
// (new Date()).Format("yyyy-M-d h:m:s.S")      ==> 2006-7-2 8:9:4.18 
Date.prototype.Format = function(fmt) 
{ //author: meizz 
  var o = { 
    "M+" : this.getMonth()+1,                 //月份 
    "d+" : this.getDate(),                    //日 
    "h+" : this.getHours(),                   //小时 
    "m+" : this.getMinutes(),                 //分 
    "s+" : this.getSeconds(),                 //秒 
    "q+" : Math.floor((this.getMonth()+3)/3), //季度 
    "S"  : this.getMilliseconds()             //毫秒 
  }; 
  if(/(y+)/.test(fmt)) 
    fmt=fmt.replace(RegExp.$1, (this.getFullYear()+"").substr(4 - RegExp.$1.length)); 
  for(var k in o) 
    if(new RegExp("("+ k +")").test(fmt)) 
  fmt = fmt.replace(RegExp.$1, (RegExp.$1.length==1) ? (o[k]) : (("00"+ o[k]).substr((""+ o[k]).length))); 
  return fmt; 
}

Date.prototype.StringFormat = function(str, fmt) {
    if(!str){
        return '';
    }
    var d = new Date(str);
    return d.Format(fmt);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值