🍦 Vanilla JavaScript

Projects for the Vanilla JS Academy

Day 19

New York Times Multiple Categories

Goal

Modify the previous script to display five stories from multiple categories.

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 = category =>
	{
		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/${category}.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 = (category, stories) =>
	{
		let html =
			`<h3 class="font-family:sans font-size:0 font-weight:extrabold line-height:none text-transform:uppercase">${category}</h3>
			<div class="stack margin-top:1 story-items">`;

		stories.slice( 0, 5 ).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>`;
		});

		html += `</div>`;

		elStories.innerHTML += html;
	};

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

	elFetchStories.addEventListener( "click", () =>
	{
		elStories.innerHTML = "";

		let allStories = [];
		fetchStories( "arts" )
			.then( stories =>
			{
				renderStories( "Arts", stories );
				return fetchStories( "science" );
			})
			.then( stories =>
			{
				renderStories( "Science", stories );
				return fetchStories( "us" );
			})
			.then( stories =>
			{
				renderStories( "U.S.", stories );
				return fetchStories( "world" );
			})
			.then( stories =>
			{
				renderStories( "World", stories );
			})
			.catch( err => error.display( err.message ) );
	});
})();