我试图在jQuery Waypoint和Masonry API的帮助下使用Primefaces实现无限滚动。
这是我到目前为止所做的:
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml" xmlns:h="http://xmlns.jcp.org/jsf/html" xmlns:f="http://xmlns.jcp.org/jsf/core"
xmlns:ui="http://xmlns.jcp.org/jsf/facelets" xmlns:p="http://primefaces.org/ui" xmlns:pe="http://primefaces.org/ui/extensions">
<f:view>
<h:head>
<h:outputScript library="primefaces" name="jquery/jquery.js" />
<h:outputScript name="js/global.js"/>
<h:outputScript name="js/masonry.pkgd.js"/>
<h:outputScript name="js/imagesloaded.pkgd.js"/>
<h:outputStylesheet name="css/global.css" />
<title>Gallery</title>
</h:head>
<h:body>
<h:form prependId="false">
<h:panelGroup id="galleryPanel" layout="block">
<p:outputPanel autoUpdate="true">
<h:panelGroup layout="block" styleClass="galleryContainer">
<ui:repeat id="gallery" value="#{galleryController.images}" var="image">
<h:panelGroup layout="block" styleClass="item">
<h:graphicImage library="images" name="demo/#{image}.jpg" />
</h:panelGroup>
</ui:repeat>
</h:panelGroup>
</p:outputPanel>
<pe:waypoint id="waypoint" widgetVar="waypointWidget" offset="function(){return $.waypoints('viewportHeight') - $(this).outerHeight()}">
<pe:javascript event="reached" execute="handleLoadStart(ext);"/>
</pe:waypoint>
<h:outputScript target="body">
var layout = function(){
var container = $('.galleryContainer');
$(container).imagesLoaded(function(){
$(container).masonry({
itemSelector : '.item',
columnWidth : 240
});
});
};
var handleLoadStart = function(ext) {
if (ext.direction == "down") {
PF('waypointWidget').remove();
moreMedia();
}
};
var handleLoadStop = function(){
layout();
PF('waypointWidget').register();
};
$(document).ready(function(){
layout();
});
</h:outputScript>
<p:remoteCommand name="moreMedia" update="gallery" actionListener="#{galleryController.loadMore}" oncomplete="handleLoadStop()"/>
</h:panelGroup>
</h:form>
</h:body>
</f:view>
</html>
Managed Bean是:
import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.IntStream;
import javax.annotation.PostConstruct;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.ViewScoped;
import javax.faces.event.ActionEvent;
@ManagedBean(name="galleryController")
@ViewScoped
public class GalleryController implements Serializable {
private static final long serialVersionUID = 563439107531288284L;
private List<String> images;
@PostConstruct
public void initialize() {
images = new ArrayList<>();
IntStream.range(1, 16).forEach(i->images.add(new String("image" + i)));
}
public void loadMore(ActionEvent event){
IntStream.range(1, 16).forEach(i->images.add(new String("image" + i)));
}
public List<String> getImages() {
return images;
}
public void setImages(List<String> images) {
this.images = images;
}
}
部分有效,因为它有问题。
主要问题是,当我将新图像添加到现有图像列表时,ui:repeat
将完全呈现。我不想这样做。因为通过这种方式,现有图像也会被加载。像FF或Chome这样的现代浏览器会缓存图像,所以它对他们来说不是问题,但在IE浏览器中,我可以在网络控制台中看到它正在发送GET来获取这些图像。从性能角度来看,已经加载的图像不应该被提取,只有新添加的图像。
但我不知道如何在JSF中创建它!
另外,作为副作用,砌体没有按预期工作。每当onComplete
p:remoteCommand
触发layout()
方法时,滚动条就会设置为顶部。从功能的角度来看,它应该保持在Waypoint触发下一次加载的位置。
任何建议都会非常有用。
答案 0 :(得分:0)
PrimeFaces Extensions有pe:fluidGrid顺便说一下基于Masonry。检查展示http://primeext.mooo.com:8080/primeext-showcase/views/fluidGrid.jsf
答案 1 :(得分:0)
初始加载后,您不再更新ui:repeat。使用临时数据存储(如h:inputHidden)来保存由托管返回和格式化的数据,然后使用JavaScript将数据从h:inputHidden移动到Masonry。在Masonry中使用以下内容附加数据:
$container.masonry( "appended", html, true );
其中html是h:inputHidden
的数据如果您需要,可以访问以下博客了解详情。它不使用PrimeFaces也不使用WayPoints,但是如何更新Masonry与想要做的类似。
答案 2 :(得分:0)
假设您需要使用一个无限列表
<ul>
<li>item 1</li>
<li>item 2</li>
<li>...</li>
</ul>
这个想法是创建一个名为list.xhml的复合组件,例如带有属性索引。 例如,该组件可以加载10个元素的页面。 滚动时,使用JQuery ajax加载该组件并将其添加到dom。