react-infinite-list
Advanced tools
Comparing version 0.2.1 to 0.2.2
@@ -0,1 +1,12 @@ | ||
## v0.2.2 (2015-06-12) | ||
Improved scrolling behavior with webkit. Sometimes, when using some point or touch devices | ||
whole page was scrolled to the bottom, even though the scroll event was emit from the list | ||
view. | ||
Removed unecessary topItem in favor of padding of the first item. Also, styles need not to | ||
be passed down to the list item view. | ||
Thanks crudo! | ||
## v0.2.1 (2015-06-03) | ||
@@ -2,0 +13,0 @@ |
@@ -89,3 +89,3 @@ (function webpackUniversalModuleDefinition(root, factory) { | ||
"div", | ||
{ className: "infinite-list-item", style: { height: this.props.height } }, | ||
{ className: "infinite-list-item" }, | ||
this.props.title | ||
@@ -105,2 +105,8 @@ ); | ||
var isWebkit = /WebKit/.test(navigator && navigator.userAgent || ""); | ||
function isHighDensity() { | ||
return window.matchMedia && (window.matchMedia("only screen and (min-resolution: 124dpi), only screen and (min-resolution: 1.3dppx), only screen and (min-resolution: 48.8dpcm)").matches || window.matchMedia("only screen and (-webkit-min-device-pixel-ratio: 1.3), only screen and (-o-min-device-pixel-ratio: 2.6/2), only screen and (min--moz-device-pixel-ratio: 1.3), only screen and (min-device-pixel-ratio: 1.3)").matches) || window.devicePixelRatio && window.devicePixelRatio > 1.3; | ||
} | ||
var InfiniteList = (function (_React$Component2) { | ||
@@ -112,2 +118,3 @@ function InfiniteList(props) { | ||
this._scrollTimer = null; | ||
this.state = { renderedStart: 0 }; | ||
@@ -119,4 +126,25 @@ } | ||
_createClass(InfiniteList, { | ||
onWheel: { | ||
value: function onWheel() { | ||
this._scrolledByWheel = true; | ||
} | ||
}, | ||
onScroll: { | ||
value: function onScroll() { | ||
value: function onScroll(e) { | ||
e.stopPropagation(); | ||
// webkit when scrolling by wheel | ||
if (isWebkit && this._scrolledByWheel && !isHighDensity()) { | ||
this._scrolledByWheel = false; | ||
if (!this._scrollTimer) { | ||
this._scrollTimer = setTimeout((function () { | ||
this._scrollTimer = null; | ||
this._calculateVisibleItems(); | ||
}).bind(this), 150); | ||
} | ||
return; | ||
} | ||
this._calculateVisibleItems(); | ||
@@ -154,3 +182,3 @@ } | ||
var ListItemComponent = this.props.listItemClass || InfiniteListItem; | ||
return React.createElement(ListItemComponent, _extends({ key: item.id }, item, { height: this.props.itemHeight })); | ||
return React.createElement(ListItemComponent, _extends({ key: item.id }, item)); | ||
} | ||
@@ -167,3 +195,2 @@ }, | ||
var numOfVisibleItems = Math.ceil(height / itemHeight) + 1; | ||
var paddingHeight = renderedStart * itemHeight; | ||
var totalHeight = items.length * itemHeight; | ||
@@ -174,9 +201,15 @@ | ||
var padding = this.state.renderedStart * itemHeight; | ||
var maxPadding = totalHeight - numOfVisibleItems * itemHeight + itemHeight; | ||
var paddingTop = Math.min(maxPadding, padding); | ||
return React.createElement( | ||
"div", | ||
{ className: "infinite-list", onScroll: this.onScroll.bind(this), style: { height: this.props.height } }, | ||
{ className: "infinite-list", | ||
onWheel: this.onWheel.bind(this), | ||
onScroll: this.onScroll.bind(this), | ||
style: { height: this.props.height } }, | ||
React.createElement( | ||
"div", | ||
{ className: "infinite-list-content", style: { height: totalHeight } }, | ||
React.createElement("div", { className: "topitem", style: { height: paddingHeight }, key: "top" }), | ||
{ className: "infinite-list-content", style: { height: totalHeight - paddingTop, paddingTop: paddingTop } }, | ||
listItems | ||
@@ -183,0 +216,0 @@ ) |
@@ -1,1 +0,1 @@ | ||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("react")):"function"==typeof define&&define.amd?define(["react"],t):"object"==typeof exports?exports["react-infinite-list"]=t(require("react")):e["react-infinite-list"]=t(e.React)}(this,function(e){return function(e){function t(i){if(r[i])return r[i].exports;var n=r[i]={exports:{},id:i,loaded:!1};return e[i].call(n.exports,n,n.exports,t),n.loaded=!0,n.exports}var r={};return t.m=e,t.c=r,t.p="",t(0)}([function(e,t,r){"use strict";var i=function(e){return e&&e.__esModule?e["default"]:e},n=function h(e,t,r){var i=Object.getOwnPropertyDescriptor(e,t);if(void 0===i){var n=Object.getPrototypeOf(e);return null===n?void 0:h(n,t,r)}if("value"in i&&i.writable)return i.value;var o=i.get;return void 0===o?void 0:o.call(r)},o=function(){function e(e,t){for(var r in t){var i=t[r];i.configurable=!0,i.value&&(i.writable=!0)}Object.defineProperties(e,t)}return function(t,r,i){return r&&e(t.prototype,r),i&&e(t,i),t}}(),s=function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(e.__proto__=t)},a=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")},l=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var r=arguments[t];for(var i in r)Object.prototype.hasOwnProperty.call(r,i)&&(e[i]=r[i])}return e},c=i(r(1)),p=function(e){function t(){a(this,t),null!=e&&e.apply(this,arguments)}return s(t,e),o(t,{render:{value:function(){return c.createElement("div",{className:"infinite-list-item",style:{height:this.props.height}},this.props.title)}}}),t}(c.Component);p.propTypes={height:c.PropTypes.number.isRequired,title:c.PropTypes.string.isRequired};var u=function(e){function t(e){a(this,t),n(Object.getPrototypeOf(t.prototype),"constructor",this).call(this,e),this.state={renderedStart:0}}return s(t,e),o(t,{onScroll:{value:function(){this._calculateVisibleItems()}},_calculateVisibleItems:{value:function(){var e=c.findDOMNode(this).scrollTop,t=Math.floor(e/this.props.itemHeight);t!==this.state.renderedStart&&this.setState({renderedStart:t})}},componentWillReceiveProps:{value:function(e){var t=this.props.items.length!==e.items.length,r=this.props.height!==e.height;t&&(c.findDOMNode(this).scrollTop=0),(t||r)&&this._calculateVisibleItems()}},_getItemComponent:{value:function(e){var t=this.props.listItemClass||p;return c.createElement(t,l({key:e.id},e,{height:this.props.itemHeight}))}},render:{value:function(){var e=this.state.renderedStart,t=this.props,r=t.items,i=t.height,n=t.itemHeight,o=Math.ceil(i/n)+1,s=e*n,a=r.length*n,l=r.slice(e,e+o),p=l.map(this._getItemComponent,this);return c.createElement("div",{className:"infinite-list",onScroll:this.onScroll.bind(this),style:{height:this.props.height}},c.createElement("div",{className:"infinite-list-content",style:{height:a}},c.createElement("div",{className:"topitem",style:{height:s},key:"top"}),p))}}}),t}(c.Component);e.exports=u,u.propTypes={items:c.PropTypes.array.isRequired,height:c.PropTypes.number.isRequired,itemHeight:c.PropTypes.number.isRequired}},function(t,r,i){t.exports=e}])}); | ||
!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t(require("react")):"function"==typeof define&&define.amd?define(["react"],t):"object"==typeof exports?exports["react-infinite-list"]=t(require("react")):e["react-infinite-list"]=t(e.React)}(this,function(e){return function(e){function t(n){if(i[n])return i[n].exports;var r=i[n]={exports:{},id:n,loaded:!1};return e[n].call(r.exports,r,r.exports,t),r.loaded=!0,r.exports}var i={};return t.m=e,t.c=i,t.p="",t(0)}([function(e,t,i){"use strict";function n(){return window.matchMedia&&(window.matchMedia("only screen and (min-resolution: 124dpi), only screen and (min-resolution: 1.3dppx), only screen and (min-resolution: 48.8dpcm)").matches||window.matchMedia("only screen and (-webkit-min-device-pixel-ratio: 1.3), only screen and (-o-min-device-pixel-ratio: 2.6/2), only screen and (min--moz-device-pixel-ratio: 1.3), only screen and (min-device-pixel-ratio: 1.3)").matches)||window.devicePixelRatio&&window.devicePixelRatio>1.3}var r=function(e){return e&&e.__esModule?e["default"]:e},o=function f(e,t,i){var n=Object.getOwnPropertyDescriptor(e,t);if(void 0===n){var r=Object.getPrototypeOf(e);return null===r?void 0:f(r,t,i)}if("value"in n&&n.writable)return n.value;var o=n.get;return void 0===o?void 0:o.call(i)},s=function(){function e(e,t){for(var i in t){var n=t[i];n.configurable=!0,n.value&&(n.writable=!0)}Object.defineProperties(e,t)}return function(t,i,n){return i&&e(t.prototype,i),n&&e(t,n),t}}(),l=function(e,t){if("function"!=typeof t&&null!==t)throw new TypeError("Super expression must either be null or a function, not "+typeof t);e.prototype=Object.create(t&&t.prototype,{constructor:{value:e,enumerable:!1,writable:!0,configurable:!0}}),t&&(e.__proto__=t)},a=function(e,t){if(!(e instanceof t))throw new TypeError("Cannot call a class as a function")},c=Object.assign||function(e){for(var t=1;t<arguments.length;t++){var i=arguments[t];for(var n in i)Object.prototype.hasOwnProperty.call(i,n)&&(e[n]=i[n])}return e},u=r(i(1)),p=function(e){function t(){a(this,t),null!=e&&e.apply(this,arguments)}return l(t,e),s(t,{render:{value:function(){return u.createElement("div",{className:"infinite-list-item"},this.props.title)}}}),t}(u.Component);p.propTypes={height:u.PropTypes.number.isRequired,title:u.PropTypes.string.isRequired};var h=/WebKit/.test(navigator&&navigator.userAgent||""),d=function(e){function t(e){a(this,t),o(Object.getPrototypeOf(t.prototype),"constructor",this).call(this,e),this._scrollTimer=null,this.state={renderedStart:0}}return l(t,e),s(t,{onWheel:{value:function(){this._scrolledByWheel=!0}},onScroll:{value:function(e){return e.stopPropagation(),h&&this._scrolledByWheel&&!n()?(this._scrolledByWheel=!1,void(this._scrollTimer||(this._scrollTimer=setTimeout(function(){this._scrollTimer=null,this._calculateVisibleItems()}.bind(this),150)))):void this._calculateVisibleItems()}},_calculateVisibleItems:{value:function(){var e=u.findDOMNode(this).scrollTop,t=Math.floor(e/this.props.itemHeight);t!==this.state.renderedStart&&this.setState({renderedStart:t})}},componentWillReceiveProps:{value:function(e){var t=this.props.items.length!==e.items.length,i=this.props.height!==e.height;t&&(u.findDOMNode(this).scrollTop=0),(t||i)&&this._calculateVisibleItems()}},_getItemComponent:{value:function(e){var t=this.props.listItemClass||p;return u.createElement(t,c({key:e.id},e))}},render:{value:function(){var e=this.state.renderedStart,t=this.props,i=t.items,n=t.height,r=t.itemHeight,o=Math.ceil(n/r)+1,s=i.length*r,l=i.slice(e,e+o),a=l.map(this._getItemComponent,this),c=this.state.renderedStart*r,p=s-o*r+r,h=Math.min(p,c);return u.createElement("div",{className:"infinite-list",onWheel:this.onWheel.bind(this),onScroll:this.onScroll.bind(this),style:{height:this.props.height}},u.createElement("div",{className:"infinite-list-content",style:{height:s-h,paddingTop:h}},a))}}}),t}(u.Component);e.exports=d,d.propTypes={items:u.PropTypes.array.isRequired,height:u.PropTypes.number.isRequired,itemHeight:u.PropTypes.number.isRequired}},function(t,i,n){t.exports=e}])}); |
@@ -1,4 +0,4 @@ | ||
"use strict"; | ||
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
Object.defineProperty(exports, '__esModule', { | ||
value: true | ||
@@ -9,13 +9,13 @@ }); | ||
var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ("value" in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; | ||
var _get = function get(_x, _x2, _x3) { var _again = true; _function: while (_again) { var object = _x, property = _x2, receiver = _x3; desc = parent = getter = undefined; _again = false; var desc = Object.getOwnPropertyDescriptor(object, property); if (desc === undefined) { var parent = Object.getPrototypeOf(object); if (parent === null) { return undefined; } else { _x = parent; _x2 = property; _x3 = receiver; _again = true; continue _function; } } else if ('value' in desc) { return desc.value; } else { var getter = desc.get; if (getter === undefined) { return undefined; } return getter.call(receiver); } } }; | ||
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); | ||
var _createClass = (function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ('value' in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; })(); | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { "default": obj }; } | ||
function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { 'default': obj }; } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | ||
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError('Cannot call a class as a function'); } } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== "function" && superClass !== null) { throw new TypeError("Super expression must either be null or a function, not " + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; } | ||
function _inherits(subClass, superClass) { if (typeof superClass !== 'function' && superClass !== null) { throw new TypeError('Super expression must either be null or a function, not ' + typeof superClass); } subClass.prototype = Object.create(superClass && superClass.prototype, { constructor: { value: subClass, enumerable: false, writable: true, configurable: true } }); if (superClass) subClass.__proto__ = superClass; } | ||
var _react = require("react"); | ||
var _react = require('react'); | ||
@@ -36,7 +36,7 @@ var _react2 = _interopRequireDefault(_react); | ||
_createClass(InfiniteListItem, [{ | ||
key: "render", | ||
key: 'render', | ||
value: function render() { | ||
return _react2["default"].createElement( | ||
"div", | ||
{ className: "infinite-list-item", style: { height: this.props.height } }, | ||
return _react2['default'].createElement( | ||
'div', | ||
{ className: 'infinite-list-item' }, | ||
this.props.title | ||
@@ -48,9 +48,15 @@ ); | ||
return InfiniteListItem; | ||
})(_react2["default"].Component); | ||
})(_react2['default'].Component); | ||
InfiniteListItem.propTypes = { | ||
height: _react2["default"].PropTypes.number.isRequired, | ||
title: _react2["default"].PropTypes.string.isRequired | ||
height: _react2['default'].PropTypes.number.isRequired, | ||
title: _react2['default'].PropTypes.string.isRequired | ||
}; | ||
var isWebkit = /WebKit/.test(navigator && navigator.userAgent || ''); | ||
function isHighDensity() { | ||
return window.matchMedia && (window.matchMedia('only screen and (min-resolution: 124dpi), only screen and (min-resolution: 1.3dppx), only screen and (min-resolution: 48.8dpcm)').matches || window.matchMedia('only screen and (-webkit-min-device-pixel-ratio: 1.3), only screen and (-o-min-device-pixel-ratio: 2.6/2), only screen and (min--moz-device-pixel-ratio: 1.3), only screen and (min-device-pixel-ratio: 1.3)').matches) || window.devicePixelRatio && window.devicePixelRatio > 1.3; | ||
} | ||
var InfiniteList = (function (_React$Component2) { | ||
@@ -60,4 +66,5 @@ function InfiniteList(props) { | ||
_get(Object.getPrototypeOf(InfiniteList.prototype), "constructor", this).call(this, props); | ||
_get(Object.getPrototypeOf(InfiniteList.prototype), 'constructor', this).call(this, props); | ||
this._scrollTimer = null; | ||
this.state = { renderedStart: 0 }; | ||
@@ -69,10 +76,31 @@ } | ||
_createClass(InfiniteList, [{ | ||
key: "onScroll", | ||
value: function onScroll() { | ||
key: 'onWheel', | ||
value: function onWheel() { | ||
this._scrolledByWheel = true; | ||
} | ||
}, { | ||
key: 'onScroll', | ||
value: function onScroll(e) { | ||
e.stopPropagation(); | ||
// webkit when scrolling by wheel | ||
if (isWebkit && this._scrolledByWheel && !isHighDensity()) { | ||
this._scrolledByWheel = false; | ||
if (!this._scrollTimer) { | ||
this._scrollTimer = setTimeout((function () { | ||
this._scrollTimer = null; | ||
this._calculateVisibleItems(); | ||
}).bind(this), 150); | ||
} | ||
return; | ||
} | ||
this._calculateVisibleItems(); | ||
} | ||
}, { | ||
key: "_calculateVisibleItems", | ||
key: '_calculateVisibleItems', | ||
value: function _calculateVisibleItems() { | ||
var scrolledPx = _react2["default"].findDOMNode(this).scrollTop; | ||
var scrolledPx = _react2['default'].findDOMNode(this).scrollTop; | ||
@@ -86,3 +114,3 @@ var visibleStart = Math.floor(scrolledPx / this.props.itemHeight); | ||
}, { | ||
key: "componentWillReceiveProps", | ||
key: 'componentWillReceiveProps', | ||
value: function componentWillReceiveProps(nextProps) { | ||
@@ -94,3 +122,3 @@ var itemsChanged = this.props.items.length !== nextProps.items.length, | ||
if (itemsChanged) { | ||
_react2["default"].findDOMNode(this).scrollTop = 0; | ||
_react2['default'].findDOMNode(this).scrollTop = 0; | ||
} | ||
@@ -103,9 +131,9 @@ | ||
}, { | ||
key: "_getItemComponent", | ||
key: '_getItemComponent', | ||
value: function _getItemComponent(item) { | ||
var ListItemComponent = this.props.listItemClass || InfiniteListItem; | ||
return _react2["default"].createElement(ListItemComponent, _extends({ key: item.id }, item, { height: this.props.itemHeight })); | ||
return _react2['default'].createElement(ListItemComponent, _extends({ key: item.id }, item)); | ||
} | ||
}, { | ||
key: "render", | ||
key: 'render', | ||
value: function render() { | ||
@@ -119,3 +147,2 @@ var renderedStart = this.state.renderedStart;var _props = this.props; | ||
var numOfVisibleItems = Math.ceil(height / itemHeight) + 1; | ||
var paddingHeight = renderedStart * itemHeight; | ||
var totalHeight = items.length * itemHeight; | ||
@@ -126,9 +153,15 @@ | ||
return _react2["default"].createElement( | ||
"div", | ||
{ className: "infinite-list", onScroll: this.onScroll.bind(this), style: { height: this.props.height } }, | ||
_react2["default"].createElement( | ||
"div", | ||
{ className: "infinite-list-content", style: { height: totalHeight } }, | ||
_react2["default"].createElement("div", { className: "topitem", style: { height: paddingHeight }, key: "top" }), | ||
var padding = this.state.renderedStart * itemHeight; | ||
var maxPadding = totalHeight - numOfVisibleItems * itemHeight + itemHeight; | ||
var paddingTop = Math.min(maxPadding, padding); | ||
return _react2['default'].createElement( | ||
'div', | ||
{ className: 'infinite-list', | ||
onWheel: this.onWheel.bind(this), | ||
onScroll: this.onScroll.bind(this), | ||
style: { height: this.props.height } }, | ||
_react2['default'].createElement( | ||
'div', | ||
{ className: 'infinite-list-content', style: { height: totalHeight - paddingTop, paddingTop: paddingTop } }, | ||
listItems | ||
@@ -141,11 +174,11 @@ ) | ||
return InfiniteList; | ||
})(_react2["default"].Component); | ||
})(_react2['default'].Component); | ||
exports["default"] = InfiniteList; | ||
exports['default'] = InfiniteList; | ||
InfiniteList.propTypes = { | ||
items: _react2["default"].PropTypes.array.isRequired, | ||
height: _react2["default"].PropTypes.number.isRequired, | ||
itemHeight: _react2["default"].PropTypes.number.isRequired | ||
items: _react2['default'].PropTypes.array.isRequired, | ||
height: _react2['default'].PropTypes.number.isRequired, | ||
itemHeight: _react2['default'].PropTypes.number.isRequired | ||
}; | ||
module.exports = exports["default"]; | ||
module.exports = exports['default']; |
{ | ||
"name": "react-infinite-list", | ||
"version": "0.2.1", | ||
"version": "0.2.2", | ||
"description": "", | ||
@@ -5,0 +5,0 @@ "main": "lib/react-infinite-list.js", |
React Infinite List | ||
============== | ||
=================== | ||
A component that displays large list of data efficiently. Reuses DOM elements during scrolling. | ||
@@ -52,2 +51,9 @@ It uses different rendering approach than [https://github.com/Morhaus/react-list-view] or Ember ListView. | ||
``` | ||
and wait till webpack builds the bundel. Brower shall be opened on port 3000. | ||
and wait till webpack builds the bundle. Browser shall be opened on port 3000. | ||
Build | ||
------- | ||
``` | ||
npm run web-build | ||
``` |
72530
340
58