Login Register

partiallyResolved: how to add clientside pagination

I am new to dojo, just got a big headache :-( when working on client-side pagination. But I really love Dojo, and want to use it :-) .
The demo somewhere in forum is just not working in Dojo1.1. http://osdir.com/ml/web.dojo.devel/2006-10/msg00013.html

** Error found:
With coding and Json below, I can only go to next item, but then got a problem which actually already reported here in forum ( dojo datastore automatically combined (messed up?) with previous store fetched).
In console, it just showed combined page1 and page 2, but I can never navigate to page 3. Why ??

My final goal is to make a client-side page with navigation buttons(previous/next page), which I am planning to let it work with dojox.offline store.
Can anybody help me?

Json file (paging.txt): (MODIFIED: from a reply below, I deleted a trailing comma :-( at the end, now works both in IE and FF)

{"timestamp":1193692111,"items":[
{"namespace":"dijit","className":"dijit.ColorPalette1"},
{"namespace":"dijit","className":"dijit.ColorPalette2"},
{"namespace":"dijit","className":"dijit.ColorPalette3"},
{"namespace":"dijit","className":"dijit.ColorPalette4"},
{"namespace":"dijit","className":"dijit.ColorPalette5"},
{"namespace":"dijit","className":"dijit.ColorPalette6"},
{"namespace":"dijit","className":"dijit.ColorPalette7"},
{"namespace":"dijit","className":"dijit.ColorPalette8"},
{"namespace":"dijit","className":"dijit.ColorPalette9"},
{"namespace":"dijit","className":"dijit.ColorPalette10"},
{"namespace":"dijit","className":"dijit.ColorPalette11"},
{"namespace":"dijit","className":"dijit.ColorPalette12"},
{"namespace":"dijit","className":"dijit.ColorPalette13"},
{"namespace":"dijit","className":"dijit.ColorPalette14"},
{"namespace":"dijit","className":"dijit.ColorPalette15"},
{"namespace":"dijit","className":"dijit.ColorPalette16"},
{"namespace":"dijit","className":"dijit.ColorPalette17"},
{"namespace":"dijit","className":"dijit.ColorPalette18"},
{"namespace":"dijit","className":"dijit.ColorPalette19"},
{"namespace":"dijit","className":"dijit.ColorPalette20"}
],"identifier":"className","label":"className"}

.html file:

<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <head>
                <style type="text/css">
                        @import "../dojoroot/dojo/resources/dojo.css";
            </style>
        <style type="text/css">
        @import "http://o.aolcdn.com/dojo/1.0.0/dojox/grid/_grid/tundraGrid.css";
        @import "http://o.aolcdn.com/dojo/1.0.0/dijit/themes/tundra/tundra.css";
        @import "http://o.aolcdn.com/dojo/1.0.0/dojo/resources/dojo.css"
                body {
                        font-size: 0.9em;
                        font-family: Geneva, Arial, Helvetica, sans-serif;
                }
                .heading {
                        font-weight: bold;
                        padding-bottom: 0.25em;
                }
                               
                #grid {
                        border: 1px solid #333;
                        width: 35em;
                        height: 30em;
                }
        </style>               
                <script type="text/javascript" src="../dojoroot/dojo/dojo.js" djConfig="isDebug: true,usePlainJson:true,parseOnLoad: true"></script>
        <script type="text/javascript">
            dojo.require("dojo.data.ItemFileReadStore");
                dojo.require("dojo.parser");
       
var store = new dojo.data.ItemFileReadStore({jsId: 'store',url: "paging.txt" });

    var pageSize = 1;
    var request = null;
    var outOfItems = false;

    //Define a function that will be connected to a 'next' button
    var onNext = function(){
//dojo.byId('show').innerHTML="";
       if(!outOfItems){
           request.start = pageSize + request.start;
           store.fetch(request);
       }
    };
    //Connect this function to the onClick event of the 'next' button
    //Done through dojo.connect() generally.

    //Define a function will be connected to a 'previous' button.
    var onPrevious = function(){
//dojo.byId('show').innerHTML="";
       if (request.start > 0){
          request.start -= pageSize;
          store.fetch(request);
       }
    }
    //Connect this function to the onClick event of the 'previous' button
    //Done through dojo.connect() generally.

    //Define how we handle the items when we get it
    var itemsLoaded = function(items, request){
       if (items.length < pageSize){
          //We have found all the items and are at the end of our set. 
          outOfItems = true;
       }else{
          outOfItems = false;
       }
       //Display the items in a table through the use of store.getValue() on the items and attributes desired.       ...
    dojo.byId('show').innerHTML="";
    dojo.forEach(items, function(i){
    dojo.byId('show').innerHTML+=store.getValue(i, "className") + "<hr />";
        });

// show in console
    var itemsList = "";
    dojo.forEach(items, function(i){
       itemsList += store.getValue(i, "className") + " ";
    });
    console.debug("All items are: " + itemsList);
/*
*/

   }

    //Do the initial request.  Without a query, it should just select all items.  The start and count limit the number returned.
    request = store.fetch({    onComplete: itemsLoaded, start: 0, count: pageSize});

var buttonID1=dojo.byId('button1');
dojo.connect(buttonID1, "onclick", onPrevious);
var buttonID2=dojo.byId('button2');
dojo.connect(buttonID2, "onclick", onNext);
                        </script>
       

        </head>
       
<body class="tundra">
<button id="button1"> previous</button>
<button id="button2"> next</button>

<div id='show'></div>
</body>

resolved in Firefox only

Aha...After struggling, resolved by myself. Though not full Dojo style, but works (in Dojo1.1).
I would work on to make a full connection on this with Dojox.offline;
1st bug: I can not disable buttons when at immediate begin/end; I think I should use some query to get full datastore size, then set correct functions to disable/enable buttons(still working on ...). :-)
2nd bug: not working in IE, but OK in firefox, can anybody tell me why?

<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <head>
                <style type="text/css">
                        @import "../dojoroot/dojo/resources/dojo.css";
            </style>
        <style type="text/css">
        @import "http://o.aolcdn.com/dojo/1.0.0/dojox/grid/_grid/tundraGrid.css";
        @import "http://o.aolcdn.com/dojo/1.0.0/dijit/themes/tundra/tundra.css";
        @import "http://o.aolcdn.com/dojo/1.0.0/dojo/resources/dojo.css";
        </style>               
                <script type="text/javascript" src="../dojoroot/dojo/dojo.js" djConfig="isDebug: true,usePlainJson:true,parseOnLoad: true"></script>
        <script type="text/javascript">
            dojo.require("dojo.data.ItemFileReadStore");
                dojo.require("dojo.parser");
       
var store = new dojo.data.ItemFileReadStore({jsId: 'store',url: "paging.txt" });

        var startPage=0;
    var pageSize = 1;
    var request = null;
    var outOfItems = false;

    //Define a function that will be connected to a 'next' button
   function onNext(){
//dojo.byId('show').innerHTML="";
console.debug("you clicked button 'to next'");
       if(!outOfItems){
                   //console.debug(startPage);
           dojo.byId('button2').disabled="";
           startPage += pageSize;
                   //console.debug("after adding 1:"+startPage);
                   request.start = startPage;
                   //console.debug(request.start);
           store.fetch(request);
       }
           else
           {
    dojo.byId('show').innerHTML="End of data!";
           dojo.byId('button2').disabled="true";
           }
       if (request.start > 0){
                   //console.debug(startPage);
           dojo.byId('button1').disabled="";
       }
           else
           {
    dojo.byId('show').innerHTML="Already beginning of data!";
           dojo.byId('button1').disabled="true";
           }
/*
*/
    };
    //Connect this function to the onClick event of the 'next' button
    //Done through dojo.connect() generally.

    //Define a function will be connected to a 'previous' button.
    function onPrevious(){
//dojo.byId('show').innerHTML="";
console.debug("you clicked button 'to previous'");
       if (request.start > 0){
                   //console.debug(startPage);
           dojo.byId('button1').disabled="";
           startPage -= pageSize;
                   //console.debug("after adding 1:"+startPage);
                   request.start = startPage;
                   //console.debug(request.start);
           store.fetch(request);
       }
           else
           {
    dojo.byId('show').innerHTML="Already beginning of data!";
           dojo.byId('button1').disabled="true";
           }
       if(!outOfItems){
                   //console.debug(startPage);
           dojo.byId('button2').disabled="";
       }
           else
           {
           dojo.byId('button2').disabled="true";
           }
    }
    //Connect this function to the onClick event of the 'previous' button
    //Done through dojo.connect() generally.

    //Define how we handle the items when we get it
    var itemsLoaded = function(items, request){
       if (items.length < pageSize){
          //We have found all the items and are at the end of our set. 
          outOfItems = true;
       }else{
          outOfItems = false;
       }
       //Display the items in a table through the use of store.getValue() on the items and attributes desired.       ...
    dojo.byId('show').innerHTML="";
    dojo.forEach(items, function(i){
    dojo.byId('show').innerHTML+=store.getValue(i, "className") + "<hr />";
        });

// show in console
    var itemsList = "";
    dojo.forEach(items, function(i){
       itemsList += store.getValue(i, "className") + " ";
    });
    console.debug("items are: " + itemsList);
   }

    //Do the initial request.  Without a query, it should just select all items.  The start and count limit the number returned.
    request = store.fetch({    onComplete: itemsLoaded, start: 0, count: pageSize});
                        </script>
       

        </head>
       
<body class="tundra">
<button id="button1" onclick="onPrevious();"> previous</button>
<button id="button2" onclick="onNext();"> next</button>

<div id='show'></div>
</body>

Rule of thumb: if you're

Rule of thumb: if you're working with JSON and it works everywhere but in IE, then you've got most likely a trailing comma in your JSON data. That's treated as a syntax error in IE.

In your case the comma is right before the closing bracket of your "items" array.

u'r completely right!

Yes. You're completely right. Thanks!
Now it works for IE as well as FF. I just modified.

These codes below using another json file format works both in IE and FF too.

**********Still how to solve first bug? Can anybody add more codes into my code? I am not familiar with Dojo at all. :-)
quote from up: " 1st bug: I can not disable buttons when at immediate begin/end; I think I should use some query to get full datastore size, then set correct functions to disable/enable buttons(still working on ...). :-) "

pantry_items.json:

{ identifier: 'name',
items: [
{ name: 'page1', aisle: 'Mexican' },
{ name: 'page2', aisle: 'Mexican' },
{ name: 'page3', aisle: 'Mexican' },
{ name: 'page4', aisle: 'Mexican' },
{ name: 'page5', aisle: 'Mexican' },
{ name: 'page6', aisle: 'Mexican' },
{ name: 'page7', aisle: 'Mexican' },
{ name: 'page8', aisle: 'Mexican' },
{ name: 'page9', aisle: 'Mexican' },
{ name: 'page10', aisle: 'Mexican' },
{ name: 'page11', aisle: 'Mexican' }
]}

.html

<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <head>
                <style type="text/css">
                        @import "../dojoroot/dojo/resources/dojo.css";
            </style>
        <style type="text/css">
        @import "http://o.aolcdn.com/dojo/1.0.0/dojox/grid/_grid/tundraGrid.css";
        @import "http://o.aolcdn.com/dojo/1.0.0/dijit/themes/tundra/tundra.css";
        @import "http://o.aolcdn.com/dojo/1.0.0/dojo/resources/dojo.css";
        </style>               
                <script type="text/javascript" src="../dojoroot/dojo/dojo.js" djConfig="isDebug: true,usePlainJson:true,parseOnLoad: true"></script>
        <script type="text/javascript">
            dojo.require("dojo.data.ItemFileReadStore");
                dojo.require("dojo.parser");
       
var store = new dojo.data.ItemFileReadStore({ url: "pantry_items.json" });

        var startPage=0;
    var pageSize = 1;
    var request = null;
    var outOfItems = false;

    //Define a function that will be connected to a 'next' button
   function onNext(){
//dojo.byId('show').innerHTML="";
console.debug("you clicked button 'to next'");
       if(!outOfItems){
                   //console.debug(startPage);
           dojo.byId('button2').disabled=false;
           startPage += pageSize;
                   //console.debug("after adding 1:"+startPage);
                   request.start = startPage;
                   //console.debug(request.start);
           store.fetch(request);
       }
           else
           {
    dojo.byId('show').innerHTML="End of data!";
           dojo.byId('button2').disabled=true;
           }
       if (request.start > 0){
                   //console.debug(startPage);
           dojo.byId('button1').disabled=false;
       }
           else
           {
    dojo.byId('show').innerHTML="Already beginning of data!";
           dojo.byId('button1').disabled=true;
           }
/*
*/
    };
    //Connect this function to the onClick event of the 'next' button
    //Done through dojo.connect() generally.

    //Define a function will be connected to a 'previous' button.
    function onPrevious(){
//dojo.byId('show').innerHTML="";
console.debug("you clicked button 'to previous'");
       if (request.start > 0){
                   //console.debug(startPage);
           dojo.byId('button1').disabled=false;
           startPage -= pageSize;
                   //console.debug("after adding 1:"+startPage);
                   request.start = startPage;
                   //console.debug(request.start);
           store.fetch(request);
       }
           else
           {
    dojo.byId('show').innerHTML="Already beginning of data!";
           dojo.byId('button1').disabled=true;
           }
       if(!outOfItems){
                   //console.debug(startPage);
           dojo.byId('button2').disabled=false;
       }
           else
           {
           dojo.byId('button2').disabled=true;
           }
    }
    //Connect this function to the onClick event of the 'previous' button
    //Done through dojo.connect() generally.

    //Define how we handle the items when we get it
    var itemsLoaded = function(items, request){
       if (items.length < pageSize){
          //We have found all the items and are at the end of our set. 
          outOfItems = true;
       }else{
          outOfItems = false;
       }
       //Display the items in a table through the use of store.getValue() on the items and attributes desired.       ...
    dojo.byId('show').innerHTML="";
    dojo.forEach(items, function(i){
    dojo.byId('show').innerHTML+=store.getValue(i, "name") + "<hr />";
        });

// show in console
    var itemsList = "";
    dojo.forEach(items, function(i){
       itemsList += store.getValue(i, "name") + " ";
    });
    console.debug("items are: " + itemsList);
   }

    //Do the initial request.  Without a query, it should just select all items.  The start and count limit the number returned.

var gotError = function(error, request){
    alert("The request to the store failed. " +  error);
}
//Invoke the search
    request = store.fetch({
            onComplete: itemsLoaded,
                start: 0,
                count: pageSize,
    onError: gotError
                });
                        </script>
       

        </head>
       
<body class="tundra">
<button id="button1" onclick="onPrevious();"> previous</button>
<button id="button2" onclick="onNext();"> next</button>

<div id='show'></div>
</body>

'object error' in IE if I refresh

:-( another bug:
In localhost with Apache, for IE, if page refresh, then an 'object error ' ???!! FF is completely OK when page refresh.

'object error' in IE if I refresh

:-( another bug:
In localhost with Apache, for IE, if page refresh, then an 'object error ' ???!! FF is completely OK when page refresh.
Why?

works with buttons: first/ previous/next/last number spinner

this page works with buttons: first/ previous/next/last with a number spinner to select page.
updated: now works as for disable/enable buttons( a bug No.3 below)
Actually this widget works quite good for most situation, though some bugs.

Bug 1 remaining: I failed to use function regExpGen in numberspinner. So, extra number of js functions ...
Bug 2 remaining: this is tested only on 1 item per page.
Bug 3 remaining: dojit buttonDisable style can not apply. So I have to roll back to browser default.

Can anyone work to complete it? I'm a new js and dojoer.


<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
        <head>
                <style type="text/css">
                        @import "../dojoroot/dojo/resources/dojo.css";
        /*
                @import "../dojoroot/dojox/grid/_grid/tundraGrid.css";
        */
        @import "../dojoroot/dijit/themes/tundra/tundra.css";
                </style>               
                <script type="text/javascript" src="../dojoroot/dojo/dojo.js" djConfig="isDebug: true,usePlainJson:true,parseOnLoad: true"></script>
        <script type="text/javascript">
        //important: this example was tested only on 1 item per page, if multiple items per page, just change codes accordingly.
            dojo.require("dojo.data.ItemFileReadStore");
                dojo.require("dojo.parser");
                dojo.require("dijit.form.Button");
                dojo.require("dijit.form.NumberSpinner");       
var store = new dojo.data.ItemFileReadStore({ url: "pantry_items.json" });
//fetch all and judge number of items, have a 'fulllength';
var fulllength=null;
    var itemsLoadedAll = function(items, requestAll){
       fulllength=items.length;
           console.debug ("fulllength="+fulllength);
 dojo.byId('goToPage').constraints="{min:1,max:"+fulllength+",places:0}";
console.debug("numberSpinner constraints property is set to"+dojo.byId('goToPage').constraints);
      }
//requestAll;
var requestAll=store.fetch({
            onComplete: itemsLoadedAll,
                start: 0
                });
var spinnerCheck=function(){
 console.debug ("spinnerChecking is working...");
       if (dojo.byId('goToPage').value <1){
           dojo.byId('goToPage').value=1;
       }
       if(dojo.byId('goToPage').value>
fulllength-1){// TODO: a bug here // regExpGen may be used.
           dojo.byId('goToPage').value=fulllength-1;
       }
}
               
        var startPage=0;
    var pageSize = 1;
    var request = null;
    var outOfItems = false;
</script>       
        </head>
       
<body class="tundra"><table border="0" cellspacing="10" cellpadding="5">
  <tr>
    <td><button dojoType="dijit.form.Button" id="button1">first
<script type="dojo/method" event="onClick">
onFirst();
</script>
</button>
</td>
    <td><button dojoType="dijit.form.Button" id="button2">previous
<script type="dojo/method" event="onClick">
onPrevious();
</script>
</button></td>
    <td><button dojoType="dijit.form.Button" id="button3">next
<script type="dojo/method" event="onClick">
onNext();
</script>
</button></td>
    <td><button dojoType="dijit.form.Button" id="button4">last
<script type="dojo/method" event="onClick">
onLast();
</script>
</button></td>
    <td>        <input dojoType="dijit.form.NumberSpinner"
                value="1"
                smallDelta="1"
                intermediateChanges="true"
                id="goToPage"
                constraints={min:1,max:20000,places:0}
                onchange="spinnerCheck();"
                onmouseup="spinnerCheck();" />

<button dojoType="dijit.form.Button" id="goToPageButton">go!
<script type="dojo/method" event="onClick">
onGoToPage();
</script>
</button></td>
  </tr>
</table>
This is page:
<h1><span id='show'></span></h1>
</body>
        <script type="text/javascript">
//I just do not want to use dojo addOnLoad :-)
    //Define a function that will be connected to a 'first' button
    //Connect this function to the onClick event of the 'first' button
    //Done through dojo.connect() generally.
 var onFirst = function (){
//dojo.byId('show').innerHTML="";
console.debug("you clicked button 'to first'");
       if (request.start > 0){
           startPage = 0;
                   request.start = startPage;
                   //console.debug(request.start);
           store.fetch(request);
       }
    };
    //Define a function will be connected to a 'previous' button.
    //Connect this function to the onClick event of the 'previous' button
    //Done through dojo.connect() generally.
    var onPrevious = function (){
//dojo.byId('show').innerHTML="";
console.debug("you clicked button 'to previous'");
       if (request.start > 0){
           startPage -= pageSize;
                   request.start = startPage;
                   //console.debug(request.start);
           store.fetch(request);
       }
    }
    //Define a function that will be connected to a 'next' button
    //Connect this function to the onClick event of the 'next' button
    //Done through dojo.connect() generally.
 var onNext = function (){
//dojo.byId('show').innerHTML="";
console.debug("you clicked button 'to next'");
startPage += pageSize;
       if(startPage<fulllength){     
                   request.start = startPage;
                   //console.debug(request.start);
           store.fetch(request);
       }
    };
    //Define a function that will be connected to a 'last' button
    //Connect this function to the onClick event of the 'last' button
    //Done through dojo.connect() generally.
 var onLast = function (){
//dojo.byId('show').innerHTML="";
console.debug("you clicked button 'to Last'");
console.debug("fulllength="+fulllength);
       if(startPage<fulllength-1){
          startPage = fulllength-1;
                   request.start = startPage;
                   //console.debug(request.start);
           store.fetch(request);
                   }
    };
 var onGoToPage = function (){
//dojo.byId('show').innerHTML="";
console.debug("you clicked button 'go to page'");
//console.debug("fulllength="+fulllength);
          startPage = dojo.byId('goToPage').value-1;
                   request.start = startPage;
                   //console.debug(request.start);
           store.fetch(request);
    };
    //Done through dojo.connect() generally.
//define a function to control
function EnableDisableButtonsCtrl(){
console.debug ("judging buttons");
       if (request.start >
0){
//console.debug ("Enabling buttons 1/2");
          
           dojo.byId('button1').disabled=false;
           dojo.byId('button2').disabled=false;
dojo.byId('button1').className="";
dojo.byId('button2').className="";
dojo.byId('button1').style.cursor="pointer";
dojo.byId('button2').style.cursor="pointer";
       }
           else
           {
//console.debug ("Disabling buttons 1/2");
           dojo.byId('button1').disabled=true;
           dojo.byId('button2').disabled=true;
/*
        dojo.byId('button1').style.bordercolor="#d5d5d5 #bdbdbd #bdbdbd #d5d5d5";
        dojo.byId('button1').style.background="#e4e4e4 url(images/buttonDisabled.png) top repeat-x";
        dojo.byId('button1').style.opacity="0.60";
*/
dojo.byId('button1').className="";
dojo.byId('button2').className="";
dojo.byId('button1').style.cursor="not-allowed";
dojo.byId('button2').style.cursor="not-allowed";
           }
       if(startPage<fulllength-1){
//console.debug ("Enabling buttons 3/4");
           dojo.byId('button3').disabled=false;
           dojo.byId('button4').disabled=false;
dojo.byId('button3').className="";
dojo.byId('button4').className="";
dojo.byId('button3').style.cursor="pointer";
dojo.byId('button4').style.cursor="pointer";
       }
           else
           {
//console.debug ("Disabling buttons 3/4");
           dojo.byId('goToPage').value=fulllength;
           dojo.byId('button3').disabled=true;
           dojo.byId('button4').disabled=true;
dojo.byId('button3').className="";
dojo.byId('button4').className="";
dojo.byId('button3').style.cursor="not-allowed";
dojo.byId('button4').style.cursor="not-allowed";
           }
}
    //Define how we handle the items when we get it
    var itemsLoaded = function(items, request){
       //Display the items in a table through the use of store.getValue() on the items and attributes desired.       ...
console.debug ("items are loading");
EnableDisableButtonsCtrl();
    dojo.byId('show').innerHTML="";
    dojo.forEach(items, function(i){
    dojo.byId('show').innerHTML+=store.getValue(i, "name") + "<hr />";
        });
// show in console
    var itemsList = "";
    dojo.forEach(items, function(i){
       itemsList += store.getValue(i, "name") + " ";
    });
    console.debug("items are: " + itemsList);
   }
    //Do the initial request.  Without a query, it should just select all items.  The start and count limit the number returned.
var gotError = function(error, request){
    alert("The request to the store failed. " +  error);
}
//Invoke the search
var    request = store.fetch({
            onComplete: itemsLoaded,
                start: 0,
                count: pageSize,
    onError: gotError
                });
           store.fetch(requestAll);// for IE/safari compatibility
                        </script>