export default class ScrollBrowser { /** * Kick things off * * @param {Node} _element The scrollbrowser root element */ constructor(_element) { this._element = _element; this._element.style.display = 'none'; this._loadingIndicator = this._element.lastElementChild; if (!this._loadingIndicator) { return; } this.url = document.querySelector('.tx-pagebrowse-next a').getAttribute('href'); window.addEventListener('scroll', this.checkAndLoad.bind(this)); // Initial check this.checkAndLoad(); } /** * Checks and loads the next page if required */ checkAndLoad() { const recordLockedOrNotInPosition = this.lock || !this.checkPosition(); const urlIsInvalid = typeof this.url === 'undefined' || this.url === null || this.url === this.lastUrl; if (recordLockedOrNotInPosition || urlIsInvalid) { return; } this.lock = true; this.fetchContent().then(this.displayNewData.bind(this)); } /** * Fetches the content of the next page via Ajax */ fetchContent() { return new Promise((resolve) => { const request = new XMLHttpRequest(); request.onreadystatechange = () => { if (request.readyState === XMLHttpRequest.DONE) { if (request.status === 200) { resolve(request.responseText); } } }; request.open( 'GET', this.url ); request.send(); }); } /** * Adds fetched DOM nodes to the list * * @param {String} response The HTML of the AJAX response */ displayNewData(response) { const parser = new DOMParser(); const doc = parser.parseFromString(response, 'text/html'); const results = Array.from(doc.querySelectorAll('.tx-sgnews-list')); results.forEach((result) => { const children = Array.from(result.childNodes); if (!children.length) { return; } let resultList = document.querySelector(`.tx-sgnews-list-${result.dataset.record}`); if (!resultList) { resultList = document.querySelector('.tx-sgnews-list'); } children.forEach((child) => { resultList.appendChild(child); }); this._loadingIndicator = resultList.lastElementChild; }); this.lastUrl = this.url; this.url = doc.querySelector('.tx-pagebrowse-next a').getAttribute('href'); this.lock = false; } /** * Checks the current position of the scrollbar in relation to the position of the load indicator. * * @return boolean */ checkPosition() { const loadingIndicatorPosition = this._loadingIndicator.getBoundingClientRect(); const windowScrollPosition = window.scrollY; return (windowScrollPosition > (loadingIndicatorPosition.top - 6000)); } }