/* global insertAfter, insertArticles, buildArticleHTML, nextPage:writable, fetching:writable, done:writable, InstantClick */ // The purpose of initScrolling is to start paginating the page once you reach the bottom of the page. // It does this for majority of the views on the dashboard page as well as the home feed. var client; /** * * @param {String} el is an HTML element that contains the container that we want to append items to. It contains id: indexContainer. * @param {String} endpoint is the relative URL of the endpoint to call to get the data * @param {Function} insertCallback is a function from the return of the callback function (insertNext). The function is passed the data as an argument to build the HTML. * @returns nil but calls the insertCallback (i.e. the insertEntries function) with the data as an argument to update the HTML. It also handles the loading spinner. */ function fetchNext(el, endpoint, insertCallback) { var indexParams = JSON.parse(el.dataset.params); // I change the name of the param from "action" to "controller_action" prior to the fetch because Rails ignores the // "action" param in the corresponding endpoint controller because it is a reserved word in Rails. Based on the above // I thought it would be safe to do the param name update for now until we can refactor this file and change the coupled architecture. // "action" renamed to "controller_action" is the name of the action from the originating server side request e.g. hidden_tags in the dashboard_controller. const updatedIndexParams = {}; if (indexParams['action']) { delete Object.assign(updatedIndexParams, indexParams, { ['controller_action']: indexParams['action'], })['action']; } var urlParams = new URLSearchParams(updatedIndexParams).toString(); if (urlParams.indexOf('q=') > -1) { return; } var fetchUrl = `${endpoint}?page=${nextPage}&${urlParams}&signature=${parseInt( Date.now() / 400000, 10, )}`.replace('&&', '&'); window .fetch(fetchUrl) .then(function handleResponse(response) { response.json().then(function insertEntries(entries) { nextPage += 1; insertCallback(entries); if (entries.length === 0) { const loadingElement = document.getElementById('loading-articles'); if (loadingElement) { loadingElement.style.display = 'none'; } done = true; } }); }) .catch(function logError(err) { // eslint-disable-next-line no-console console.log(err); }); } /** * * @param {*} params are the dataset params on an wrapping container like 'index-container'. It contains the action and the elID. * The elID is the id of the element that we are appending to. * The action like 'following_tags' is the action that we are taking. * @param {*} buildCallback is the callback function (the buildFollowsHTML function) that will be called after the data is fetched. * It will be passed the data as an argument, and insert the HTML into the DOM. * @returns a function that will be called after the data is fetched from the caller. */ function insertNext(params, buildCallback) { return function insertEntries(entries = []) { var indexContainer = document.getElementById('index-container'); var containerAction = JSON.parse(indexContainer.dataset.params).action || null; var action = params.action || null; var matchingAction = action === containerAction; var list = document.getElementById(params.listId || 'sublist'); var newFollowersHTML = ''; entries.forEach(function insertAnEntry(entry) { let existingEl = document.getElementById( (params.elId || 'element') + '-' + entry.id, ); if (!existingEl) { var newHTML = buildCallback(entry); newFollowersHTML += newHTML; } }); var followList = document.getElementById('following-wrapper'); if (followList && matchingAction) { followList.insertAdjacentHTML('beforeend', newFollowersHTML); } if (nextPage > 0) { fetching = false; } }; } /** * Constructs the HTML for a follows entry using the data from the follows entries object. * * @param {*} follows is the entries for the follows that we are building HTML for. * @returns an HTML block for the follows. */ function buildFollowsHTML(follows) { return ( '
' + '' + '@' + follows.username + '' + '
' + '${tag.short_summary}
`; } // TODO: remove the data-follow-id and the data-tag-id in the child components return `