<script type="text/javascript"> var numPage=2; var sumPageCount=$("#sumPageCount").val(); //給窗口綁定滾動條滾動事件 $(document).ready(function(){ $('#loading').shCircleLoader(); $("#loading").css('display','none'); window.onscroll = loadMore; }); function loadMore(){ // 而後判斷窗口的滾動條是否接近頁面底部,這裏的20能夠自定義 //滾動條距離底部仍是20像素的時候開始加載下一頁數據 if(numPage<=parseInt(sumPageCount)){ if (parseInt($(document).scrollTop() + $(window).height()) > parseInt($(document).height() - 100)) { window.onscroll = null;//爲防止重複執行,先清除事件 //顯示加載效果 $("#loading").css('display','block'); //alert("前臺頁碼:要開始加載第"+numPage+"頁的數據"); var type=$("#type").val(); var htmlText=""; $.ajax({ url : "${ctx}/bbs/bbsMoreContent", data:{ "numPage":numPage, "type":type }, dataType : 'json', success : function(data) { // alert("後臺頁碼:已經加載了第"+numPage+"頁的數據"); numPage=numPage+1; //alert("加載數據的總列數:"+data.bbsthemelist.length); $.each(data.bbsthemelist,function(index,item){ htmlText=htmlText+"<li style='list-style-type:none;'><div class='list-group-item'><h4 class='list-group-item-heading' >"+ "<a href='${ctx}/bbs/bbsreply?id="+item.id+"&type=${type}'>"+item.title+"</a>"+ "</h4> <p class='list-group-item-text'>"+ item.content+ "</p><h6 class='list-group-item-heading'><span class='glyphicon glyphicon-eye-open'>" +item.viewnum+ "</span>|<span class='glyphicon glyphicon-pencil'>" +item.floor+"</span>|<span class='glyphicon glyphicon-user'>" +item.createuser+"</span>|<span class='glyphicon glyphicon-calendar'>" +item.updatetime+"</span></h6></div></li>"; }); $("#themeList").append(htmlText); setTimeout(function(){ $("#loading").css('display','none'); window.onscroll =loadMore; },3000); } }); } } } </script>
其實瀑布流的根本思想就是分頁思想,首先進入頁面顯示 分頁數據的第一頁數據,然後監測頁面滾動條的位置,單滾動條到達頁面底部必定位置後異步加載下一頁的數據並用js追加dom元素到頁面中,就是這麼簡單,須要注意的地方就是控制好頁碼數,然後就是 監測滾動條,由於滾動條可能隨時在變,當在拿到當前頁數據而且追加到頁面中時,全部的操做都要鎖定滾動監測事件,讓其失效,整理數據完畢以後,在把滾動偵測事件從新啓動,思路就是這樣的。這裏我同時在加載數據的時候給他來了個加載圖標,人性化,具體代碼也貼出來了,可參考代碼javascript
相應的HTML代碼:css
<div class="list-group"> <a href="#" class="list-group-item active">帖子列表 ${sessionScope.user.name} ${sessionScope.user.phone}</a> <ul id="themeList" style="list-style-type:none;padding-left:0px;"> <c:forEach items="${bbsthemelist}" var="bbstheme"> <li style="list-style-type:none;"> <div class="list-group-item"> <h4 class="list-group-item-heading" > <a href="${ctx}/bbs/bbsreply?id=${bbstheme.id}&type=${type}">${bbstheme.title}</a> </h4> <p class="list-group-item-text"> ${bbstheme.content} </p> <h6 class="list-group-item-heading" > <span class="glyphicon glyphicon-eye-open">${bbstheme.viewnum}</span>| <span class="glyphicon glyphicon-pencil">${bbstheme.floor}</span>| <span class="glyphicon glyphicon-user">${bbstheme.createuser}</span>| <span class="glyphicon glyphicon-calendar">${bbstheme.updatetime }</span> </h6> </div> </li> </c:forEach> </ul> <div class="loading loading7" id="loading"></div> <a class="list-group-item active"></a> </div>
/*! * SunHater Circle Loader v0.2 (2013-12-28) * jQuery plugin * Copyright (c) 2014 Pavel Tzonkov <sunhater@sunhater.com> * Dual licensed under the MIT and GPL licenses. * http://opensource.org/licenses/MIT * http://www.gnu.org/licenses/gpl.html */ (function($) { $.fn.shCircleLoader = function(first, second) { var defaultNamespace = "shcl", id = 1, sel = $(this); // Destroy the loader if (first === "destroy") { sel.find("." + defaultNamespace).detach(); return; // Show progress status into the center } else if ((first === "progress") && (typeof second !== "undefined")) { sel.each(function() { var el = $(this), outer = el.find('.' + defaultNamespace); if (!outer.get(0)) return; if (!el.find('span').get(0)) outer.append("<span></span>"); var span = outer.find('span').last(); span.html(second).css({ position: "absolute", display: "block", left: Math.round((outer.width() - span.width()) / 2) + "px", top: Math.round((outer.height() - span.height()) / 2) + "px" }); }); return; } // Default options var o = { namespace: defaultNamespace, radius: "auto", // "auto" - calculate from selector's width and height dotsRadius: "auto", color: "auto", // "auto" - get from selector's color CSS property; null - do not set dots: 12, duration: 1, clockwise: true, externalCss: false, // true - don't apply CSS from the script keyframes: '0%{{prefix}transform:scale(1)}80%{{prefix}transform:scale(.3)}100%{{prefix}transform:scale(1)}', uaPrefixes: ['o', 'ms', 'webkit', 'moz', ''] }; $.extend(o, first); // Usable options (for better YUI compression) var cl = o.color, ns = o.namespace, dots = o.dots, eCss = o.externalCss, ua = o.uaPrefixes, // Helper functions no_px = function(str) { return str.replace(/(.*)px$/i, "$1"); }, parseCss = function(text) { var i, prefix, ret = ""; for (i = 0; i < ua.length; i++) { prefix = ua[i].length ? ("-" + ua[i] + "-") : ""; ret += text.replace(/\{prefix\}/g, prefix); } return ret; }, prefixedCss = function(property, value) { var ret = {}; if (!property.substr) { $.each(property, function(p, v) { $.extend(ret, prefixedCss(p, v)); }); } else { var i, prefix; for (i = 0; i < ua.length; i++) { prefix = ua[i].length ? ("-" + ua[i] + "-") : ""; ret[prefix + property] = value; } } return ret; }; // Get unexisting ID while ($('#' + ns + id).get(0)) {id++;} // Create animation CSS if (!eCss) { var kf = o.keyframes.replace(/\s+$/, "").replace(/^\s+/, ""); // Test if the first keyframe (0% or "from") has visibility property. If not - add it. if (!/(\;|\{)\s*visibility\s*\:/gi.test(kf)) kf = /^(0+\%|from)\s*\{/i.test(kf) ? kf.replace(/^((0+\%|from)\s*\{)(.*)$/i, "$1visibility:visible;$3") : (/\s+(0+\%|from)\s*\{/i.test(kf) ? kf.replace(/(\s+(0+\%|from)\s*\{)/i, "$1visibility:visible;") : ("0%{visibility:visible}" + kf)); $($('head').get(0) ? 'head' : 'body').append('<style id="' + ns + id + '" type="text/css">' + parseCss('@{prefix}keyframes ' + ns + id + '_bounce{' + kf + '}') + '</style>'); } // Create loader sel.each(function() { var r, dr, i, dot, rad, x, y, delay, offset, css, cssBase = {}, el = $(this), l = el.find('.' + defaultNamespace); // If loader exists, destroy it before creating new one if (l.get(0)) l.shCircleLoader("destroy"); el.html('<div class="' + ns + ((ns != defaultNamespace) ? (" " + defaultNamespace) : "") + '"></div>'); if (eCss) el = el.find('div'); x = el.innerWidth() - no_px(el.css('padding-left')) - no_px(el.css('padding-right')); y = el.innerHeight() - no_px(el.css('padding-top')) - no_px(el.css('padding-bottom')); r = (o.radius == "auto") ? ((x < y) ? (x / 2) : (y / 2)) : o.radius; if (!eCss) { r--; if (o.dotsRadius == "auto") { dr = Math.abs(Math.sin(Math.PI / (1 * dots))) * r; dr = (dr * r) / (dr + r) - 1; } else dr = o.dotsRadius; el = el.find('div'); i = Math.ceil(r * 2); css = { position: "relative", width: i + "px", height: i + "px" }; if (i < x) css.marginLeft = Math.round((x - i) / 2); if (i < y) css.marginTop = Math.round((y - i) / 2); el.css(css); i = Math.ceil(dr * 2) + "px"; cssBase = { position: "absolute", visibility: "hidden", width: i, height: i }; if (cl !== null) cssBase.background = (cl == "auto") ? el.css('color') : cl; $.extend(cssBase, prefixedCss({ 'border-radius': Math.ceil(dr) + "px", 'animation-name': ns + id + "_bounce", 'animation-duration': o.duration + "s", 'animation-iteration-count': "infinite", 'animation-direction': "normal" })); } for (i = 0; i < dots; i++) { el.append("<div></div>"); if (eCss && (typeof dr === "undefined")) dr = (no_px(el.find('div').css('width')) / 2); dot = el.find('div').last(); delay = (o.duration / dots) * i; rad = (2 * Math.PI * i) / dots; offset = r - dr; x = offset * Math.sin(rad); y = offset * Math.cos(rad); if (o.clockwise) y = -y; css = { left: Math.round(x + offset) + "px", top: Math.round(y + offset) + "px" }; if (delay) $.extend(css, prefixedCss('animation-delay', delay + 's')); $.extend(css, cssBase); dot.css(css); }; }); } })(jQuery);