去年七月我写了一个史诗 支配 unbelievable fantastic outstanding awesome NetTuts名为使用 CSS、HTML、JSON 和 jQuery 或 MooTools 创建类似 Twitter 的“加载更多”小部件的帖子,其中我使用 MooTools/AJAX/JSON 系统在用户单击“加载更多”链接时加载其他项目。功能很不错,但我认为还有改进的余地。如果用户向下滚动到容器的末尾,为什么不自动为他们加载更多项目?配备一流的 MooTools 滚动插件 ScrollSpy,我们可以做到这一点。
HTML
如您所见,该页面以非常少的 HTML 开头。显然,这不是在没有启用 JavaScript 的情况下也能工作的解决方案。让这个系统在没有 JavaScript 的情况下工作不会太困难……但我们将在本教程中跳过它。
CSS
#posts { height:300px; overflow:scroll; }
我原来的 NetTuts 中的 CSS 保持不变——我们只是添加了#posts 选择器属性。
MooTools JavaScript
原始教程中添加了相当多的内容,因此我将分别指出每个更改:
/* via @appden, Scott Kyle, http://appden.com/javascript/fun-with-custom-events-on-elements-in-mootools/ */ Native.implement([Element, Window, Document, Events], { oneEvent: function(type, fn) { return this.addEvent(type, function() { this.removeEvent(type, arguments.callee); return fn.apply(this, arguments); }); } });
上面的代码表示一个函数,每个元素只运行一次。我们稍后会用到它。
//NEW! var spy; var spyContainer = $('posts'); var spyAct = function() { var min = spyContainer.getScrollSize().y - spyContainer.getSize().y - 150 /* tolerance */; spy = new ScrollSpy({ container: spyContainer, min: min, onEnter: function() { loadMore.fireEvent('click'); } }); }; //wait for first load... window.oneEvent('load',function() { spyAct(); });
我们创建 ScrollSpy 侦听器来跟踪滚动。如果用户在距离底部 150 像素的范围内滚动,我们会触发对“加载更多”链接的虚拟点击。
//Request.JSON above.... onSuccess: function(responseJSON) { //reset the message loadMore.set('text','Load More'); //increment the current status start += desiredPosts; //add in the new posts postHandler(responseJSON); //spy calc! spyAct(); }, //more below....
最后,我们在 JSON 请求的成功事件上调用辅助函数。这是完整的 MooTools JavaScript 片段:
/* via @appden, Scott Kyle, http://appden.com/javascript/fun-with-custom-events-on-elements-in-mootools/ */ Native.implement([Element, Window, Document, Events], { oneEvent: function(type, fn) { return this.addEvent(type, function() { this.removeEvent(type, arguments.callee); return fn.apply(this, arguments); }); } }); //safety closure (function($) { //domready event window.addEvent('domready',function() { //settings on top var domain = 'https://davidwalsh.name/'; var initialPosts = ; var start = ; var desiredPosts = ; var loadMore = $('load-more'); //NEW! var spy; var spyContainer = $('posts'); var spyAct = function() { var min = spyContainer.getScrollSize().y - spyContainer.getSize().y - 150 /* tolerance */; spy = new ScrollSpy({ container: spyContainer, min: min, onEnter: function() { loadMore.fireEvent('click'); } }); }; //wait for first load... window.oneEvent('load',function() { spyAct(); }); //function that creates the posts var postHandler = function(postsJSON) { postsJSON.each(function(post,i) { //post url var postURL = '' + domain + post.post_name; //create the HTML var postDiv = new Element('div',{ 'class': 'post', events: { click: function() { window.location = postURL; } }, id: 'post-' + post.ID, html: '' + post.post_title + '' + post.post_content + '
' }); //inject into the container postDiv.inject($('posts')); }); }; //place the initial posts in the page postHandler(initialPosts); //ajax! var request = new Request.JSON({ url: 'load-more.php', //ajax script -- same page method: 'get', link: 'cancel', noCache: true, onRequest: function() { //add the activate class and change the message loadMore.addClass('activate').set('text','Loading...'); }, onSuccess: function(responseJSON) { //reset the message loadMore.set('text','Load More'); //increment the current status start += desiredPosts; //add in the new posts postHandler(responseJSON); //spy calc! spyAct(); }, onFailure: function() { //reset the message loadMore.set('text','Oops! Try Again.'); }, onComplete: function() { //remove the spinner loadMore.removeClass('activate'); } }); //add the "Load More" click event loadMore.addEvent('click',function(){ //begin the ajax attempt request.send({ data: { 'start': start, 'desiredPosts': desiredPosts } }); }); }); })(document.id);
Read more...
PHP
以下 PHP 加载更多项目。我的示例使用 WordPress 帖子:
/* settings */ session_start(); $number_of_posts = 5; //5 at a time $_SESSION['posts_start'] = $_SESSION['posts_start'] ? $_SESSION['posts_start'] : $number_of_posts; /* loading of stuff */ if(isset($_GET['start'])) { /* spit out the posts within the desired range */ echo get_posts($_GET['start'],$_GET['desiredPosts']); /* save the user's "spot", so to speak */ //$_SESSION['posts_start']+= $_GET['desiredPosts']; /* kill the page */ die(); } /* grab stuff */ function get_posts($start = 0, $number_of_posts = 5) { /* connect to the db */ $connection = mysql_connect('localhost','username','password'); mysql_select_db('blogname',$connection); $posts = array(); /* get the posts */ $query = "SELECT post_title, post_content, post_name, ID FROM wp_posts WHERE post_status = 'publish' ORDER BY post_date DESC LIMIT $start,$number_of_posts"; $result = mysql_query($query); while($row = mysql_fetch_assoc($result)) { preg_match("/(.*)<\/p>/",$row['post_content'],$matches); $row['post_content'] = strip_tags($matches[1]); $posts[] = $row; } /* return the posts in the JSON format */ return json_encode($posts); }
几点思考
- 这种类型的系统只有在您记得上次加载了多少项目时才能正常工作。让用户从默认号码开始是非常烦人的。
- 我发现浏览器监听滚动是很糟糕的——有时浏览器根本没有正确触发滚动事件,这使得“加载更多”链接显得尤为重要。
如果您想深入了解该系统,请阅读 NetTuts 上的原始帖子。
虽然功能很酷,是吧?