Skip to content

Instantly share code, notes, and snippets.

@tgpfeiffer
Last active October 3, 2016 15:25
Show Gist options
  • Save tgpfeiffer/4970978 to your computer and use it in GitHub Desktop.
Save tgpfeiffer/4970978 to your computer and use it in GitHub Desktop.
AJAX loading of new items in Lift (with Non-AJAX fallback)
class EndlessList {
/**
* Gets a "page" (e.g., 10 items) of content entities from the database.
*/
def getPage(page: Int): (Seq[Content], Boolean) = {
val realPage: Int = if (page < 1) 1 else page
val limit = 10
val contents = Content.findAll(
(/* conditions */),
Limit(limit + 1),
Skip((realPage - 1) * limit))
// actual contents, hasNext
(contents.take(limit), contents.size > limit)
}
/**
* Given a list of content items, compute the CSS selector to
* display them.
*/
def renderPage(contents: Seq[Content]): CssSel = {
".content" #> contents.map(c => {
".title" #> c.title.is /* &
other CSS selectors */
})
}
def render = {
val myUri = S.uri
val urlPageNo = S.param("page").flatMap(asInt).getOrElse(1)
var ajaxPageNo = urlPageNo
// *initially*, we render the HTML as determined by the urlPage
val initPageData = getPage(urlPageNo)
/**
* This is called to insert another page of items to the list.
*/
def insertPage = {
// get the next page
ajaxPageNo += 1
val thisPage = getPage(ajaxPageNo)
// render and append to page
val tmpl = Templates("templates-hidden" :: "_contentblock" :: Nil)
val html = tmpl.map(t => renderPage(thisPage._1).apply(t))
AppendHtml("blocks", html.getOrElse(NodeSeq.Empty)) &
(if (thisPage._2)
// if there is a next page, update the link
(JqId("nextlink") ~> JqAttr("href", myUri + "?page=" + (ajaxPageNo + 1))).cmd
else {
// if not, disable the link
(JqId("nextlink") ~> JqAttr("href", myUri + "?page=" + (ajaxPageNo))).cmd &
(JqId("nextlink") ~> JsFunc("parent") ~> JsFunc("addClass", "disabled")).cmd
})
}
renderPage(initPageData._1) &
".pager" #> {
".previous" #> {
// the "previous" link is only present on pages 2 and higher and
// is always a static link to the page before
if (urlPageNo > 2) {
"a [href]" #> (S.uri + "?page=" + (urlPageNo - 1)) &
"a [rel]" #> "prev" &
"a *" #> "Previous"
} else if (urlPageNo == 2) {
"a [href]" #> (S.uri) &
"a [rel]" #> "prev" &
"a *" #> "Previous"
} else {
".previous" #> NodeSeq.Empty
}
} &
".next" #> {
// in a JS-enabled client, this will load the next page,
// non-JS-enabled clients will simply follow the link
if (initPageData._2) {
"a" #> SHtml.a(insertPage _, "Next", ("rel" -> "next")) andThen
"a [href]" #> (myUri + "?page=" + (urlPageNo + 1))
} else {
".next" #> NodeSeq.Empty
}
}
}
}
}
<div class="lift:surround?with=default;at=content">
<div class="lift:EndlessList?eager_eval=true">
<div id="blocks">
<div class="lift:embed?what=_contentblock"></div>
</div>
<div>
<ul class="pager">
<li class="previous"><a href="#">Previous</a></li>
<li class="next"><a id="nextlink" href="#">Next</a></li>
</ul>
</div>
</div>
</div>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment