Last active
December 29, 2024 19:23
-
-
Save juanbrujo/25f7fd343182012466acc9f32383ff89 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<form action='index.php' method='post'> | |
<input name='title' type='text' placeholder='Title...' value=''> | |
<div class='articles-list'></div> | |
<br /> | |
<textarea name='body' placeholder='Content...' ></textarea> | |
<br /> | |
<a class='submit-button' href='#' />Submit</a> | |
<br /> | |
<div class='error-message'></div> | |
</form> |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
'use strict'; | |
// TODO A: Improve readability and documentation. | |
// TODO B: Implement an autocomplete functionality for the text input. | |
// TODO C: Preview file content when clicking on an autocomplete suggestion. | |
// TODO D: Display autocomplete suggestions only when the input is in focus. | |
// TODO E: Add error handling for the autocomplete suggestions in case of a network failure. | |
(() => { | |
const submitButton = document.querySelector('.submit-button'); | |
const form = document.querySelector('form'); | |
const articleTitle = document.querySelector('input'); | |
const articleBody = document.querySelector('textarea'); | |
const autoCompleteList = document.querySelector('.articles-list'); | |
const errorMessage = document.querySelector('.error-message'); | |
const delay = 200; | |
/** | |
* Create child element for the autocomplete list. | |
* | |
* @function createChildOption | |
* @param {string} articleName | |
* @returns {HTMLElement} The created child option element wrapped | |
*/ | |
const createChildOption = (articleName) => { | |
const childOption = document.createElement('div'); | |
childOption.textContent = articleName; | |
childOption.addEventListener('click', () => { | |
articleTitle.value = articleName; | |
fetchArticleContent(articleName); | |
clearAutoCompleteList(); | |
}); | |
return childOption; | |
}; | |
/** | |
* Clear autocomplete list removing all child elements and hides the list | |
* from view. | |
* | |
* @function clearAutoCompleteList | |
*/ | |
const clearAutoCompleteList = () => { | |
autoCompleteList.innerHTML = ''; | |
autoCompleteList.style.display = 'none'; | |
} | |
/** | |
* Handles errors that occur during data fetching. | |
* | |
* @function handleFetchError | |
* @param {Error} error - The error object thrown during the fetch operation | |
*/ | |
const handleFetchError = (error) => { | |
console.error('Error fetching data:', error); | |
errorMessage.textContent = 'Unable load content. Please try again.'; | |
errorMessage.style.display = 'block'; | |
}; | |
/** | |
* Fetch an existing title of an article based on a search query | |
* and fill the autocomplete list. | |
* | |
* @function fetchArticleTitle | |
* @param {string} query | |
*/ | |
const fetchArticleTitle = (query) => { | |
fetch(`/api.php?search=${encodeURIComponent(query)}`) | |
.then(response => { | |
if (!response.ok) { | |
throw new Error(`HTTP error: ${response.status}`); | |
} | |
return response.json(); | |
}) | |
.then(data => { | |
autoCompleteList.innerHTML = ''; | |
if (data.content && data.content.length > 0) { | |
data.content.forEach(articleName => { | |
const childOption = createChildOption(articleName); | |
autoCompleteList.appendChild(childOption); | |
}); | |
autoCompleteList.style.display = 'block'; | |
} else { | |
autoCompleteList.style.display = 'none'; | |
} | |
}) | |
.catch(error => { | |
clearAutoCompleteList(); | |
handleFetchError(error); | |
}); | |
} | |
/** | |
* Fetch the content of an article based on its title and fill textarea. | |
* | |
* @function fetchArticleContent | |
* @param {string} title | |
*/ | |
const fetchArticleContent = (title) => { | |
fetch(`/api.php?title=${encodeURIComponent(title)}`) | |
.then(response => { | |
if (!response.ok) { | |
throw new Error(`HTTP error: ${response.status}`); | |
} | |
return response.json(); | |
}) | |
.then(data => { | |
articleBody.value = data.content; | |
errorMessage.style.display = 'none'; | |
}) | |
.catch(error => { | |
handleFetchError(error); | |
}); | |
}; | |
/** | |
* Initializes the autocomplete functionality for the article title input. | |
* | |
* This function set up event listeners to provide autocomplete suggestions | |
* as the user types in the input field. Handle hiding the autocomplete list | |
* when the input loses focus. | |
* | |
* The autocomplete data are fetched after a delay to avoid too many | |
* requests in short time. | |
* | |
* @function autoComplete | |
*/ | |
const autoComplete = () => { | |
let autoCompleteTimeout = null; | |
articleTitle.addEventListener('input', function () { | |
const query = this.value.trim(); | |
clearTimeout(autoCompleteTimeout); | |
clearAutoCompleteList(); | |
if (query.length === 0) return; | |
autoCompleteTimeout = setTimeout(() => { | |
fetchArticleTitle(query); | |
}, delay); | |
}); | |
/** | |
* Hide the autocomplete list with a delay when the input loses focus. | |
*/ | |
articleTitle.addEventListener('blur', () => { | |
setTimeout(() => { | |
clearAutoCompleteList(); | |
}, delay); | |
}); | |
} | |
/** | |
* Validate the form fields before submitting the form. | |
* | |
* @function submitArticle | |
*/ | |
const submitArticle = () => { | |
submitButton.addEventListener('click', (e) => { | |
if (articleTitle.value.trim() === '' || articleBody.value.trim() === '') { | |
e.preventDefault(); | |
errorMessage.innerHTML = 'Fields shouldn\'t be empty.'; | |
errorMessage.style.display = 'block'; | |
} else { | |
form.submit(); | |
} | |
}); | |
}; | |
/** | |
* Calls submitArticle function on DOM loaded to set up the form submission. | |
* | |
* @event DOMContentLoaded | |
*/ | |
document.addEventListener('DOMContentLoaded', function() { | |
autoComplete(); | |
submitArticle(); | |
}); | |
})(); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment