🍦 Vanilla JavaScript

Projects for the Vanilla JS Academy

Day 17

New York Times Top Stories

Goal

Display top stories using the New York Times API.

Project

View Source
let error = (() =>
{
	let elError = document.querySelector( "#error-message" );
	let methods = {};

	/**
	 * @param {string} message
	 */
	methods.display = message =>
	{
		elError.innerText = message;
		elError.classList.remove( "hidden" );
	}

	methods.dismiss = () => elError.classList.add( "hidden" );

	return methods;
})();

(() =>
{
	/* Variables and UI elements */
	let elApiKey = document.querySelector( "#api-key" );
	elApiKey.value = localStorage.getItem( "nyt-api-key" );

	let elFetchStories = document.querySelector( "#fetch-stories" );
	let elStories = document.querySelector( "#stories" );
	let elStoryItems = document.querySelector( "#story-items" );

	/**
	 * @param {Object[]}
	 */
	let fetchStories = () =>
	{
		error.dismiss();

		let apiKey = elApiKey.value;
		if( !apiKey )
		{
			error.display( "Please provide an API key before proceeding." );
			return;
		}

		let apiURL = `https://api.nytimes.com/svc/topstories/v2/home.json?api-key=${apiKey}`;

		return fetch( apiURL )
			.then( response => response.json() )
			.then( json =>
			{
				if( json.fault )
				{
					if( json.fault.detail.errorcode === "oauth.v2.InvalidApiKey" )
					{
						throw new Error( "Invalid API key" );
					}

					throw new Error( json.fault.faultstring );
				}

				elStories.classList.remove( "hidden" );
				return json.results;
			});

	};

	/**
	 * @param {Object[]}
	 */
	let renderStories = stories =>
	{
		let html = "";
		stories.forEach( story =>
		{
			let thumbnail = story.multimedia.find( image => image.format === "thumbLarge" );
			html +=
				`<a class="story columns" href="${story.url}">
					<img src="${thumbnail.url}" loading="lazy">
					<article>
						<p><strong>${story.title}</strong></p>
						<p>${story.abstract}</p>
					</article>
				</a>`;
		});

		elStoryItems.innerHTML = html;
	};

	/* Event listeners */
	elApiKey.addEventListener( "input", e =>
	{
		localStorage.setItem( "nyt-api-key", e.target.value );
	});

	elFetchStories.addEventListener( "click", () =>
	{
		fetchStories()
			.then( stories => renderStories( stories ) )
			.catch( err => error.display( err.message ) );
	});
})();