diff --git a/karma.conf.js b/karma.conf.js
index 16f52a014..78293811d 100644
--- a/karma.conf.js
+++ b/karma.conf.js
@@ -86,8 +86,8 @@ module.exports = function(config) {
plugins:[
new webpack.DefinePlugin({
- __CLIENT__: false,
- __SERVER__: true,
+ __CLIENT__: true,
+ __SERVER__: false,
__DEVELOPMENT__: true,
__DEVTOOLS__: false // <-------- DISABLE redux-devtools HERE
})
diff --git a/src/components/LazyLoad/index.js b/src/components/LazyLoad/index.js
new file mode 100644
index 000000000..a2a804d06
--- /dev/null
+++ b/src/components/LazyLoad/index.js
@@ -0,0 +1,51 @@
+import React, { Component, PropTypes } from 'react';
+import ReactDOM from 'react-dom';
+
+import debug from '../../helpers/debug';
+
+export default class LazyLoad extends Component {
+ static propTypes = {
+ isLoading: PropTypes.bool.isRequired,
+ isEnd: PropTypes.bool.isRequired,
+ isLoaded: PropTypes.bool,
+ onLazyLoad: PropTypes.func.isRequired,
+ loadingComponent: PropTypes.any,
+ endComponent: PropTypes.any,
+ offset: PropTypes.number
+ }
+
+ static defaultProps = {
+ loadingComponent: 'Loading...',
+ endComponent: 'End.',
+ offset: 1000
+ }
+
+ componentDidMount() {
+ if (__CLIENT__) {
+ window.removeEventListener('scroll', this.onScroll, true);
+ window.addEventListener('scroll', this.onScroll, true);
+ }
+ }
+
+ onScroll = () => {
+ const { isLoading, isEnd, offset } = this.props;
+ const dom = ReactDOM.findDOMNode(this);
+
+ if ((!isLoading && !isEnd) && (dom.offsetParent || dom).offsetTop - (window.pageYOffset + window.innerHeight) < offset) {
+ debug('component:LazyLoad', 'onLazyLoad called');
+ return this.props.onLazyLoad();
+ }
+
+ return false;
+ }
+
+ render() {
+ const { isEnd, loadingComponent, endComponent } = this.props;
+
+ if (isEnd) {
+ return endComponent;
+ }
+
+ return loadingComponent;
+ }
+}
diff --git a/src/components/LazyLoad/spec.js b/src/components/LazyLoad/spec.js
new file mode 100644
index 000000000..30c17a29e
--- /dev/null
+++ b/src/components/LazyLoad/spec.js
@@ -0,0 +1,58 @@
+import React from 'react';
+import ReactDOM from 'react-dom';
+import { mount } from 'enzyme';
+
+import LazyLoad from './index';
+
+let wrapper;
+let onLazyLoad;
+let makeComponent;
+
+describe('
Loading
} + /> + ); + }; + + makeComponent(); + }); + + it('should render', () => { + expect(wrapper).to.be.ok; + }); + + it('should show loading component', () => { + expect(wrapper.text()).to.eql('Loading'); + }); + + it('should show end component when no more lazy loading needed', () => { + makeComponent(true); + expect(wrapper.text()).to.eql('End'); + }); + + it('should call onLazyLoad when not end and not loading', () => { + wrapper.instance().onScroll(); + expect(wrapper.props().onLazyLoad).to.have.been.called; + }); + + it('should not call onLazyLoad when at end', () => { + makeComponent(true); + wrapper.instance().onScroll(); + expect(wrapper.props().onLazyLoad).not.to.have.been.called; + }); + + it('should not call onLazyLoad when loading', () => { + makeComponent(false, true); + wrapper.instance().onScroll(); + expect(wrapper.props().onLazyLoad).not.to.have.been.called; + }); +}); diff --git a/src/containers/Surah/index.js b/src/containers/Surah/index.js index 51b3eda1e..e5133b4ad 100644 --- a/src/containers/Surah/index.js +++ b/src/containers/Surah/index.js @@ -8,6 +8,7 @@ import Col from 'react-bootstrap/lib/Col'; import Helmet from 'react-helmet'; // components +import LazyLoad from '../../components/LazyLoad'; import PageBreak from '../../components/PageBreak'; import Audioplayer from '../../components/Audioplayer'; import ContentDropdown from '../../components/ContentDropdown'; @@ -126,8 +127,6 @@ const ayahRangeSize = 30; export default class Surah extends Component { constructor() { super(...arguments); - - this.onScroll = this.onScroll.bind(this); } state = { @@ -136,31 +135,15 @@ export default class Surah extends Component { componentDidMount() { if (__CLIENT__) { - window.removeEventListener('scroll', this.onScroll, true); - window.addEventListener('scroll', this.onScroll, true); + window.removeEventListener('scroll', this.handleNavbar, true); + window.addEventListener('scroll', this.handleNavbar, true); lastScroll = window.pageYOffset; } } - shouldComponentUpdate(nextProps) { - const sameSurahIdRouting = this.props.params.surahId === nextProps.params.surahId; - const lazyLoadFinished = sameSurahIdRouting && (!this.props.isLoaded && nextProps.isLoaded); - const hasReadingModeChange = this.props.options.isReadingMode !== nextProps.options.isReadingMode; - const hasFontSizeChange = this.props.options.fontSize !== nextProps.options.fontSize; - const hasSurahInfoChange = this.props.options.isShowingSurahInfo !== nextProps.options.isShowingSurahInfo; - - return ( - !sameSurahIdRouting || - lazyLoadFinished || - hasReadingModeChange || - hasFontSizeChange || - hasSurahInfoChange - ); - } - componentWillUnmount() { if (__CLIENT__) { - window.removeEventListener('scroll', this.onScroll, true); + window.removeEventListener('scroll', this.handleNavbar, true); } } @@ -224,7 +207,7 @@ export default class Surah extends Component { return setOptionDispatch(payload); } - handleNavbar() { + handleNavbar = () => { // TODO: This should be done with react! if (window.pageYOffset > lastScroll) { document.querySelector('nav').classList.add('scroll-up'); @@ -254,24 +237,6 @@ export default class Surah extends Component { }, 1000)); // then scroll to it } - onScroll() { - const { isLoading, isEndOfSurah } = this.props; - - this.handleNavbar(); - - if (isEndOfSurah) { - return false; - } - - if (!isLoading && !this.state.lazyLoading && window.pageYOffset > (document.body.scrollHeight - window.innerHeight - 1000)) { - // Reached the end. - this.setState({ - lazyLoading: true - }); - - this.lazyLoadAyahs(); - } - } lazyLoadAyahs(callback) { const { loadAyahsDispatch, ayahIds, surah, options } = this.props; @@ -297,38 +262,41 @@ export default class Surah extends Component { } renderPagination() { - const { isEndOfSurah, surah } = this.props; - const { lazyLoading } = this.state; - - if (isEndOfSurah && !lazyLoading) { - return ( -Loading...
; + { + surah.id < 114 && +Loading...
} + /> + ); } renderAyahs() { diff --git a/src/redux/modules/ayahs.js b/src/redux/modules/ayahs.js index e0c45bc3a..33ddf07f8 100644 --- a/src/redux/modules/ayahs.js +++ b/src/redux/modules/ayahs.js @@ -13,6 +13,7 @@ const initialState = { current: null, errored: false, loaded: false, + loading: false, entities: {}, result: [], fontFaces: []