Skip to content

Instantly share code, notes, and snippets.

@JohannesFischer
Created August 12, 2015 03:06
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save JohannesFischer/76e7269955de2db2a983 to your computer and use it in GitHub Desktop.
Save JohannesFischer/76e7269955de2db2a983 to your computer and use it in GitHub Desktop.
"use strict"
topOfElement = (element) ->
if element then element.offsetTop + topOfElement(element.offsetParent) else 0
ScrollList = React.createClass
getDefaultProps: ->
cssclass: ''
limit: 10
offset: 150
getInitialState: ->
data: @props.data
loading: false
initialized: false
componentWillUnmount: ->
@detachScrollListener()
componentDidMount: ->
@attachScrollListener()
scrollListener: ->
el = @getDOMNode()
if window.pageYOffset
scrollTop = window.pageYOffset
else
bd = document.documentElement || document.body.parentNode || document.body
scrollTop = bd.scrollTop
to_btm = topOfElement(el) + el.offsetHeight - scrollTop - window.innerHeight
if to_btm < @props.offset
@detachScrollListener()
unless @state.data is null || @state.data.length < this.props.limit
@setState(
loading: true
)
@fetchNext()
attachScrollListener: ->
window.addEventListener 'scroll', @scrollListener
window.addEventListener 'resize', @scrollListener
@scrollListener()
detachScrollListener: ->
window.removeEventListener 'scroll', @scrollListener
window.removeEventListener 'resize', @scrollListener
fetchNext: ->
@setState
loading: true
glue = if @props.url.indexOf('?') > -1 then '&' else '?'
params = "limit=#{@props.limit}&offset=#{@state.data.length}"
$.ajax
url: "#{@props.url}?#{params}"
dataType: 'json'
success: (response) =>
if response.length > 0
# FIXME fires render twice when updating
@setState(
data: @state.data.concat(response)
loading: false
)
if response.length < @props.limit
@forceUpdate()
if response.length == @props.limit
@attachScrollListener()
else
@setState
loading: false
error: (xhr, status, err) ->
console.error @url, status, err.toString()
render: ->
if @state.loading is true
loading = React.createElement(Loading, { text: @props.text.loading })
if @state.data && @state.data.length is 0
empty = React.createElement('div', {
className: 'columns large-12'
},
React.createElement('p', {
className: 'sub'
}, @props.text.empty
)
)
if @state.data && @state.data.length > 0
if @props.component == 'postlist'
list = React.createElement(PostList,
cssclass: @props.cssclass
empty: @props.text.empty
data: @state.data
)
else
list = React.createElement(UserList,
button: @props.button
cssclass: @props.cssclass
empty: @props.text.empty
users: @state.data
)
React.createElement('div', null,
empty,
list,
loading
)
window.ScrollList = ScrollList
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment