-
Notifications
You must be signed in to change notification settings - Fork 11
feilongDisplay pager
分页是商城乃至整个互联网应用最常用的功能之一,好的分页标签及方案可以降低开发的复杂度和维护量,缩短工程师的开发时间.
面向具有一定的网站开发能力,了解 JAVA、JSP 等开发语言的网站开发、维护人员
术语 |解释
:---- |:---------
taglib |自定义标签
pager |分页
velocity |是apache基金会的一个java模板引擎(`template engine`),参见 http://velocity.apache.org/
Jsp |全名为`Java Server Pages`,是由Sun 倡导、许多公司参与建立的一种动态网页技术标准,参见 http://www.oracle.com/technetwork/java/javaee/jsp/index.html
properties |properties文件是java中的一种配置文件,主要用于表达配置信息,文件类型为*.properties,格式为文本文件,文件的内容是格式是"键=值"的格式
I18n |来自英文单词 `internationalization` 的首末字符i和n,18为中间的字符数,是 `国际化` 的简称.
Ajax |即 `Asynchronous Javascript And XML`(异步JavaScript和XML),是指一种创建交互式网页应用的网页开发技术
-
支持
国际化
-
支持
Ajax
分页,参见 Ajax 分页使用步骤 -
当前页码
永远居中 -
内置页码输入文本框,支持快速跳转
如可实现以下功能:
-
支持类似于淘宝
最大分页码
100 这样的控制如可实现以下功能:
见参数 maxShowPageNo
-
分页页码
支持根据页码数字动态显示
页码个数比如当当前页码是1001页显示6个页码,当当前页码是101,显示8个页码,见参数 dynamicNavigationPageNumberConfig
-
自动识别是否是forwoad 连接
-
支持自定义velocity分页模版
见参数 vmPath
-
支持皮肤切换
内置26种皮肤 (需要引入feilong-pager.css), 如果您的网站有自己特殊的样式,可以重新修改vm模板结构或者按照皮肤结构自定义css特殊的皮肤(建议选择后者) 内置皮肤样式参见附录部分
-
经过大型项目检验,通用严格的安全扫描测试
Esprit,Nike,Underarmour,blanja,speedo 等大型项目都有使用该标签,并通过严格的安全扫描测试
示例: 当前页面路径
http://127.0.0.1:8088/pager?page=8&name=%E9%A3%9E%E5%A4%A9%E5%A5%94%E6%9C%88
带皮肤的页面效果:
跳转分页
顾名思义,点击分页页码,浏览器地址栏地址变更,显示新的页面
<%@ taglib prefix="feilongDisplay" uri="http://java.feilong.com/tags-display"%>
<feilongDisplay:pager count="${pagination.count}"/>
仅需要总数参数 count
即可,其余参数缺省,均使用默认值
<feilongDisplay:pager
count="${pagination.count}"
charsetType="utf-8"
dynamicNavigationPageNumberConfig="1000=6&100=8&1=10"
locale="zh_CN"
maxShowPageNo="-1"
pageParamName="page"
pageSize="10"
pagerHtmlAttributeName="feilongPagerHtml1"
skin="scott"
vmPath="velocity/feilong-default-pager.vm"
/>
每个参数的含义,请参见下面 参数表格部分
参数 | 说明 | 类型 | Since | 默认值 |
---|---|---|---|---|
count | 数据总数 | Integer | 1.0 | - |
参数 | 说明 | 类型 | Since | 默认值 |
---|---|---|---|---|
pageSize | 每一页显示多少个数据 | Integer | 1.0 | 20 |
pageParamName | url分页页码参数 | String | 1.0 | pageNo |
pagerHtmlAttributeName | vm被解析出来的文本,会被存在该变量中 | String | 1.0.5 | "feilongPagerHtml" |
locale | 国际化语言, 支持 java.util.Locale 或 String 类型的实例 |
Locale | 1.0.5 | request.getLocale() |
charsetType | url编码 | String | 1.0.5 | UTF-8 |
maxShowPageNo | 显示最大的页码数, (-1或者不设置,显示所有页数) 类似淘宝不管结果多少,最多显示100页 |
Integer | 1.0.5 | -1 |
vmPath | 基于classpath 下面的velocity模版文件路径 | String | 1.0 | "velocity/feilong-default-pager.vm" |
skin | 皮肤,内置24种常用皮肤 需要引入feilong-pager.css |
String | 1.0 | "digg" |
dynamicNavigationPageNumberConfig | 动态显示导航页码数量 | String | 1.9.2 | 1000=6&100=8&1=10 |
数据总数,(必需参数)
每一页显示多少个数据,默认 20
国际化语言,支持 java.util.Locale
或 String 类型的实例
注:since 1.7.2
<feilongDisplay:pager
...
locale="zh_CN"
.../>
假设服务器是英文语言
,某网站是简体中文
和繁体中文
两种语言,
如果是使用spring-mvc
,不能直接使用 ${requestScope['org.springframework.web.servlet.i18n.CookieLocaleResolver.LOCALE']}
,
该属性如果用户不切换网站语言,那么值是null,那么分页标签会使用默认值 request.getLocale()
,显示英文的分页标签,但是该网站其实没有英文的站点,那么就不符合站点要求
在每个标签上方,使用 spel
表达式(参见 http://docs.spring.io/spring/docs/current/spring-framework-reference/html/expressions.html),获得当前的网站语言
示例:
<%@ taglib prefix="spring" uri="http://www.springframework.org/tags"%>
<spring:eval var="locale" expression="T(org.springframework.web.servlet.support.RequestContextUtils).getLocale(pageContext.request)"></spring:eval>
<feilongDisplay:pager
...
locale="${locale}"
.../>
注:since 1.7.2
示例:
<%@ taglib prefix="flsp" uri="http://java.feilong.com/el-spring"%>
<feilongDisplay:pager
...
locale="${flsp:getLocale()}"
.../>
url分页页码参数,默认 pageNo
vm被解析出来的文本,会被存在在这个变量中,作用域为pageContext,以便重复使用, 默认值 feilongPagerHtml
url编码(默认是 utf-8
)
显示最大的页码数,(-1或者不设置,默认 -1
显示所有页数).
比如淘宝,不管搜索东西多少,最多显示100页
这是一种折中的处理方式,空间换时间. 数据查询越往后翻,对服务器的压力越大,速度越低,而且从业务上来讲商品质量也越差,所以就没有必要给太多了. 新浪微博的时间轴也只给出了10页,同样的折中处理.
基于classpath 下面的velocity模版文件路径,默认的velocity\feilong-default-pager.vm
,虽然已经包含了大部分需求功能,但是可能实际项目中可能有特殊的需求,因此可以使用自定义pager vm 模板
动态显示导航页码数量(默认是 1000=6&100=8&1=10
).
-
背景: 一般的分页标签是固定的分页页码数量,一般是10个,如果当前页码页码大于1000的时候,还是10条页码的显示(如1001,1002,1003,1004,1005,1006,1007,1008,1009,1010),那么页面分页会很长 ,可能打乱页面布局.因此使用动态显示导航页码数量
-
规则: 示例:
1000=6&100=8&1=10
- 含义:当当前页码>=1000的时候,显示6个页码;当当前页码>=100的时候显示8个页码;当当前页码>=1的时候,显示10个页码
- 设置规则类似于url的参数规则
- 分隔之后,key是当前页码参考值,value是显示页码数量,如果当前页码大于等于key的时候,那么页码的数量会显示值的数量,
比如上例中,如果当前页码是1001,那么分页页码会显示成6个, 而如果当前页码是5,那么会显示10个页码 - 顺序不限制,不需要值大的写前面,程序会自动排序,比如你可以写成
1=10&100=8&1000=6
- 如果参数里面有相同名字的key,那么转换的时候取第一个值,比如
1000=6&1000 =7&100=8&1=10
,有效数据为1000=6&100=8&1=10
- 默认是
1000=6&100=8&1=10
,如果设置为empty或者blank, 那么表示不使用动态显示的功能,永远显示10个页码 - 当然如果你需要不管什么时候都显示10个,除了将此值设置为empty或者blank外,你还可以设置为
1000=10&100=10&1=10
,值设置为相同
皮肤,默认 digg
参见 Ajax分页
在Pager vm模板中可以使用的参数有 6.1 PagerVMParam对象 以及 6.2 i18nMap对象 (国际化使用的文案)
变量名称 | 说明 | 类型 | since | 示例数据 |
---|---|---|---|---|
totalCount | 数据总数 | int | 1.0 | 1024 |
skin | 设定的皮肤 | String | 1.0 | digg |
currentPageNo | 当前页码 | int | 1.0 | 12 |
allPageNo | 总页数 | int | 1.0 | 103 |
prePageNo | 上一页页码 | int | 1.4.0 | 11 |
nextPageNo | 下一页页码 | int | 1.4.0 | 13 |
pagerType | 分页类型 | PagerType | 1.4.0 | REDIRECT |
preUrl | 上一页链接 | String | 1.0 | /pager?page=7&name=%E9%A3%9E%E5%A4%A9%E5%A5%94%E6%9C%88 |
nextUrl | 下一页链接 | String | 1.0 | /pager?page=9&name=%E9%A3%9E%E5%A4%A9%E5%A5%94%E6%9C%88 |
firstUrl | 第一页的链接 | String | 1.0 | /pager?page=1&name=%E9%A3%9E%E5%A4%A9%E5%A5%94%E6%9C%88 |
lastUrl | 最后一页的链接 | String | 1.0 | /pager?page=1000&name=%E9%A3%9E%E5%A4%A9%E5%A5%94%E6%9C%88 |
hrefUrlTemplate | 链接的模板,以便前端js替换 | 1.0 | /pager?page=-8888888&name=%E9%A3%9E%E5%A4%A9%E5%A5%94%E6%9C%88 | |
startIteratorIndex | 开始迭代索引编号 | int | 1.0 | 7 |
endIteratorIndex | 结束迭代索引编号 | int | 1.0 | 9 |
iteratorIndexMap | 循环 迭代索引map key是编号,value 是页面链接 | LinkedHashMap<Integer, String> | 1.0 | "7": "/pager?page=7&name=%E9%A3%9E%E5%A4%A9%E5%A5%94%E6%9C%88", "8": "/pager?page=8&name=%E9%A3%9E%E5%A4%A9%E5%A5%94%E6%9C%88", "9": "/pager?page=9&name=%E9%A3%9E%E5%A4%A9%E5%A5%94%E6%9C%88" |
pageParamName | 分页参数名称 | String | 1.0.6 | pageNo |
pagerUrlTemplate | 分页链接模板 | PagerUrlTemplate | 1.0.6 | "pagerUrlTemplate": { "href": "/pager?page=-88888888&name=%E9%A3%9E%E5%A4%A9%E5%A5%94%E6%9C%88", "templateValue": -88888888 }, |
将messages/feilong-pager.properties配置文件的key和value转成了i18nMap对象,可以在vm模板中直接使用配置文件中的参数
示例参见 8.3.messages/feilong-pager.properties
如:
div.digg a {border:1px solid #aad;padding:2px 5px;margin:2px;color:#009;text-decoration:none}
div.digg a:link {color:#009;}
div.digg a:visited {color:#009;}
div.digg a:hover {border:1px solid #009;color:#000;}
div.digg a:active {border:1px solid #009;color:#000;}
div.digg span.current {border:1px solid #009;padding:2px 5px;margin:2px;font-weight:bold;color:#fff;background:#009}
div.digg span.disabled {border:1px solid #999;padding:2px 5px;margin:2px;color:#777;}
其中 digg
是 皮肤名称,你也可以根据这样的层级结构,建个自己的皮肤
下图是内置皮肤 默认样式,您可以指定皮肤名字使用
#**
这是个示例或者默认的模板,通过这个模板,可以看到哪些变量可以使用
每个商城可以使用这个模板,也可以自定义模板来使用
该VM 可以取到两个变量:
pagerVMParam : 包含各种显示数字/链接 参数
i18nMap : 包含国际化信息
@version 1.0.0 2010-2-3 下午01:03:14
@version 1.0.5 May 3, 2014 1:44:08 PM
@since 1.0.0
*#
<div class="div_feilongPager ${pagerVMParam.skin}" style="text-align:left">
##总数
<span class="span_pagerInfo">${i18nMap.get('feilong-pager.text.totalCount')}${pagerVMParam.totalCount}</span>
##当前第${pagerVMParam.currentPageNo}页/共${pagerVMParam.allPageNo}页
<span class="span_pagerInfo" title="${i18nMap.get('feilong-pager.text.current')}${pagerVMParam.currentPageNo}${i18nMap.get('feilong-pager.text.pager')}/${i18nMap.get('feilong-pager.text.total')}${pagerVMParam.allPageNo}${i18nMap.get('feilong-pager.text.pager')}">${pagerVMParam.currentPageNo}/${pagerVMParam.allPageNo}</span>
##第一页不显示首页和上一页
#if(1 != ${pagerVMParam.currentPageNo})
<a pageNoValue="${pagerVMParam.prePageNo}" title="${i18nMap.get('feilong-pager.text.goto.pre')}" href="${pagerVMParam.preUrl}">${i18nMap.get('feilong-pager.text.prev')}</a>
##// 如果导航编号里面没有首页 则添加首页
##// 导航里面 是否有第一页, 如果从开始1索引 则已经包含的首页包含
#if (${pagerVMParam.startIteratorIndex} != 1)
<a pageNoValue="1" title="${i18nMap.get('feilong-pager.text.goto.first')}" href="${pagerVMParam.firstUrl}">1</a>
#end
#end
##开始迭代索引不等于1,并且开始迭代索引不等于2,显示3点
#if (${pagerVMParam.startIteratorIndex} != 1 && ${pagerVMParam.startIteratorIndex} != 2)
<span class="color_666">...</span>
#end
##循环所有的页码 显示导航编号
#foreach( ${entry} in ${pagerVMParam.iteratorIndexMap.entrySet()} )
##当前 直接是数字编号
#if(${entry.key}==${pagerVMParam.currentPageNo})
<span class="current">${entry.key}</span>
#else
##不是当前页面
<a pageNoValue="${entry.key}" title="${i18nMap.get('feilong-pager.text.goto')}${entry.key}${i18nMap.get('feilong-pager.text.pager')}" href="${entry.value}">${entry.key}</a>
#end
#end
##如果最后一个迭代索引不等于总页数,且最后一个迭代索引不等于总也是-1,那么 显示3点
#set($allPageNoTo1=${pagerVMParam.allPageNo} - 1)
#if (${pagerVMParam.endIteratorIndex} != ${pagerVMParam.allPageNo} && ${pagerVMParam.endIteratorIndex} != $allPageNoTo1)
<span class="color_666">...</span>
#end
##最后一页不显示下一页和末页
#if(${pagerVMParam.allPageNo}!=${pagerVMParam.currentPageNo})
## 如果导航编号里面没有尾页 则添加尾页
##导航里面是否有最后一页, 如果结束的位置是allPageNo 则已经包含的尾页
#if(${pagerVMParam.endIteratorIndex} != ${pagerVMParam.allPageNo})
##跳转到最后一页
<a pageNoValue="$!{pagerVMParam.allPageNo}" title="${i18nMap.get('feilong-pager.text.goto.last')}" href="${pagerVMParam.lastUrl}">$!{pagerVMParam.allPageNo}</a>
#end
##跳转到下一页
<a pageNoValue="${pagerVMParam.nextPageNo}" title="${i18nMap.get('feilong-pager.text.goto.next')}" href="${pagerVMParam.nextUrl}">${i18nMap.get('feilong-pager.text.next')}</a>
#end
<input type="text" value="${pagerVMParam.currentPageNo}" class="feilongGotoInput" pagerUrlTemplateHref="${pagerVMParam.pagerUrlTemplate.href}" templateValue="${pagerVMParam.pagerUrlTemplate.templateValue}" pageParamName="${pagerVMParam.pageParamName}"/>/${pagerVMParam.allPageNo}<button value="go">Go</button>
</div>
<script type="text/javascript">
$(function() {
##回车事件
$(".feilongGotoInput").keydown( function() {
if (event.keyCode == 13) {
var pageNoValue=$(this).val();
if(""!=pageNoValue&&pageNoValue>0){
var templateValue=$(this).attr("templateValue");
var pageParamName=$(this).attr("pageParamName");
var pagerUrlTemplateHref=$(this).attr("pagerUrlTemplateHref");
location.href=pagerUrlTemplateHref.replace(pageParamName+"="+templateValue,pageParamName+"="+pageNoValue);
}
}
});
});
</script>