// pager.demo.js /** * jquery/bootstrap pager. * depends: jquery1.10, boostrap2 * https://code.csdn.net/snippets/146160 * @see: http://blog.csdn.net/win_lin/article/details/17628631 * v 1.0.2 */ /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /** * 分页的界面类。 * @param page_size 每页多少条记录 * @param start_page 起始的页数,即最开始就从多少页展示,或者选中的页数。 * 从自然计数开始计算,即1表示第1页。 * @param max_pages 显示的最多页数,当超过页数时,不显示其他的。 * 点击上一页和下一页可以翻页。 * events: * on_click_page():void 当用户点击某一页时的回调函数。可以获取点击的数据。 * step 1: 需要在页面放置一下元素: <div class="pagination text-center"> <ul> <li id="pager_first"><a href="javascript:void(0);">«</a></li> <li id="pager_pre_page"><a href="javascript:void(0);">前N页</a></li> <li id="pager_pre"><a href="javascript:void(0);">上一页</a></li> <li id="pager_next"><a href="javascript:void(0);">下一页</a></li> <li id="pager_next_page"><a href="javascript:void(0);">后N页</a></li> <li id="pager_last"><a href="javascript:void(0);">»</a></li> <li><span>第 <font id="txt_page_index">1</font> 页 / 共 <font id="txt_page_total">1</font> 页</span></li> </ul> <li id="pager_template" class="hide"><a href="javascript:void(0);" id="pager_num">1</a></li> </div> * step 2: 在初始化页面时初始化控件: $(function(){ var pager_ui = new PagerUI(10, 1, 10); pager_ui.on_click_page = function() { // 点击时,获取分页的参数,发起新的异步请求。 ajax_request(); }; }); * step 3: 向服务器发起请求,从分页获取分数的参数。获取结果后更新分页。 function ajax_request() { var url = "/api/v1/tasks?" + "start=" + pager_ui.get_query_start() + "&count=" + pager_ui.get_query_count(); jQuery.getJSON(url, function(ret) { var total = ret["data"]["total"]; var count = ret["data"]["count"]; pager_ui.pager_render(total, count); setTimeout(ajax_request, 5000); }); } */ function PagerUI(page_size, start_page, max_pages) { $("#pager_template").hide(); this.__pager = new Pager(page_size, start_page - 1); // 显示的最多的页数:滑动窗口的大小 this.__window = new PagerWindow(this.__pager, max_pages); this.__pager_nav_handler(); } /** * 获取请求的query参数:起始索引。 * @return start 例如:15:表示从第15索引开始的记录,即符合条件的第16条记录。 */ PagerUI.prototype.get_query_start = function() { return this.__pager.get_query_start(); } /** * 获取请求的query参数:记录数目。 * @return count 例如:10:表示要求返回的最大记录数目。 */ PagerUI.prototype.get_query_count = function() { return this.__pager.get_query_count(); } /** * 从服务器端请求后,更新分页数据,并更新展示。 * @param total 后端数据库符合条件的总记录数。譬如100表示:请求10条记录,但符合条件的共有100条。 * @param count 后端返回的记录条数。譬如3表示:要求返回10条,可能只返回了3条。 */ PagerUI.prototype.pager_render = function(total, count) { if (!this.__pager.update(total, count)) { setTimeout(this.on_page_changed, 0); } $("#txt_page_index").text(this.__pager.get_page_index() + 1); $("#txt_page_total").text(this.__pager.get_page_total()); var _self = this; this.__window.render(function(){ var parent = $(this).parent(); var page_index = parseInt(parent.text()) - 1; _self.__on_click_page(page_index); }); this.__update_pager_navigate_items(); return; } /** * 当用户点击某页时的回调事件。 * 可以通过get_query()获取更新的分页参数。 */ PagerUI.prototype.on_click_page = function() { } /** * 当页面改变时,譬如展现页面时发现页面改变了之类。 */ PagerUI.prototype.on_page_changed = function() { } PagerUI.prototype.__on_click_page = function(page_index) { // update the previous selected page. $("#pager_item_" + this.__pager.get_page_index()).removeClass("disabled"); // refresh page. this.__pager.set_page_index(page_index); this.__update_pager_navigate_items(); this.on_click_page(); } PagerUI.prototype.__update_pager_navigate_items = function() { // disable the current selected page $("#pager_item_" + this.__pager.get_page_index()).addClass("disabled"); if (this.__pager.is_first_page()) { $("#pager_first").addClass("disabled"); } else { $("#pager_first").removeClass("disabled"); } if (this.__pager.is_last_page()) { $("#pager_last").addClass("disabled"); } else { $("#pager_last").removeClass("disabled"); } this.__window.__update_pager_navigate_items(); } PagerUI.prototype.__pager_nav_handler = function() { var _self = this; // first page $("#pager_first").click(function(){ if ($(this).hasClass("disabled")) { return; } _self.__on_click_page(0); }); // previous page $("#pager_pre").click(function(){ if ($(this).hasClass("disabled")) { return; } _self.__on_click_page(_self.__pager.get_page_index() - 1); }); // previous N page $("#pager_pre_page").click(function(){ if ($(this).hasClass("disabled")) { return; } _self.__on_click_page(_self.__window.to_previous()); }); // next N page $("#pager_next_page").click(function(){ if ($(this).hasClass("disabled")) { return; } _self.__on_click_page(_self.__window.to_next()); }); // next page $("#pager_next").click(function(){ if ($(this).hasClass("disabled")) { return; } _self.__on_click_page(_self.__pager.get_page_index() + 1); }); // last page $("#pager_last").click(function(){ if ($(this).hasClass("disabled")) { return; } _self.__on_click_page(_self.__pager.get_page_total() - 1); }); } /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /** * 分页窗口管理。 */ function PagerWindow(pager, window_size) { // 分页逻辑对象 this.__pager = pager; // 窗口的大小。 this.__window_size = window_size; $("#pager_pre_page").find("a").text("前"+this.__window_size+"页"); $("#pager_next_page").find("a").text("后"+this.__window_size+"页"); // 窗口的起始索引。 this.__start = 0; // 窗口中的元素。 /*{ page: 页码。 ui: jquery的显示对象。 }*/ this.__elems = []; } /** * 展示滑动窗口。 * @param total_pages 总的页数。 * @param on_click_page 新增页码的点击回调函数。 */ PagerWindow.prototype.render = function(on_click_page) { var total_pages = this.__pager.get_page_total(); this.__start = parseInt(this.__pager.get_page_index() / this.__window_size); // valid start/end page index. var valid_start_page = Math.max(0, this.__start * this.__window_size); var valid_end_page = Math.min(total_pages, valid_start_page + this.__window_size); // delete the removed for (var i = this.__elems.length - 1; i >= 0; i--) { var elem = this.__elems[i]; if (elem.page >= valid_start_page && elem.page < valid_end_page) { continue; } elem.ui.remove(); this.__elems.splice(i, 1); } // show elements. var previous = $("#pager_pre"); for (var i = valid_start_page; i < valid_end_page; i++) { var item_id = "pager_item_" + i; var item = $("#" + item_id); if (item.length > 0) { previous = item; continue; } item = $("<li/>").html($("#pager_template").html()).attr("id", item_id); item.find("#pager_num").text(i + 1); item.find("#pager_num").click(on_click_page); item.insertAfter(previous); previous = item; this.__elems.push({page: i, ui: item}); } } /** * change to previous N pages. @return the changed current page. */ PagerWindow.prototype.to_previous = function() { this.__start--; var new_page = this.__start * this.__window_size; new_page = Math.max(0, new_page); return new_page; } /** * change to next N pages. @return the changed current page. */ PagerWindow.prototype.to_next = function() { this.__start++; var new_page = this.__start * this.__window_size; new_page = Math.min(this.__pager.get_page_total() - 1, new_page); return new_page; } PagerWindow.prototype.__update_pager_navigate_items = function() { // update the navigate window if (this.__pager.is_first_page() || this.__start == 0) { $("#pager_pre_page").addClass("disabled"); } else { $("#pager_pre_page").removeClass("disabled"); } if (this.__pager.is_last_page() || (this.__start + 1) * this.__window_size >= this.__pager.get_page_total()) { $("#pager_next_page").addClass("disabled"); } else { $("#pager_next_page").removeClass("disabled"); } // update the pre and next. if (this.__pager.is_first_page() || this.__start == this.__pager.get_page_index()) { $("#pager_pre").addClass("disabled"); } else { $("#pager_pre").removeClass("disabled"); } if (this.__pager.is_last_page() || this.__start + this.__window_size - 1 == this.__pager.get_page_index()) { $("#pager_next").addClass("disabled"); } else { $("#pager_next").removeClass("disabled"); } } /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /////////////////////////////////////////////////////////////////////////// /** * 分页管理类: * @param page_size 每页多少条记录 * @param start_page 起始的页数,即最开始就从多少页展示,或者选中的页数。 * 从计算机计数开始计算,即0表示第1页。 */ function Pager(page_size, start_page) { this.__page_size = page_size; this.__start_page = start_page; // server update. this.__total = 0; this.__count = 0; } /** * 获取请求的query参数:起始索引。 * @return start 例如:15:表示从第15索引开始的记录,即符合条件的第16条记录。 */ Pager.prototype.get_query_start = function() { var start = this.__start_page * this.__page_size; return start; } /** * 获取请求的query参数:记录数目。 * @return count 例如:10:表示要求返回的最大记录数目。 */ Pager.prototype.get_query_count = function() { var count = this.__page_size; return count; } /** * 从服务器端请求后,更新分页数据。 * @param total 后端数据库符合条件的总记录数。譬如100表示:请求10条记录,但符合条件的共有100条。 * @param count 后端返回的记录条数。譬如3表示:要求返回10条,可能只返回了3条。 * @return true, 更新成功。false, 更新失败,需要重新请求数据后更新。 */ Pager.prototype.update = function(total, count) { this.__total = total; this.__count = count; var previous_start_page = this.__start_page; this.__start_page = Math.min(this.__start_page, this.get_page_total() - 1); this.__start_page = Math.max(0, this.__start_page); return previous_start_page == this.__start_page; } /** 获取当前请求的页的索引,从0开始计算,即0表示第1页。 -1表示第0页,没有数据。 */ Pager.prototype.get_page_index = function() { if (this.__total == 0) { return -1; } return this.__start_page; } /** 设置当前请求的页的索引 @param start_page 页索引,从0开始计算,即0表示第1页。 */ Pager.prototype.set_page_index = function(start_page) { return this.__start_page = start_page; } /** * 返回当前选中的页是否是第一页。 */ Pager.prototype.is_first_page = function() { return this.__start_page <= 0; } /** * 返回当前选中的页是否是最后一页。 */ Pager.prototype.is_last_page = function() { var total = this.get_page_total(); return this.__start_page >= total - 1; } /** 获取总页数。1表示1页。 */ Pager.prototype.get_page_total = function() { var left = this.__total % this.__page_size; var page_size = parseInt(this.__total / this.__page_size); if (left > 0) { return page_size + 1; } return page_size; } // other components. /** * common utilities * depends: jquery1.10 * https://code.csdn.net/snippets/147103 * @see: http://blog.csdn.net/win_lin/article/details/17994347 */