const SMALL = 576 const MEDIUM = 768 const LARGE = 992 const EXTRA_LARGE = 1200 const RESULTS_NUMBER = 10 const urlParams = new URLSearchParams(window.location.search); let navbarForm = document.querySelector('.navbar-form') let searchBar = document.querySelector('#searchbar') let searchBarButton = document.querySelector('#search-button') let suggestions = document.querySelector('#suggestions') let loader = document.querySelector('.loader') let error = document.querySelector('#error') let errorMessage = document.querySelector('#error-message') let errorButton = document.querySelector('#error-button') let hamMenu = document.querySelector('#hamburger-menu') let title = document.querySelector('#title') let ham = document.querySelector('#hamburgerSvg') let cross = document.querySelector('#crossSvg') let pagesNumbersContainer = document.querySelector('.page-nav') let pagesNumbers = document.querySelector('.page-nav div') let resultsDiv = document.querySelector('#results') let resultsCount = document.querySelector('#results-count') let filters = document.querySelectorAll('.filters p') function sanitize(chain) { return chain.replace(/[^a-zA-Z0-9\- ]/g,'') } function showSuggestions() { if (!suggestionsDisplayed) { navbarForm.style.borderRadius = '15px 15px 0 0' suggestions.style.display = 'block' searchBarButton.style.boxShadow = 'none' searchBarButton.classList.replace('animation-in', 'animation-out') suggestionsDisplayed = true } } function hideSuggestions() { if (suggestionsDisplayed) { navbarForm.style.borderRadius = '15px' suggestions.style.display = 'none' searchBarButton.style.boxShadow = 'rgba(0, 0, 0, 0.15) 4px 2px 5px' searchBarButton.classList.replace('animation-out', 'animation-in') suggestionsDisplayed = false } } function emptyResults(withCount = false) { resultsDiv.innerHTML = "" if (withCount) resultsCount.innerHTML = "" } let searchString = ""; let lastRequest = null let queryOption = null function apiRequestThese(search, offset) { hideSuggestions() if (lastRequest === null || (new Date().getTime() - lastRequest) > 1000) { lastRequest = new Date().getTime() emptyResults(true) pagesNumbers.innerHTML = "" loader.style.display = "block" searchString = sanitize(search) fetch(`api.php?q=theses&search=${searchString}&option=${queryOption}&offset=${offset}`) .then(response => response.json()) .then(data => { fetch(`api.php?q=count&search=${searchString}&option=${queryOption}&offset=0`) .then(response => response.json()) .then(aCount => { if (aCount.data) { displayResults(data, aCount.data[0]) } else { displayResults(data, 0) } }) }) } else { alert('Veuillez attendre une seconde entre chaque recherche.') } } function fadeIn() { let elementsToFade = document.querySelectorAll(".result-element") if (elementsToFade !== null) { elementsToFade.forEach(elem => { let distInView = elem.getBoundingClientRect().top - window.innerHeight + 20; if (distInView < 0) { elem.classList.add("fade-in"); } }) } } window.addEventListener('scroll', fadeIn); function updatePageNumber(number) { pagesNumbers.childNodes.forEach(elem => { if (parseInt(elem.innerHTML) === number) { elem.style.fontWeight = "bold" elem.style.textDecoration = "underline" pagesNumbers.scrollLeft += elem.getBoundingClientRect().left - pagesNumbers.getBoundingClientRect().left - (pagesNumbers.offsetWidth / 2) + (elem.offsetWidth / 2) } else { elem.style.textDecoration = "normal" elem.style.textDecoration = "none" } }) } function focusResults(result) { resultsDiv.childNodes.forEach(elem => { let elemContent = elem.querySelector('.element-content') if (result !== elem) { elemContent.style.display = 'none' } else { let display = elemContent.style.display elemContent.style.display = display === 'none' || display === '' ? 'block' : 'none' } }) fadeIn() } let resultsArray = [] let count = 0 let nbPages = 0 let currentPage = null function displayResults(results, aCount) { if (results.status === 400) { loader.style.display = "none" error.classList.remove("fade-out"); error.classList.add("fade-in"); errorMessage.innerHTML = results.message pagesNumbersContainer.style.display = 'none' } else if (results.status === 200) { count = aCount resultsArray = [] pagesNumbersContainer.style.display = 'flex' results.data.forEach(elem => { let result = document.createElement('div') result.classList.add('result-element') let i = 0 let header = document.createElement('div') let qAuthor = elem[0] let author = document.createElement('h3') let pre_replacement = new RegExp(searchString, 'gi').exec(qAuthor) author.innerHTML = qAuthor.replace(pre_replacement, `${pre_replacement}`) let qTitle = elem[2] let title = document.createElement('p') pre_replacement = new RegExp(searchString, 'gi').exec(qTitle) title.innerHTML = qTitle.replace(pre_replacement, `${pre_replacement}`) let firstElement = document.createElement('div') firstElement.classList.add('result-element-header') let onlineButton = document.createElement('button') onlineButton.innerHTML = "" if (elem[14] === 'no') { onlineButton.disabled = true } else { onlineButton.onclick = function() { window.open('https://www.theses.fr/' + elem[13] + '/document', ',_blank') } } firstElement.append(author, onlineButton) header.append(firstElement, title) let content = document.createElement('div') content.classList.add('element-content') elem.forEach(e => { if (i > 3 && i !== 14) { let child = document.createElement('p') let pre_replacement = new RegExp(searchString, 'gi').exec(e) child.innerHTML = e.replace(pre_replacement, `${pre_replacement}`) content.appendChild(child) } i += 1 }) header.addEventListener('click', () => { focusResults(result) }) result.append(header, content) resultsArray.push(result) }) let nb = document.createElement("p") nb.innerHTML = `Nombre de résultats en ${queryOption} pour "${searchString}": ${new Intl.NumberFormat('fr-FR', { maximumSignificantDigits: 3 }).format(count)}.` resultsCount.appendChild(nb) loader.style.display = "none" nbPages = Math.ceil(count / RESULTS_NUMBER) for (let i = 0 ; i < nbPages ; i++) { let number = document.createElement('p') number.innerHTML = i + 1 if (i === 0) number.style.textDecoration = 'underline' number.onclick = () => { browseResults(i + 1) } pagesNumbers.appendChild(number) } if (count < 1) { pagesNumbersContainer.style.display = 'none' } resultsArray.forEach(result => { resultsDiv.appendChild(result) }) currentPage = (parseInt(urlOffset) + RESULTS_NUMBER) / RESULTS_NUMBER updatePageNumber(currentPage) fadeIn() } } function submitForm(offset) { navbarForm.querySelector('input[name="option"]').value = queryOption navbarForm.querySelector('input[name="offset"]').value = offset navbarForm.submit() } function browseResults(wantedPage) { if (wantedPage > 0 && wantedPage < nbPages + 1) { let offset = (wantedPage * RESULTS_NUMBER) - RESULTS_NUMBER submitForm(offset) } } let lastSearch = "" let lastSuggestion = new Date().getTime() let suggestionsDisplayed = false function realTimeDisplay() { let search = document.querySelector('input[name=\'search\']').value search = sanitize(search) if (search.length > 3 && (search !== lastSearch && (new Date().getTime() - lastSuggestion) > 500)) { lastSearch = search lastSuggestion = new Date().getTime() fetch(`api.php?q=suggestion&search=${search}&option=${queryOption}&offset=0`) .then(response => response.json()) .then(results => { if (results.data) { suggestions.innerHTML = "" if (!results.data.length) { hideSuggestions() } else if (document.activeElement === searchBar) { showSuggestions() } results.data.forEach(elem => { let name = document.createElement('p') name.innerHTML = elem name.addEventListener('click', () => { searchBar.value = elem apiRequestThese(elem, 0) }) suggestions.appendChild(name) }) } }) } } function switchHam(q) { if (q) { ham.classList.add('spin-fade') cross.classList.remove('spin-fade') hamMenu.classList.remove('slide-out') hamMenu.classList.add('slide-in') } else { cross.classList.add('spin-fade') ham.classList.remove('spin-fade') hamMenu.classList.replace('slide-in', 'slide-out') } } function switchNavTitle(q) { if (q) { title.style.display = 'block' } else if (window.innerWidth < SMALL) { title.style.display = 'none' } } function updateFilter(f) { if (f.includes('f-')) { queryOption = f.substring(2) } else { queryOption = f } filters.forEach(elem => { elem.style.boxShadow = 'none' }) document.querySelector('#f-' + queryOption).style.boxShadow = 'inset rgba(0, 0, 0, 0.40) 0 0 5px' } document.addEventListener('click', e => { if (e.target.id !== 'suggestions' && e.target !== searchBar && e.target !== searchBarButton) { hideSuggestions() switchNavTitle(true) if (e.target.id === 'hamburger' || e.target.id === 'hamburgerSvg' || e.target.id === 'crossSvg') { if (ham.classList.contains('spin-fade')) switchHam(false) else switchHam(true) } if (e.target === errorButton || e.target === errorButton.firstElementChild) { error.classList.replace('fade-in', 'fade-out') } let toggleSwitch = null let toggleSwitchParent = null if (e.target.classList.contains('slider')) { toggleSwitch = e.target toggleSwitchParent = e.target.parentNode } else if (e.target.classList.contains('toggle-switch')) { toggleSwitch = e.target.firstElementChild toggleSwitchParent = e.target } if (toggleSwitch !== null && toggleSwitchParent !== null) { if (toggleSwitch.classList.contains('untoggle')) { toggleSwitchParent.style.backgroundColor = '#FFF' toggleSwitch.classList.replace('untoggle', 'toggle') } else { toggleSwitchParent.style.backgroundColor = '#ECECEC' toggleSwitch.classList.replace('toggle', 'untoggle') } } if (e.target.id.toString().includes('f-')) { updateFilter(e.target.id) } } }) searchBar.addEventListener('focus', () => { switchNavTitle(false) }) navbarForm.addEventListener('submit', e => { e.preventDefault() submitForm(0) }) let urlSearch = urlParams.get('search') let urlOption = urlParams.get('option') let urlOffset = urlParams.get('offset') updateFilter(urlOption ? urlOption : 'f-auto') if (urlSearch && urlOption && urlOffset) { searchBar.value = urlSearch apiRequestThese(urlSearch, urlOffset) }