去年七月我写了一个史诗 支配 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 + '
Read more...
'
});
//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);
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 上的原始帖子。
虽然功能很酷,是吧?
