【问题标题】:Implementing Infinite Scrolling in JSF by Primefaces, Waypoint and Masonry通过 Primefaces、Waypoint 和 Masonry 在 JSF 中实现无限滚动
【发布时间】:2014-01-11 16:30:50
【问题描述】:

我正在尝试在 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>

托管 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 中实现它!

另外一个副作用是,Masonry 无法按预期工作。每次当p:remoteCommandonComplete 触发layout() 方法时,滚动条都会设置到顶部。从功能的角度来看,它应该停留在 Waypoint 触发下一次加载的位置。

任何建议都会非常有帮助。

【问题讨论】:

    标签: jsf-2 primefaces jquery-masonry jquery-waypoints primefaces-extensions


    【解决方案1】:

    顺便说一下,PrimeFaces Extensions 有基于 Masonry 的 pe:fluidGrid。查看陈列柜http://primeext.mooo.com:8080/primeext-showcase/views/fluidGrid.jsf

    【讨论】:

      【解决方案2】:

      初始加载后,您不再更新 ui:repeat。使用临时数据存储,例如 h:inputHidden 来保存托管返回和格式化的数据,然后使用 JavaScript 将数据从 h:inputHidden 移动到 Masonry。在 Masonry 中使用以下内容附加数据:

      $container.masonry( "appended", html, true );    
      

      其中html是h:inputHidden的数据

      如果您愿意,可以访问下面的博客了解详细信息。它不使用 PrimeFaces 或 WayPoints,但 Masonry 的更新方式与想要做的类似。

      http://kahimyang.info/kauswagan/code-blogs/1699/how-to-use-and-append-data-to-masonry-in-responsive-jquerymobile-with-jsf-2-and-ajax

      【讨论】:

        【解决方案3】:

        假设您需要一个无限列表

        <ul>
           <li>item 1</li>
           <li>item 2</li>
           <li>...</li>
        </ul>
        

        这个想法是创建一个名为 list.xhml 的复合组件,例如具有属性索引。 例如,该组件可以加载包含 10 个元素的页面。 滚动时,使用 JQuery ajax 加载该组件并将其添加到 dom。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多