diff --git a/src/components/datascroller/DataScroller.css b/src/components/datascroller/DataScroller.css
new file mode 100644
index 0000000000..c40b80a94b
--- /dev/null
+++ b/src/components/datascroller/DataScroller.css
@@ -0,0 +1,25 @@
+.ui-datascroller .ui-datascroller-header {
+ text-align: center;
+ padding: .5em .75em;
+ border-bottom: 0 none;
+}
+
+.ui-datascroller .ui-datascroller-footer {
+ text-align: center;
+ padding: .25em .625em;
+ border-top: 0px none;
+}
+
+.ui-datascroller .ui-datascroller-content {
+ padding: .25em .625em;
+}
+
+.ui-datascroller-inline .ui-datascroller-content {
+ overflow: auto;
+}
+
+.ui-datascroller .ui-datascroller-list {
+ list-style-type: none;
+ margin: 0;
+ padding: 0;
+}
\ No newline at end of file
diff --git a/src/components/datascroller/DataScroller.js b/src/components/datascroller/DataScroller.js
new file mode 100644
index 0000000000..eeb22d7ca3
--- /dev/null
+++ b/src/components/datascroller/DataScroller.js
@@ -0,0 +1,240 @@
+import React, { Component } from 'react';
+import PropTypes from 'prop-types';
+import ReactDOM from 'react-dom';
+import classNames from 'classnames';
+
+export class Header extends Component {
+ render() {
+ return (
+
+ {this.props.children}
+
+ );
+ }
+}
+
+export class Footer extends Component {
+ render() {
+ return (
+
+ {this.props.children}
+
+ );
+ }
+}
+
+export class DataScroller extends Component {
+ static defaultProps = {
+ value: null,
+ rows: 0,
+ inline: false,
+ scrollHeight:null,
+ loader: null,
+ buffer: 0.9,
+ style: null,
+ styleClass: null,
+ onLazyLoad: null,
+ itemTemplate: null
+ }
+
+ static propsTypes = {
+ value: PropTypes.array,
+ rows: PropTypes.number,
+ inline: PropTypes.bool,
+ scrollHeight: PropTypes.any,
+ loader: PropTypes.any,
+ buffer: PropTypes.number,
+ style: PropTypes.string,
+ styleClass: PropTypes.string,
+ onLazyLoad: PropTypes.func,
+ itemTemplate: PropTypes.func
+ }
+
+ constructor(props) {
+ super(props);
+ this.state = {};
+ this.dataToRender = [];
+ this.value = this.props.value;
+ this.first = 0;
+ }
+
+ handleDataChange() {
+ if(this.props.lazy) {
+ this.dataToRender = this.value;
+ this.setState({ dataToRender: this.dataToRender });
+ }
+ else {
+ this.load();
+ }
+ }
+
+ load() {
+ if(this.props.lazy) {
+ if(this.props.onLazyLoad) {
+ this.props.onLazyLoad(this.createLazyLoadMetadata());
+ }
+
+ this.first = this.first + this.props.rows;
+ }
+ else {
+ if(this.value) {
+ for(var i = this.first; i < (this.first + this.props.rows); i++) {
+ if(i >= this.value.length) {
+ break;
+ }
+
+ this.dataToRender.push(this.value[i]);
+ }
+
+ this.first = this.first + this.props.rows;
+ this.setState({ dataToRender: this.dataToRender });
+ }
+ }
+ }
+
+ reset() {
+ this.first = 0;
+ this.dataToRender = [];
+ this.setState({ dataToRender: this.dataToRender });
+ this.load();
+ }
+
+ isEmpty() {
+ return !this.dataToRender||(this.dataToRender.length === 0);
+ }
+
+ createLazyLoadMetadata() {
+ return {
+ first: this.first,
+ rows: this.props.rows
+ };
+ }
+
+ bindScrollListener() {
+ if(this.props.inline) {
+ this.scrollFunction = () => {
+ var scrollTop = this.contentElement.scrollTop,
+ scrollHeight = this.contentElement.scrollHeight,
+ viewportHeight = this.contentElement.clientHeight;
+
+ if((scrollTop >= ((scrollHeight * this.props.buffer) - (viewportHeight)))) {
+ this.load();
+ }
+ }
+
+ this.contentElement.addEventListener('scroll', this.scrollFunction);
+ }
+ else {
+ this.scrollFunction = () => {
+ var docBody = document.body,
+ docElement = document.documentElement,
+ scrollTop = (window.pageYOffset||document.documentElement.scrollTop),
+ winHeight = docElement.clientHeight,
+ docHeight = Math.max(docBody.scrollHeight, docBody.offsetHeight, winHeight, docElement.scrollHeight, docElement.offsetHeight);
+
+ if(scrollTop >= ((docHeight * this.props.buffer) - winHeight)) {
+ this.load();
+ }
+ }
+
+ window.addEventListener('scroll', this.scrollFunction);
+ }
+ }
+
+ unbindScrollListener() {
+ if (this.scrollFunction) {
+ if(this.props.inline) {
+ this.contentElement.removeEventListener('scroll', this.scrollFunction);
+ this.contentElement = null;
+ }
+ else if(this.loader && this.isLoaded) {
+ this.loader.removeEventListener('click', this.scrollFunction);
+ }
+ else {
+ window.removeEventListener('scroll', this.scrollFunction);
+ }
+ }
+ }
+
+ componentDidMount() {
+ if(this.props.lazy) {
+ this.load();
+ }
+
+ if(this.props.loader) {
+ this.scrollFunction = () => {
+ this.load();
+ }
+ this.loader = ReactDOM.findDOMNode(this.props.loader);
+ this.loader.addEventListener('click', this.scrollFunction);
+ this.isLoaded = true;
+ }
+ else {
+ this.bindScrollListener();
+ }
+ }
+
+ componentDidUpdate(prevProps, prevState) {
+ if(this.props.loader && !this.isLoaded) {
+ this.unbindScrollListener();
+
+ this.scrollFunction = () => {
+ this.load();
+ }
+ this.loader = ReactDOM.findDOMNode(this.props.loader);
+ this.loader.addEventListener('click', this.scrollFunction);
+ this.isLoaded = true;
+ }
+ }
+
+ componentWillReceiveProps(nextProps) {
+ var newValue = nextProps.value;
+ if (newValue && this.value !== newValue) {
+ this.value = newValue;
+
+ this.handleDataChange();
+ }
+ }
+
+ componentWillUnmount() {
+ if (this.scrollFunction) {
+ this.unbindScrollListener();
+ }
+ }
+
+ render() {
+ var styleClass = classNames('ui-datascroller ui-widget', this.props.styleClass, {
+ 'ui-datascroller-inline': this.props.inline
+ });
+
+ var header = React.Children.map(this.props.children, (element, i) => {
+ return (element && element.type === Header) &&
+ }),
+ footer = React.Children.map(this.props.children, (element, i) => {
+ return (element && element.type === Footer) &&
+ }),
+ content = (
+ this.contentElement = ReactDOM.findDOMNode(el)} className="ui-datascroller-content ui-widget-content" style={{'maxHeight': this.props.scrollHeight}}>
+
+ {
+ this.state.dataToRender && this.state.dataToRender.map((val, i) => {
+ var listItemContent = this.props.itemTemplate ? this.props.itemTemplate(val) : val;
+ return (-
+ {listItemContent}
+
);
+ })
+ }
+
+
+ );
+
+ return (
+
+ {header}
+ {content}
+ {footer}
+
+ );
+ }
+
+}
\ No newline at end of file