(function() { const root = $(`link[type='root']`).attr('href'); const incrementalLoadingParams = { start: 0, count: viewPortToCount() }; const bookOrderMap = new Map(); const filterCookieName = 'filters'; const oneDayDelta = 86400000; let loader; let footer; let fadeOutDiv; let iso; let isFetching = false; let noResultInjected = false; let filters = getCookie(filterCookieName); let params = new URLSearchParams(window.location.search || filters || ''); let timer; function queryUrlBuilder() { let url = `${root}/catalog/search?`; url += Object.keys(incrementalLoadingParams).map(key => `${key}=${incrementalLoadingParams[key]}`).join("&"); params.forEach((value, key) => {url+= value ? `&${key}=${value}` : ''}); return (url); } function setCookie(cookieName, cookieValue) { const date = new Date(); date.setTime(date.getTime() + oneDayDelta); document.cookie = `${cookieName}=${cookieValue};expires=${date.toUTCString()};sameSite=Strict`; } function getCookie(cookieName) { const name = cookieName + "="; let result; decodeURIComponent(document.cookie).split('; ').forEach(val => { if (val.indexOf(name) === 0) { result = val.substring(name.length); } }); return result; } const humanFriendlySize = (fileSize) => { if (fileSize === 0) { return ''; } const units = ['bytes', 'kB', 'MB', 'GB', 'TB']; let quotient = Math.floor(Math.log10(fileSize) / 3); quotient = quotient < units.length ? quotient : units.length - 1; fileSize /= (1000 ** quotient); return `${+fileSize.toFixed(2)} ${units[quotient]}`; }; const humanFriendlyTitle = (title) => { title = title.replace(/_/g, ' '); return htmlEncode(title[0].toUpperCase() + title.slice(1)); } function htmlEncode(str) { return str.replace(/[\u00A0-\u9999<>\&]/gim, (i) => `&#${i.charCodeAt(0)};`); } function viewPortToCount(){ const zoom = Math.floor((( window.outerWidth - 10 ) / window.innerWidth) * 100); return Math.floor(window.innerHeight/(3*zoom) + 1)*(window.innerWidth/(2.5*zoom) + 1); } function getInnerHtml(node, query) { return node.querySelector(query).innerHTML; } function generateBookHtml(book, sort = false) { const link = book.querySelector('link[type="text/html"]').getAttribute('href'); let iconUrl; book.querySelectorAll('link[rel="http://opds-spec.org/image/thumbnail"]').forEach(link => { if (link.getAttribute('type').split(';')[1] == 'width=48' && !iconUrl) { iconUrl = link.getAttribute('href'); } }); const title = getInnerHtml(book, 'title'); const description = getInnerHtml(book, 'summary'); const id = getInnerHtml(book, 'id'); const language = getInnerHtml(book, 'language'); const tags = getInnerHtml(book, 'tags'); let tagHtml = tags.split(';').filter(tag => {return !(tag.split(':')[0].startsWith('_'))}) .map((tag) => {return tag.charAt(0).toUpperCase() + tag.slice(1)}) .join(' | ').replace(/_/g, ' '); let downloadLink; let zimSize = 0; try { const downloadBookLink = book.querySelector('link[type="application/x-zim"]') zimSize = parseInt(downloadBookLink.getAttribute('length')); downloadLink = downloadBookLink.getAttribute('href').split('.meta4')[0]; } catch { downloadLink = ''; } const humanFriendlyZimSize = humanFriendlySize(zimSize); const divTag = document.createElement('div'); divTag.setAttribute('class', 'book'); divTag.setAttribute('data-id', id); if (sort) { divTag.setAttribute('data-idx', bookOrderMap.get(id)); } divTag.innerHTML = `
${title}
${downloadLink ? `
Download ${humanFriendlyZimSize ? ` - ${humanFriendlyZimSize}
`: ''}` : ''}
${description}
${language.substr(0, 2).toUpperCase()}
${tagHtml}
`; return divTag; } function toggleFooter(show=false) { if (show) { footer.style.display = 'block'; } else { footer.style.display = 'none'; fadeOutDiv.style.display = 'block'; } } function insertModal(button) { const downloadLink = button.getAttribute('data-link'); button.addEventListener('click', (event) => { event.preventDefault(); document.body.insertAdjacentHTML('beforeend', ``); }) } async function getBookCount(query) { const url = `${root}/catalog/search?${query}`; return await fetch(url).then(async (resp) => { const data = new window.DOMParser().parseFromString(await resp.text(), 'application/xml'); return parseInt(data.querySelector('totalResults').innerHTML); }); } async function loadBooks() { loader.style.display = 'block'; return await fetch(queryUrlBuilder()).then(async (resp) => { const data = new window.DOMParser().parseFromString(await resp.text(), 'application/xml'); const books = data.querySelectorAll('entry'); books.forEach((book, idx) => { bookOrderMap.set(getInnerHtml(book, 'id'), idx); }); incrementalLoadingParams.start += books.length; const results = parseInt(data.querySelector('totalResults').innerHTML) if (results === bookOrderMap.size) { incrementalLoadingParams.count = 0; toggleFooter(true); } else { toggleFooter(); } const kiwixResultText = document.querySelector('.kiwixHomeBody__results') if (results) { let resultText = `${results} books`; if (results === 1) { resultText = `${results} book`; } kiwixResultText.innerHTML = resultText; } else { kiwixResultText.innerHTML = ``; } loader.style.display = 'none'; return books; }); } async function loadAndDisplayOptions(nodeQuery, query, valueEntryNode) { await fetch(query).then(async (resp) => { const data = new window.DOMParser().parseFromString(await resp.text(), 'application/xml'); let optionStr = ''; data.querySelectorAll('entry').forEach(entry => { const title = getInnerHtml(entry, 'title'); const value = getInnerHtml(entry, valueEntryNode); optionStr += `