react-lazy-load-image-component
Advanced tools
Comparing version 1.0.1 to 1.0.2
{ | ||
"name": "react-lazy-load-image-component", | ||
"version": "1.0.1", | ||
"version": "1.0.2", | ||
"description": " React Component to lazy load images using a HOC to track window scroll position. ", | ||
"main": "build/index.js", | ||
"peerDependencies": { | ||
"react": "^15.x.x || ^16.x.x" | ||
"react": "^15.x.x || ^16.x.x", | ||
"react-dom": "^15.x.x || ^16.x.x" | ||
}, | ||
@@ -18,2 +19,4 @@ "devDependencies": { | ||
"babel-preset-react": "^6.24.1", | ||
"enzyme": "^3.3.0", | ||
"enzyme-adapter-react-16": "^1.1.1", | ||
"eslint": "^4.18.1", | ||
@@ -40,3 +43,7 @@ "eslint-loader": "^1.9.0", | ||
"react", | ||
"lazyloading" | ||
"react-component", | ||
"lazyload", | ||
"lazyloading", | ||
"lazy-loading", | ||
"lazyload-images" | ||
], | ||
@@ -43,0 +50,0 @@ "author": { |
import React from 'react'; | ||
import ReactDOM from 'react-dom'; | ||
import { PropTypes } from 'prop-types'; | ||
@@ -11,7 +12,2 @@ | ||
}; | ||
this.previousBoundingBox = { | ||
bottom: -1, | ||
top: -1 | ||
}; | ||
} | ||
@@ -23,6 +19,2 @@ | ||
componentWillReceiveProps(nextProps) { | ||
this.updateVisibility(nextProps.scrollPosition); | ||
} | ||
getRelevantProps(nextProps) { | ||
@@ -47,3 +39,3 @@ const keys = Object.keys(nextProps); | ||
shouldComponentUpdate(nextProps, nextState) { | ||
if (this.state.visible !== nextState.visible) { | ||
if (!this.state.visible) { | ||
return true; | ||
@@ -65,43 +57,27 @@ } | ||
getPlaceholderBoundingBox() { | ||
return { | ||
bottom: this.placeholder.offsetTop + | ||
this.placeholder.offsetHeight, | ||
left: this.placeholder.offsetLeft, | ||
right: this.placeholder.offsetLeft + | ||
this.placeholder.offsetWidth, | ||
top: this.placeholder.offsetTop | ||
}; | ||
} | ||
componentDidUpdate(prevProps, prevState) { | ||
if (!prevState.visible && this.state.visible) { | ||
this.props.afterLoad(); | ||
} | ||
componentDidUpdate() { | ||
if (this.placeholder) { | ||
const boundingBox = this.getPlaceholderBoundingBox(); | ||
if (this.previousBoundingBox.bottom !== boundingBox.bottom || | ||
this.previousBoundingBox.left !== boundingBox.left || | ||
this.previousBoundingBox.right !== boundingBox.right || | ||
this.previousBoundingBox.top !== boundingBox.top) { | ||
this.updateVisibility(); | ||
} | ||
} | ||
this.updateVisibility(); | ||
} | ||
updateVisibility(scrollPosition = this.props.scrollPosition) { | ||
if (this.state.visible) { | ||
return; | ||
} | ||
getPlaceholderBoundingBox(scrollPosition = this.props.scrollPosition) { | ||
const boundingRect = this.placeholder.getBoundingClientRect(); | ||
const style = ReactDOM.findDOMNode(this.placeholder).style; | ||
const margin = { | ||
left: parseInt(style.getPropertyValue('margin-left'), 10) || 0, | ||
top: parseInt(style.getPropertyValue('margin-top'), 10) || 0 | ||
}; | ||
if (!this.isImageInViewport(scrollPosition)) { | ||
return; | ||
} | ||
this.props.beforeLoad(); | ||
this.setState({ | ||
visible: true | ||
}, this.props.afterLoad); | ||
return { | ||
bottom: scrollPosition.y + boundingRect.bottom + margin.top, | ||
left: scrollPosition.x + boundingRect.left + margin.left, | ||
right: scrollPosition.x + boundingRect.right + margin.left, | ||
top: scrollPosition.y + boundingRect.top + margin.top | ||
}; | ||
} | ||
isImageInViewport(scrollPosition) { | ||
isImageInViewport() { | ||
if (!this.placeholder) { | ||
@@ -111,4 +87,4 @@ return false; | ||
const { threshold } = this.props; | ||
const boundingBox = this.getPlaceholderBoundingBox(); | ||
const { scrollPosition, threshold } = this.props; | ||
const boundingBox = this.getPlaceholderBoundingBox(scrollPosition); | ||
const viewport = { | ||
@@ -121,4 +97,2 @@ bottom: scrollPosition.y + window.innerHeight, | ||
this.previousBoundingBox = boundingBox; | ||
return Boolean(viewport.top - threshold <= boundingBox.bottom && | ||
@@ -130,4 +104,16 @@ viewport.bottom + threshold >= boundingBox.top && | ||
updateVisibility() { | ||
if (this.state.visible || !this.isImageInViewport()) { | ||
return; | ||
} | ||
this.props.beforeLoad(); | ||
this.setState({ | ||
visible: true | ||
}); | ||
} | ||
getPlaceholder() { | ||
const { className, height, placeholder, width } = this.props; | ||
const { className, height, placeholder, style, width } = this.props; | ||
@@ -142,3 +128,3 @@ if (placeholder) { | ||
ref={el => this.placeholder = el} | ||
style={{ height, width }}> | ||
style={{ height, width, ...style }}> | ||
</span> | ||
@@ -152,11 +138,5 @@ ); | ||
if (!this.state.visible) { | ||
return this.getPlaceholder(); | ||
} | ||
return ( | ||
<img | ||
{...props} | ||
ref={img => this.image = img} /> | ||
); | ||
return this.state.visible ? | ||
<img {...props} /> : | ||
this.getPlaceholder(); | ||
} | ||
@@ -163,0 +143,0 @@ } |
import React from 'react'; | ||
import ReactTestUtils from 'react-dom/test-utils'; | ||
import assert from 'assert'; | ||
import { configure, mount } from 'enzyme'; | ||
import Adapter from 'enzyme-adapter-react-16'; | ||
import LazyLoadImage from './LazyLoadImage.jsx'; | ||
configure({ adapter: new Adapter() }); | ||
const { | ||
@@ -17,5 +20,6 @@ scryRenderedDOMComponentsWithClass, | ||
placeholder = null, | ||
scrollPosition = {x: 0, y: 0} | ||
scrollPosition = {x: 0, y: 0}, | ||
style = {} | ||
} = {}) { | ||
return ReactTestUtils.renderIntoDocument( | ||
return mount( | ||
<LazyLoadImage | ||
@@ -26,8 +30,28 @@ afterLoad={afterLoad} | ||
scrollPosition={scrollPosition} | ||
src="" /> | ||
src="" | ||
style={style} /> | ||
); | ||
} | ||
function simulateScroll(lazyLoadImage, offsetX = 0, offsetY = 0) { | ||
const myMock = jest.fn(); | ||
myMock.mockReturnValue({ | ||
bottom: -offsetY, | ||
height: 0, | ||
left: -offsetX, | ||
right: -offsetX, | ||
top: -offsetY, | ||
width: 0 | ||
}); | ||
lazyLoadImage.instance().placeholder.getBoundingClientRect = myMock; | ||
lazyLoadImage.setProps({ | ||
scrollPosition: {x: offsetX, y: offsetY} | ||
}); | ||
} | ||
function expectImages(wrapper, numberOfImages) { | ||
const img = scryRenderedDOMComponentsWithTag(wrapper, 'img'); | ||
const img = scryRenderedDOMComponentsWithTag(wrapper.instance(), 'img'); | ||
@@ -38,3 +62,3 @@ expect(img.length).toEqual(numberOfImages); | ||
function expectPlaceholders(wrapper, numberOfPlaceholders, placeholderClassName = 'lazy-load-image-placeholder') { | ||
const placeholder = scryRenderedDOMComponentsWithClass(wrapper, placeholderClassName); | ||
const placeholder = scryRenderedDOMComponentsWithClass(wrapper.instance(), placeholderClassName); | ||
@@ -46,3 +70,3 @@ expect(placeholder.length).toEqual(numberOfPlaceholders); | ||
const lazyLoadImage = renderLazyLoadImage({ | ||
scrollPosition: {x: 0, y: -1000} | ||
style: {marginTop: 100000} | ||
}); | ||
@@ -55,6 +79,9 @@ | ||
it('renders the prop placeholder when it\'s not in the viewport', function() { | ||
const placeholder = <span className="test-placeholder"></span>; | ||
const style = {marginTop: 100000}; | ||
const placeholder = ( | ||
<span className="test-placeholder" style={style}></span> | ||
); | ||
const lazyLoadImage = renderLazyLoadImage({ | ||
scrollPosition: {x: 0, y: -1000}, | ||
placeholder | ||
placeholder, | ||
style | ||
}); | ||
@@ -74,7 +101,8 @@ | ||
it('renders the image when it appears in the viewport', function() { | ||
const offset = 100000; | ||
const lazyLoadImage = renderLazyLoadImage({ | ||
scrollPosition: {x: 0, y: -1000} | ||
style: {marginTop: offset} | ||
}); | ||
lazyLoadImage.componentWillReceiveProps({scrollPosition: {x: 0, y: 0}}); | ||
simulateScroll(lazyLoadImage, 0, offset); | ||
@@ -86,7 +114,8 @@ expectImages(lazyLoadImage, 1); | ||
it('renders the image when it appears in the viewport horizontally', function() { | ||
const offset = 100000; | ||
const lazyLoadImage = renderLazyLoadImage({ | ||
scrollPosition: {x: -1000, y: 0} | ||
style: {marginLeft: offset} | ||
}); | ||
lazyLoadImage.componentWillReceiveProps({scrollPosition: {x: 0, y: 0}}); | ||
simulateScroll(lazyLoadImage, offset, 0); | ||
@@ -101,6 +130,6 @@ expectImages(lazyLoadImage, 1); | ||
beforeLoad, | ||
scrollPosition: {x: 0, y: -1000} | ||
style: {marginTop: 100000} | ||
}); | ||
expect(beforeLoad).toHaveBeenCalledTimes(0); | ||
expect(beforeLoad).toHaveBeenCalledTimes(0); | ||
}); | ||
@@ -119,8 +148,9 @@ | ||
const beforeLoad = jest.fn(); | ||
const offset = 100000; | ||
const lazyLoadImage = renderLazyLoadImage({ | ||
beforeLoad, | ||
scrollPosition: {x: 0, y: -1000} | ||
style: {marginTop: offset} | ||
}); | ||
lazyLoadImage.componentWillReceiveProps({scrollPosition: {x: 0, y: 0}}); | ||
simulateScroll(lazyLoadImage, 0, offset); | ||
@@ -134,3 +164,3 @@ expect(beforeLoad).toHaveBeenCalledTimes(1); | ||
afterLoad, | ||
scrollPosition: {x: 0, y: -1000} | ||
style: {marginTop: 100000} | ||
}); | ||
@@ -152,8 +182,9 @@ | ||
const afterLoad = jest.fn(); | ||
const offset = 100000; | ||
const lazyLoadImage = renderLazyLoadImage({ | ||
afterLoad, | ||
scrollPosition: {x: 0, y: -1000} | ||
style: {marginTop: offset} | ||
}); | ||
lazyLoadImage.componentWillReceiveProps({scrollPosition: {x: 0, y: 0}}); | ||
simulateScroll(lazyLoadImage, 0, offset); | ||
@@ -160,0 +191,0 @@ expect(afterLoad).toHaveBeenCalledTimes(1); |
Sorry, the diff of this file is too big to display
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
Long strings
Supply chain riskContains long string literals, which may be a sign of obfuscated or packed code.
Found 1 instance in 1 package
2353053
16467
2
19
16
1