読者です 読者をやめる 読者になる 読者になる

Challenge Java EE !

Java EEを中心に趣味や仕事における開発メモを書いています。

Infinite Scroll by using #PrimeFaces Extensions Waypoint.

JavaScript JSF PrimeFaces

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へ
にほんブログ村