Challenge Engineer Life !

エンジニア人生を楽しみたい!仕事や趣味で学んだ技術的なことを書いていくブログです。

Infinite Scroll by using #PrimeFaces Extensions Waypoint.

I'd like to implement infinite scroll page in JSF. So I tried it.

My goal

Today's goal is following simple web page by using JSF.

f:id:kikutaro777:20140101161953p:plain

How to implement

If you are familiar with jQuery, you had better look for jQuery plugins.
There are various plugins. Following site has good summary. It's Japanese site, but you can read plugin names maybe.
http://kachibito.net/web-design/5-infinite-scroll.html

Unfortunately I'm not familiar with jQuery :q

So I search JSF and infinite scroll. One of good ways is here.

Building a page with infinite scroll in PrimeFaces using Waypoints jQuery plugin

Looks nice. But finally, I found PrimeFaces Extensnions component 'Waypoint'.

PrimeFaces Extensions Waypoint component

PrimeFaces Extensions Showcase has good examples.
http://fractalsoft.net/primeext-showcase-mojarra/views/waypoint.jsf

I show my implement result at first.
Run my web application, there are many panel components like this.
f:id:kikutaro777:20140101172735j:plain

When your scroll reached the bottom of web page, then JavaScript event is executed.
The dialog shows 'すたーと', the Japanese word means start.
f:id:kikutaro777:20140101172831j:plain

What is start? Of course, JavaScript function starts.
JavaScript starts to read new panel data from Backing Bean through RemoteCommand component.

After reading adding panel data, then another JavaScript function executes.
'えんど' means end.
f:id:kikutaro777:20140101172918j:plain

It works! Ten panels are added.
f:id:kikutaro777:20140101173040j:plain

If you scroll down again, the same processing run.
f:id:kikutaro777:20140101173254j:plain

I repeated this until around 500 panels.
f:id:kikutaro777:20140101173325j:plain

Code

Here is my Backing Bean of this sample. It's very simple.

package jp.co.hoge.pfsample.ext.waypoint;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import javax.annotation.PostConstruct;
import javax.faces.view.ViewScoped;
import javax.inject.Named;
import lombok.Getter;
import lombok.Setter;

@Named(value = "wayPointPanelBean")
@ViewScoped
public class WayPointPanelBean implements Serializable{

    @Getter @Setter
    private List<String> strList;
    
    private int strListMax = 0;
    
    @PostConstruct
    public void init(){
        strList = new ArrayList<>();
        for(int i = 1; i <= 50; i++){
            strList.add(Integer.toString(i));
        }
    }
    
    public void loadMorePanel(){
        //Add more panels
        strListMax = strList.size();
        for(int i = strListMax + 1; i <= strListMax + 10; i++){
            strList.add(Integer.toString(i));
        }
    }
}

Facelets is following.

<?xml version='1.0' encoding='UTF-8' ?> 
<!DOCTYPE html>
<html lang="ja"
    xmlns="http://www.w3.org/1999/xhtml"
      xmlns:h="http://xmlns.jcp.org/jsf/html"
      xmlns:p="http://primefaces.org/ui"
      xmlns:pe="http://primefaces.org/ui/extensions">
    <h:head>
        <title>Waypoint</title>
    </h:head>
    <h:body>
        <h:form prependId="true">
            <p:dataGrid id="dgPanel" var="pnl" value="#{wayPointPanelBean.strList}">
                <p:panel id="pnl" header="#{pnl}">Name:hogehoge#{pnl}</p:panel>
            </p:dataGrid>
            
            <p:remoteCommand id="remote" name="loadMore" update="dgPanel" process="@this"
                             actionListener="#{wayPointPanelBean.loadMorePanel()}"
                             oncomplete="handleLoadEnd();">
            </p:remoteCommand>

            <pe:waypoint id="way" offset="function(){return $.waypoints('viewportHeight') - $(this).outerHeight()}" widgetVar="widgetWay">
                <pe:javascript event="reached" execute="handleLoadStart(ext);" /> 
            </pe:waypoint>

            <script type="text/javascript">
                function handleLoadStart(ext){
                    if(ext.direction === "down"){
                        alert("すたーと");
                        PF('widgetWay').remove();
                        loadMore();
                    }
                }
                
                function handleLoadEnd(){
                    alert("えんど");
                    PF('widgetWay').register();
                }
            </script>
        </h:form>
    </h:body>
</html>

This is very similar code to Showcase one.

I'm not familiar with jQuery, so the offset attribute is pretty difficult for me at first.
For understanding, I read jQuery Waypoint plugin document.
http://imakewebthings.com/jquery-waypoints/#docs

Finally I figured what offset defines in this code. And I understood it.
f:id:kikutaro777:20140101211633j:plain

Environment

  • Windows 8 Pro 64bit
  • JDK 8
  • NetBeans 7.4
  • GlassFish 4.0
  • PrimeFaces 4.0
  • PrimeFaces Extensions 1.1.0
にほんブログ村 IT技術ブログへ
にほんブログ村 にほんブログ村 IT技術ブログ Javaへ
にほんブログ村