sns 评论 ajax 分页 和二级 评论 ajax 分页 ssh2 实现 源码下组 jar 在jar_1 jar_2 下载 数据 mysql测试可以
经过周六日的研究 终于弄明白 ajax 分页的实现了。
基本上就是利用了 jquery 的一个函数
$("#id").load(url,function() {});
首先 进入 评论页面 -> load 评论 ,评论 再 -> load 子评论。
按照 组件开发的方式 编写分页标签。
package com.freewebsys.core.sns.taglib; import javax.servlet.jsp.JspException; import javax.servlet.jsp.tagext.TagSupport; import com.freewebsys.core.sns.page.PageConf; public class PageTaglib extends TagSupport { private String id;// 标识不同分页,当一个页面有多个分页时, private String action; private int start; private int limit; private int total; private String otherValue; private String theme; // 默认 分页跳转 js.兼容写法。兼容刷新分页 和 ajax分页。都调js函数。ajax要重写 goPage函数 private static final String DEFAULT_PAGE_JS = "<script type='text/javascript'>function goPage(url){location.href = url;}</script>"; // 分页 div 开始 private final String DEFAULT_THEME_BEGIN = "<div class='pagination' id='Pagination'>"; private final String MINI_THEME_BEGIN = "<div class='paginationMini' id='PaginationMini'>"; // 分页 div 结束 private final String DEFAULT_THEME_END = "</div>"; // 分页字符串 private final String PAGE_A = "<a href=\"javaScript:void(0);\" onclick=\"goPage('"; // 默认样式模板 @Override public int doStartTag() throws JspException { try { if (total <= limit) {// 如果还不够一页 就不显示 return super.doEndTag(); } // 初始化参数.每次独立计算.否则分页有问题. PageConf pageConf = new PageConf(start, limit, total); String ctx = pageContext.getServletContext().getContextPath() + "/"; ctx += action; if (action.indexOf("?") >= 0) {// 如果存在?号用& ctx += "&" + findOtherValue(); } else {// 否则用? ctx += "?" + findOtherValue(); } PageConf pageConfFirst = new PageConf(start, limit, total); String firstUrl = ctx; PageConf pageConfPrev = new PageConf(start, limit, total); String prevUrl = ctx; PageConf pageConfNext = new PageConf(start, limit, total); String nextUrl = ctx; PageConf pageConfLast = new PageConf(start, limit, total); String lastUrl = ctx; // pageContext.setAttribute("gridPanelWidth", width); // pageContext.setAttribute("gridPanelHeight", height); if (pageConf.hastPrevious()) { pageConfFirst.getFirst(); firstUrl += "&start=" + pageConfFirst.getStart(); pageConfPrev.getPrevious(); prevUrl += "&start=" + pageConfPrev.getStart(); } if (pageConf.hasNext()) { pageConfNext.getNext(); nextUrl += "&start=" + pageConfNext.getStart(); pageConfLast.getLast(); lastUrl += "&start=" + pageConfLast.getStart(); } // 直接将数据写到页面 String str = genCenterButtons(start, limit, total, ctx); if (theme == null || theme.equals("")) { writeToPage(DEFAULT_PAGE_JS);// 默认跳转函数 writeToPage(DEFAULT_THEME_BEGIN); writeToPage(str); } else if (theme.equals("ajax")) {// 普通ajax分页 writeToPage(DEFAULT_THEME_BEGIN); writeToPage(str); } else if (theme.equals("miniAjax")) {// mini型ajax分页 writeToPage(MINI_THEME_BEGIN); if (id != null) {//标识不用分页 str = str.replace("goPage", "goMiniPage_" + id); } else { str = str.replace("goPage", "goMiniPage"); } writeToPage(str); } // 如果是ajax就要在页面重写goPage函数 writeToPage(DEFAULT_THEME_END); } catch (Exception e) { e.printStackTrace(); } return super.doEndTag(); } /** * 生成多个跳转按钮方法,如1,2,3,4,5这样的按钮跳转最大7页跳转 */ private String genCenterButtons(int start, int limit, int total, String ctx) { // 初始化参数.每次独立计算.否则分页有问题. PageConf pageConf = new PageConf(start, limit, total); PageConf pageConfTemp1 = new PageConf(start, limit, total); PageConf pageConfTemp2 = new PageConf(start, limit, total); // 结束页 PageConf pageConfTempLast = new PageConf(start, limit, total); // pageConfTempLast.getLast(); // 字符串拼写. StringBuilder strOut = new StringBuilder(); // 设置开始为当前页往前3页,最小1 int begin = Math.max(1, (pageConf.getCurrentPage() + 1) - 3); // 设置结束为当前页往后3页,最大到总页数 int end = Math.min((pageConf.getCurrentPage() + 1) + 3, pageConf.getTotalPage()); int abs = 5 - Math.abs(pageConfTempLast.getCurrentPage() - pageConf.getCurrentPage()); if (abs > 0) { begin = pageConf.getCurrentPage() - abs; begin = Math.min(begin, (pageConf.getCurrentPage() + 1) - 3); begin = Math.max(1, begin); } // 计算当前页和首页的距离 abs = 7 - pageConf.getCurrentPage(); if (abs > 0) { end = pageConf.getCurrentPage() + abs; end = Math.max((pageConf.getCurrentPage() + 1) + 3, end); end = Math.min(end, pageConf.getTotalPage()); } if (pageConf.getTotalPage() > 7) {// 如果大于7显示首页末页 // 显示前一页 if (pageConfTemp1.hastPrevious()) { pageConfTemp1.getPrevious(); strOut.append(PAGE_A + ctx + "&start=" + pageConfTemp1.getStart() + "');\">"); strOut.append("上一页</a>"); } if (pageConf.getCurrentPage() > 3) { // 显示第 1 strOut.append(PAGE_A + ctx + "&start=" + (0) + "');\">"); strOut.append(1); strOut.append("</a>"); if (pageConf.getCurrentPage() > 4) { // 显示第 2 页 strOut.append(PAGE_A + ctx + "&start=" + (0 + pageConf.getLimit()) + "');\">"); strOut.append(2); strOut.append("</a>"); } strOut.append("…"); } } // if(pageConf.getCurrentPage()) // 循环显示数字 for (int i = begin; i <= end; i++) { // 循环多个table的button int startTemp = (i - 1) * pageConf.getLimit(); if (i == (pageConf.getCurrentPage() + 1)) { strOut.append("<span class='current'>"); strOut.append(i);// 当前页显示禁用 strOut.append("</span>"); } else { strOut.append(PAGE_A + ctx + "&start=" + startTemp + "');\">"); strOut.append(i); strOut.append("</a>"); } } // 末页显示,显示最后一页和倒数第二页 if (pageConf.getTotalPage() > 7) {// 如果大于7显示首页末页 if (pageConf.getCurrentPage() < (pageConfTempLast.getCurrentPage() - 3)) { // 如果当前页是倒数第4页就不显示 strOut.append("…"); // System.out.println(pageConf.getCurrentPage() + "/" // + pageConfTempLast.getCurrentPage()); if (pageConf.getCurrentPage() < (pageConfTempLast .getCurrentPage() - 4)) { // 如果当前页是倒数第4页就不显示倒数第2页 strOut.append(PAGE_A + ctx + "&start=" + (pageConfTempLast.getStart() - pageConf .getLimit()) + "');\">"); strOut.append(pageConfTempLast.getCurrentPage()); strOut.append("</a>"); } strOut.append(PAGE_A + ctx + "&start=" + pageConfTempLast.getStart() + "');\">"); strOut.append(pageConfTempLast.getCurrentPage() + 1); strOut.append("</a>"); } // 显示下一页 if (pageConfTemp2.hasNext()) { pageConfTemp2.getNext(); strOut.append(PAGE_A + ctx + "&start=" + pageConfTemp2.getStart() + "');\">"); strOut.append("下一页</a>"); } } return strOut.toString(); } /** * 添加其他参数. */ private String findOtherValue() { String tempValue = ""; if (otherValue != null && !"".equals(otherValue)) { // 将数据按照','进行分开. String[] values = otherValue.split(","); for (int i = 0; i < values.length; i++) { // 从request里面取得数据value. String temp = (null == pageContext.getRequest().getParameter( values[i]) ? "" : pageContext.getRequest() .getParameter(values[i])); if (i == 0) {// 如果是第一个.直接等于.否则就添加& tempValue = values[i] + "=" + temp; } else { tempValue += "&" + values[i] + "=" + temp; } } } return tempValue; } @Override public int doEndTag() throws JspException { try { // 读取模板 // writeToPage("<!--GridPanelPage结束-->");// 完成一个h3不读取模板 } catch (Exception e) { e.printStackTrace(); } return super.doEndTag(); } private void writeToPage(String strOut) { try { pageContext.getOut().print(strOut); } catch (Exception e) { e.printStackTrace(); } } ....get set 方法略.. }
用来生成 分页标签 其中分页参数 是pageconf
package com.freewebsys.core.sns.page; import java.util.List; /* * 分页类开始.*./ /** 排序字段. */ public class PageConf { private String sortField; /** 排序升降.des,aesc. */ private String sortDir; /** 分页开始. */ private int start; /** 分页结束. */ private int end; /** 每页最大数. */ private int limit; /** 分页总数. */ private int total; private List data; public List getData() { return data; } public void setData(List data) { this.data = data; } public int getCurrentPage() { return (int) Math.floor((double) start / limit); } public int getTotalPage() { /** 取得总共的页数. */ return (int) Math.ceil((double) total / limit); } public void getGo(int page) {/* 页面跳转函数.输入要跳转的页面. */ System.out.println("page:[" + page); int totalPage = getTotalPage(); int currentPage = getCurrentPage(); if (page <= 1) {/* 如果小于1.跳到首页. */ getFirst(); return; } else if (page >= totalPage) {/* 如果大于总页数跳到末页. */ getLast(); return; } else if (page == currentPage) {/* 当前页返回. */ return; } else {/* 否则进行页面跳转.也就是计算start和end. */ this.start = (page - 1) * limit; this.end = Math.min(page * limit, total); } // System.out.println("getGo:[" + toString()); } public void getNext() { // System.out.println("getNextPage"); int currentPage = getCurrentPage(); int tempStart = (currentPage + 1) * limit; if (tempStart >= total) { return; } this.start = tempStart; this.end = Math.min((currentPage + 2) * limit, total); // System.out.println("getNext" + toString()); } public void getFirst() { // System.out.println("getFirst"); this.start = 0; this.end = Math.min(limit, total); // System.out.println("getFirst" + toString()); } public void getLast() { // System.out.println("getEnd"); int lastPage = getTotalPage(); /** 如果刚好总页数刚好被整除.就往前一页. */ if ((lastPage * limit) >= total) { lastPage--; } this.start = lastPage * limit; this.end = Math.min((lastPage + 1) * limit, total); // System.out.println("getLast" + toString()); } public void getPrevious() { // System.out.println("getPreviouspage"); int currentPage = getCurrentPage(); /** 前一页等于当前页数乘以每页记录数. */ this.start = Math.max((currentPage - 1) * limit, 0); this.end = Math.max((currentPage) * limit, limit); // System.out.println("getPrevious" + toString()); } public boolean hasNext() { // System.out.println("hasNext" + toString()); if (this.end == this.total) { return false; } else if (this.getTotalPage() <= 1) { return false; } else { return true; } } public boolean hastPrevious() { // System.out.println("hastPrevious" + toString()); if (this.start == 0) { return false; } else { return true; } } public PageConf(int start, int limit, int total) {/* 构造函数.设置开始.和分页数. */ this.start = start; this.limit = limit; // 重新计算end. int currentPage = getCurrentPage(); this.end = Math.min((currentPage + 1) * limit, total); this.total = total; // System.out.println("PageConf" + toString()); } ....get set 方法略.. }
显示底部评论分页
显示二级评论的小分页
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <%@ taglib prefix="fsns" uri="http://freewebsys.sns.googlecode.com"%> <%request.setAttribute("ctx",request.getContextPath());//重新设置缩写. %> <%request.setAttribute("img_ctx",request.getContextPath()+"/common/css/web/images");//重新设置缩写. %> <script type="text/javascript"> <!-- function showReplay(objId){//{status.index} $('#replaySubComment_'+objId+'_id').toggle(); $('#replayTextarea_'+objId+'_id').focus(); } function hideReplay(objId){//{status.index} $('#replaySubComment_'+objId+'_id').hide(); } function saveReplayComment(objId){ if($('#replayTextarea_'+objId+'_id').val() == ''){ alert('请输入评论内容。'); } $.ajax({ url:'saveComment.html', type:"POST", data:{ 'appType':'${appType}', 'appId':'${appId}', 'parentId':$('#replayParentId_'+objId+'_id').val(), 'commentContent':$('#replayTextarea_'+objId+'_id').val()}, success:function(data){//回调函数 if(data == 1){ $('#replayTextarea_'+objId+'_id').val(''); $('#replaySubComment_'+objId+'_id').hide(); //重新加载子分页 var parentId = $('#replayParentId_'+objId+'_id').val(); $("#subComment_"+objId+"_id").html("<div align='center' style='padding-top:50px'><img src='${img_ctx}/loading_blue_big.gif'></div>'"); $("#subComment_"+objId+"_id").load("${ctx}/listSubComment.html?appType=${param.appType}&appId=${param.appId}&parentId="+parentId,function() { $('html,body').animate({scrollTop: $("#comment_"+objId+"_id").offset().top}, 1); }); } } }); } function goPage(url){ //加载 loading 图片 $("#comment_id").html("<div align='center' style='padding-top:50px'><img src='${img_ctx}/loading_blue_big.gif'></div>'"); $("#comment_id").load(url,function() { $('html,body').animate({scrollTop: $("comment_anchor_id").offset().top}, 1); }); } //--> </script> <ul> <s:iterator value="page.data" status="status"> <li id="comment_${id}_id" class="comlist"> <div class="left" style="width: 65px;"> <span class="headpic50"> <a href="" class="tips"><img src="http://toeoso-laptop/thinksns/data/userface/000/00/00/1_small_face.jpg"/></a></span></div> <div style="margin-left: 65px;"> <div style="padding-bottom: 20px;"> <h3 class="tit_Critique lh25 mb5"> <span class="right f12px mr5"><span> <a href="javaScript:void(0);" onclick="showReplay('${id}');">回复</a></span> </span> <a href="/thinksns/index.php?s=/space/1">管理员</a><em class="cGray2">37分钟前</em></h3> <p><s:property value="comment"/></p> </div> <span id="subComment_${id}_anchor_id"></span> <div id="subComment_${id}_id" class="subcomment"> <script type="text/javascript"> <!-- $(document).ready(function(){ $("#subComment_${id}_id").html("<div align='center' style='padding-top:50px'><img src='${img_ctx}/loading_blue_big.gif'></div>'"); $("#subComment_${id}_id").load("${ctx}/listSubComment.html?appType=${param.appType}&appId=${param.appId}&parentId=${id}",function() {}); }); //--> </script> </div> </div> </li> </s:iterator> </ul> <fsns:page action="listComment.html" otherValue="appType,appId" start="${page.start}" limit="${page.limit}" total="${page.total}" theme="ajax"/>
上面是评论分页load jsp 页面。
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@ taglib prefix="s" uri="/struts-tags"%> <%@ taglib prefix="fsns" uri="http://freewebsys.sns.googlecode.com"%> <%request.setAttribute("ctx",request.getContextPath());//重新设置缩写. %> <%request.setAttribute("img_ctx",request.getContextPath()+"/common/css/web/images");//重新设置缩写. %> <s:iterator value="page.data" status="subStatus"> <div class="sublist pt5 clear" id="subComment_${parentId}_${subStatus.index}_id"> <div class="left" style="width: 50px;"> <span class="pic38"><a href="" class="tips" rel=""><img src="http://toeoso-laptop/thinksns/data/userface/000/00/00/1_small_face.jpg"></a></span> </div> <div style="margin-left: 50px;"> <h3 class="tit_Critique lh20 mb5"><span class="right f12px mr5"> <span class="ml5"><a href="###" onclick="deleteComment('${status.index}_${subStatus.index}')">删除</a></span> </span><a href="/thinksns/index.php?s=/space/1">管理员</a><em class="cGray2">37分钟前</em></h3> <p><s:property value="comment"/></p> </div> <div class="c"></div> </div> </s:iterator> <!-- 子回复框 Begin --> <input name="comment.parentId" id="replayParentId_${parentId}_id" type="hidden" value="${parentId}"/> <div style="display: none;" id="replaySubComment_${parentId}_id"> <div class="pt5 clear"> <div class="left" style="width: 50px;"><span class="pic38"><img src="http://toeoso-laptop/thinksns/data/userface/000/00/00/1_small_face.jpg" id="face"></span></div> <div style="margin-left: 50px; overflow: hidden;"> <textarea id="replayTextarea_${parentId}_id" name="comment.comment" rows="4" style="width: 99%;" class="Text" onblur="this.className='Text'" onfocus="this.className='Text1'"></textarea> <input type="submit" class="btn_b mt5" value="回 复" onclick="saveReplayComment('${parentId}');"> <input type="button" class="btn_w mt5" value="取消" onclick="hideReplay('${parentId}');"/> </div> </div> </div> <!-- 子回复框 End --> <fsns:page id="${parentId}" action="listSubComment.html" otherValue="parentId,appType,appId" start="${page.start}" limit="${page.limit}" total="${page.total}" theme="miniAjax"/> <script type="text/javascript"> <!-- function goMiniPage_${parentId}(url){ //加载 loading 图片 $("#subComment_${parentId}_id").html("<div align='center' style='padding-top:50px'><img src='${img_ctx}/loading_blue_big.gif'></div>'"); $("#subComment_${parentId}_id").load(url,function() { $('html,body').animate({scrollTop: $("#subComment_"+objId+"_anchor_id").offset().top}, 1); }); } //--> </script>
上面是 子评论 分页的 load的 jsp 页面。
整个 页面的样式 是 参考 thinksns 的评论的样式的。
使用的技术 是 ssh2 数据库 是mysql。
protected String appType;// 应用类型 如blog
protected Integer appId;// 应用Id
可以设计 针对 不同应用 进行评论。
打算利用 自己独立 开发一个 类似于 替换 thinksns 的社区。
界面 没有美工 就参考 thinksns 数据也部分参考 thinksns 然后 按照模块 进行分布开发。
前端 用 jquery 和 jqueryui 进行。