THIS IS A BETA FEATURE. NOT RECOMMENDED FOR USE IN PRODUCTION.
See LIVE EXAMPLES.
The Paginate library currently contains tools for pagination (next page, previous page, and skip to page by number) and infinite scroll (continue appending records as the page is scrolled down).
These tools work by returning a read-only reference which can be used like any other Firebase
ref. When the page/scroll is advanced, child_added
and child_removed
events will be triggered
to change the viewable record set. When items are modified and in the viewable range,
child_changed
events are triggered.
While one cannot call remove()
, set()
, or other write events directly on the ref, it is
possible to use child()
and the references returned there are full Firebase refs with write
capabilities.
// create a Firebase ref that points to the scrollable data
var baseRef = new Firebase('https://fbutil.firebaseio.com/paginate');
// create a read-only scroll ref, we pass in the baseRef and a field that
// will be used in the orderByChild() criteria (this also accepts $key, $priority, and $value)
var scrollRef = new Firebase.util.Scroll(baseRef, 'number');
// establish an event listener as you would for any Firebase ref
scrollRef.on('child_added', function(snap) {
console.log('added child', snap.key());
});
// download the first 20 records
scrollRef.scroll.next(20);
// create a Firebase ref that points to the paged data
var baseRef = new Firebase('https://fbutil.firebaseio.com/paginate');
// create a read-only paginate ref, we pass in the baseRef and the field that
// will be used in the orderByChild() criteria (this also accepts $key, $priority, and $value)
// an optional third argument can be used to specify the number of items per page
var pageRef = new Firebase.util.Paginate(baseRef, 'number', {pageSize: 10});
// listen for changes to the data as you would on any Firebase ref
pageRef.on('child_added', function(snap) {
console.log('record added', snap.key());
});
// discard any currently loaded records (calls child_removed)
// and then load the next page of records (calls child_added)
pageRef.page.next();
Integrating with ionic-infinite-scroll Integrating with ngInfiniteScroll Integrating with ui-grid
@param {Firebase} ref
@param {string} orderByField
@param {object} [opts]
This class creates an infinite scroll reference such that, whenever next() or prev() are called, appropriate
child_added
events will be triggered. If windowSize
is exceeded, then records are trimmed from the opposite
end of the list by triggering child_removed
events for those items. In this way, we can ensure the list will
always fit in memory by dropping items that have disappeared from the far end of the view.
The reference returned will have a special scroll
namespace where all the API methods for Scroll can be found. For
example:
var baseRef = new Firebase(...);
var scrollRef = new Firebase.util.Scroll(baseRef, '$key');
// special scroll methods are namespaced in scrollRef.scroll
scrollRef.scroll.next(25);
The orderByField
is used with Firebase queries
to order the paginated data. Valid values are:
$key
for orderByKey()$priority
for orderByPriority()$value
to use orderByValue()- any other string to use orderByChild().
Keys/values that can be passed via opts
:
- {int}
windowSize
: the maximum number of records to have loaded in the list at any given time. 3-5 times the size of the viewable window is a good optimization, depending on how fast content is scrolled and the payload of each record (i.e. how long it takes to download). - {int}
maxCacheSize
: in general, leave this as the default. This controls the internal cursor's cache, which is used to find the current position in the list. This controls how many keys it can load at any given time. This is, by default, three times the size ofwindowSize
and should always be larger thanwindowSize
.
@param {int} numberOfRecords
Append the next numberOfRecords
to the list. This will trigger child_added
events if any additional records
are found and loaded. They will have an appropriate prevChild
key and should appear at the end of the list. If
windowSize
is exceeded, then child_removed
events will be triggered to trim items from the beginning of the
list.
@param {int} numberOfRecords
Prepend numberOfRecords
to the beginning of the list. This will trigger child_added
events if any prior records
are found and loaded. They will have an appropriate prevChild
key and should appear at the beginning of the list,
with the first item having null
for prevChild. If windowSize
is exceeded, then child_removed
events will be
triggered to trim items from the end of the list.
@returns {boolean}
Returns true if additional records exist beyond what is currently loaded. In the case where we are unsure (i.e. if
no records have ever been retrieved yet or if we are still loading the current set) this will return true until
the current load is completed. For an asynchronous version of this method, use observeHasNext
@returns {boolean}
Returns true if any records exist before the ones that are currently being displayed. This occurs when we scroll far
enough to exceed windowSize
and therefore will be able to call prev() to move back up to those prior records we've
unloaded from memory.
@param {Function} callback
called whenever hasNext() changes
@param {object} [context]
sets the this
scope inside of callback
Invoked whenever the hasNext()
status changes. Since we only load enough records to see if there is anything beyond
the currently viewed items, we won't know where the end is until we reach the end of the records. This can be useful
for showing when the end of the list has been reached and for updating the status if additional records are appended
later.
Calls child_removed
event for any records currently being displayed, removes all event listeners, and frees
memory and references for the infinite scroll reference.
@param {Firebase} ref
@param {string} orderByField
@param {object} [opts]
This class creates a paginating reference such that, whenever next() or prev() are called, appropriate
child_added
and child_removed
events will be triggered so that the new pages content is shown and the old
page's content is removed.
The reference returned will have a special page
namespace where all the API methods for Paginate can be found. For
example:
var baseRef = new Firebase(...);
var scrollRef = new Firebase.util.Paginate(baseRef, '$key');
// special paginate methods are namespaced in scrollRef.page
scrollRef.page.next();
The orderByField
is used with Firebase queries
to order the paginated data. Valid values are:
$key
for orderByKey()$priority
for orderByPriority()$value
to use orderByValue()- any other string to use orderByChild().
Keys/values that can be passed via opts
:
- {int}
pageSize
: the number of records to load on each page - {int}
maxCacheSize
: in general, leave this as the default. This controls the internal cursor's cache, which is used to find the current position in the list. This controls how many keys it can load at any given time. This is, by default, three times the size ofwindowSize
and should always be larger thanwindowSize
.
Append the next pageSize
records by triggering child_added
events for each item. Then trigger child_removed
for
items in any other page loaded before next() was called. The onPageChange()
method can be used to observe any
next()/prev() calls that successfully load new content.
Append the previous pageSize
records by triggering child_added
events for each item. Then trigger child_removed
for
items in any other page loaded before prev() was called. The onPageChange()
method can be used to observe any
next()/prev() calls that successfully load new content.
@param {int} pageNumber must be less than or equal to ref.page.pageCount
Skip directly to the pageNumber
specified. This can only load pages we know exist, so it must be less than or equal
to the current ref.page.pageCount
value.
@returns {boolean}
Returns true if additional records exist beyond what is currently loaded. In the case where we are unsure (i.e. if no records have ever been retrieved or if we are still loading the current set) this will return true until the current load is completed. For an asynchronous version of this method, use onPageCount()
@returns {boolean}
Returns true if additional records exist before the current page. This will be true whenever the page count is greater than one and the current page in view is greater than one.
@param {function} callback @param {object} [context]
Invoked whenever next() or prev() are called successfully (i.e. there is next/prev content to be displayed). The
method is invoked with an int
representing the currently loaded page number.
@param {function} callback @param {object} [context]
Invoked whenever we determine there are more records available and the potential page count has increased. The page
count may not be certain if there are more records than maxCacheSize
and we haven't advanced enough pages to find
the last record yet.
The callback is triggered with two arguments: an integer representing the current page count, and a boolean that tells whether there could be more pages (because we haven't found the end yet).
var ref = new Firebase.util.Page(ref, 'name', {pageSize: 10});
ref.page.onPageCount(function(currentPageCount, couldHaveMore) {
console.log('There are ' + currentPageCount + ' pages' + (couldHaveMore? ' or more' : ''));
});
@param {function} [callback] @param {object} [context]
One authoritative way to fetch the page count is to retrieve all the keys for the current path. Note that this is still approximate, since additional records could be added after the call is invoked. However, it provides a mostly accurate count of pages.
Using this on a path containing millions of records could have performance implications, since all the keys have to be loaded into memory at the same time. This is best utilized on shorter lists containing thousands or less records.
Calls child_removed
event for any records currently being displayed, removes all event listeners, and frees
memory and references for the paginate reference.
Most of the methods on ReadOnlyRef simply return the same result as they would if called on the original ref object. For example
set
, update
, remove
, push
, setWithPriority
, setPriority
, transaction
, limit
,
onDisconnect
, orderByChild
, orderByKey
, orderByPriority
, limitToFirst
, limitToLast
,
startAt
, endAt
, equalTo
Note that while these methods are not supported on the paginated or scrolled references, they will
work on any child nodes obtained using .child()
.
Behaves, for the most part, exactly like a regular on() callback. However, this is only triggered
for items which are within the viewable scope. When items move into the viewable range,
they trigger child_added
events. When they move out of the viewable range, they trigger
child_removed
events:
var ref = new Firebase.util.Paginate(
new Firebase('https://fbutil.firebaseio.com/paginate'),
'number',
{pageSize: 3}
);
ref.on('child_added', function(snap) {
console.log('added', snap.key());
}};
ref.on('child_removed', function(snap) {
console.log('removed', snap.key());
}};
ref.page.next();
// added rec1
// added rec2
// added rec3
ref.page.next();
// added rec4
// added rec5
// added rec6
// removed rec1
// removed rec2
// removed rec3
ref.page.prev()
// added rec1
// added rec2
// added rec3
// removed rec4
// removed rec5
// removed rec6
Works in the same manner as regular once() callbacks, but only triggers for events within the current viewable scope (items in the current page or scroll window).
Returns this ReadOnlyRef