Skip to content

Instantly share code, notes, and snippets.

@juanbrujo
Last active July 10, 2026 09:25
Show Gist options
  • Select an option

  • Save juanbrujo/25f7fd343182012466acc9f32383ff89 to your computer and use it in GitHub Desktop.

Select an option

Save juanbrujo/25f7fd343182012466acc9f32383ff89 to your computer and use it in GitHub Desktop.
<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>
'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();
});
})();
@emily410182

Copy link
Copy Markdown

index.html is the default homepage file for a website written in HTML. Spotifyalternative It defines the structure and content of the main web page, including elements such as headings, text, images, links, and navigation, and is typically the first page loaded when a user visits a website.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment