diff --git a/README.md b/README.md index e062a87..174523d 100644 --- a/README.md +++ b/README.md @@ -1,41 +1,19 @@ -# Responsive News Reader +# Overview -Let's create a responsive news reader website. To get the latest news the app will display we are going to use [News API](https://newsapi.org/). You will need to register with the service to obtain an API key. +Grabber is a simple news reader that pulls in current news circling Trump from all english-speaking countries and displays it vertically. -## Objectives +Articles are shown with any available image, description, title and date. -- [ ] Create a responsive layout that works well and looks good at mobile, tablet and desktop screen sizes. Please create the mobile version first, then tablet and then desktop. +Some tongue-in-cheek options for search refinement are given, as if to provide you with three wholly seperate perspectives. -- [ ] Fetch news articles from News API and display them including title, image, description, publication, date and link to article. +# Set Up -- [ ] Display images for tablet and desktop screens only - -- [ ] Implement a feature of your choice - -## Stretch goals - -- [ ] Implement pagination which allows you to get the next 20 results and display them - -- [ ] Add search functionality which allows the user to retrieve news about a particular topic - -## Instructions - -- Fork and clone this repo -- Commit your changes frequently with short and descriptive commit messages -- Create a pull request when complete -- We want to see great looking webpages -- Your code should have consistent indentation and sensible naming -- Use lots of concise functions with a clear purpose -- Add code comments where it is not immediately obvious what your code does - -## Getting started - -- Take a look at the API documentation to see what the response data will look like -- Start with pen and paper to draw what you want your new app to look like -- Create a basic HTML page with your layout -- Create a CSS file and a JS file and import them into the webpage. -- Use `fetch` load some news items from API and insert them into your web page. - -## README.md - -When finished, update this README.md file in your repo. This should explain what the project is, how to run it and how to use it. Someone who is not familiar with the project should be able to look at it and understand what it is and what to do with it. This is quite important as you want to put projects in your portfolio and the information provided here will help a reviewer understand what it is they are looking at. +Clone the repo +``` +git clone [repo path] +``` +Install project dependencies +``` +npm install +``` +Copy and paste the index.html path into your browser. diff --git a/images/flag.png b/images/flag.png new file mode 100644 index 0000000..aa77223 Binary files /dev/null and b/images/flag.png differ diff --git a/index.html b/index.html new file mode 100644 index 0000000..538865b --- /dev/null +++ b/index.html @@ -0,0 +1,44 @@ + + + + + + Grabber + + + + + +
+
+ +

Grabber

+ + + + +
+
+ +
+ +
+ +
+ +
+ + + + + \ No newline at end of file diff --git a/src/fetchingData.js b/src/fetchingData.js new file mode 100644 index 0000000..23761b4 --- /dev/null +++ b/src/fetchingData.js @@ -0,0 +1,201 @@ +//Pagination +let pageNum = 1; +let todayGMT = new Date(); +//Get yesterday's date +todayGMT.setDate(todayGMT.getDate() - 1); +let convertedToISO = todayGMT.toISOString(); +let url = `https://newsapi.org/v2/everything?q=trump&language=en&from=${convertedToISO}&sortby=popularity&apiKey=2b19d03fc1cf4cd7b62ac5bb15c98827&page=${pageNum}`; +/* + Send the 20(default) articles through a series of + functions one at a time to populate our ul. + "uri" should be undefined the first time, but not subsequent times + for purposes of pagination. +*/ +function grabData(uri) { + //Has something been passed into grabData()? + if (uri !== undefined) { + fetch(uri) + .then(response => { + return response.json(); + }) + .then(nextPageResults => { + console.log(uri); + console.log(nextPageResults); + passArticlesForCreation(nextPageResults); + }); + } else { + fetch(url) + .then(response => { + return response.json(); + }) + .then(body => { + passArticlesForCreation(body); + }); + } +} +const refreshButton = document.querySelector(".refresh"); +refreshButton.addEventListener("click", refreshFeed); + +const loadMoreButton = document.querySelector(".loadNext"); +loadMoreButton.addEventListener("click", loadMore); + +const topButton = document.querySelector(".up"); +topButton.addEventListener("click", backUp); + +const navList = document.querySelector(".options"); +navList.addEventListener("click", function(event) { + if (event.target.id !== "trump") { + let country = event.target.id; + let page = 1; + let period = convertedToISO; + let newFeedUrl = `https://newsapi.org/v2/top-headlines?q=trump&language=en&from=${period}&sortby=popularity&country=${country}&apiKey=2b19d03fc1cf4cd7b62ac5bb15c98827&page=${page}`; + const feed = document.querySelector(".articles__wrapper"); + feed.innerHTML = ""; + grabData(newFeedUrl); + } else { + trumpify(); + } +}); + +//Now this is what I call 'core functionality'. +function trumpify() { + console.log("present"); + const title = document.querySelector(".page__title"); + title.textContent = "Grabber by the p***y"; + const articles = document.querySelectorAll(".article__whole"); + console.log(articles[1].childNodes); + articles.forEach(article => { + article.childNodes[0].childNodes[0].textContent = randomPraise(); + article.childNodes[0].childNodes[0].style.backgroundColor = "#fff"; + article.style.backgroundImage = "url('images/flag.png')"; + }); +} +//Probably should be in own JSON file. +function randomPraise() { + let praise = [ + "Trump did nothing wrong.", + "Global superstar president Trump turns down nobel prize.", + "World peace declared under the greatest man to ever live, Donald Trump.", + "American masses call for all faces on Mt. Rushmore be replaced with Trump's dynamic visage.", + "The President has saved the lives of five local firemen.", + "Nine people confirmed better off under President Trump.", + "The President of the United States is a stand up dude.", + "'Make America Great Again' to be title of Spielberg's new biopic.", + "Quentin Tarantino 'okay, for a Jew' declares Trump magnanamously.", + "Trump to fight for 'bigger' womens rights.", + "New study shows: If you don't like the President... you're a communist.", + "Oh say can you see, that Trump is the greatest.", + "Fox News declares fealty to the legend himself.", + "Melania's US birth certificate miraculously found in the hands of Administration intern.", + "Tariffs - too short a word for lexicographer Trump. Should be Tariffics.", + "'Organge is the new black. You're all racist.' Declares Trump.", + "President orders new mandates for pronunciation: 'The Jina Ammendment'.", + "Lord of the Rings to be reshot with the President.", + "Trump overheard:'Kim Jong Un... sounds delicious, when's dinner?'", + "Hillary Clinton to be forcibly renamed Shrek, under Federal Law.", + "The USA to be henceforth referred to in full, according to President Donald J Trump, Great Proclaimer, Holy Unifier and Friend to Small Woodland Creatures." + ]; + let rand = praise[Math.floor(Math.random() * praise.length)]; + return rand; +} + +function backUp() { + window.scroll(0, 0); +} + +function refreshFeed() { + const title = document.querySelector(".page__title"); + title.textContent = "Grabber"; + //Clear the feed. + const feed = document.querySelector(".articles__wrapper"); + feed.innerHTML = ""; + //Fill the feed. + grabData(); +} + +function loadMore() { + pageNum++; + let period = convertedToISO; + let pageChange = pageNum++; + let updated = `https://newsapi.org/v2/everything?q=trump&language=en&from=${period}&sortby=popularity&apiKey=2b19d03fc1cf4cd7b62ac5bb15c98827&page=${pageChange}`; + grabData(updated); +} + +function passArticlesForCreation(jsonData) { + for (let i = 0; i < jsonData.articles.length; i++) { + createListElement(jsonData.articles[i]); + } +} + +//As they pass in, create list elements from them. +//Call populateNewsFeed on each one. +function createListElement(articleObject) { + /*CREATE THE LIST ITEM WITH ATTRIBUTES AND ARTICLE CONTENT */ + //List element + const article = document.createElement("li"); + article.className = "article__whole"; + //Title + const articleLink = document.createElement("a"); + articleLink.setAttribute("href", articleObject.url); + articleLink.className = "article__link"; + + const articleTitle = document.createElement("h2"); + articleTitle.textContent = articleObject.title; + + articleTitle.className = "article__title"; + + //Image and description + const imageDescWrapper = document.createElement("span"); + imageDescWrapper.className = "image__desc"; + + const articleImage = document.createElement("img"); + articleImage.setAttribute("src", articleObject.urlToImage); + articleImage.className = "article__image"; + + const articleDescription = document.createElement("p"); + articleDescription.textContent = articleObject.content; + articleDescription.className = "article__describe"; + + //Date and publication + const datePubWrapper = document.createElement("span"); + datePubWrapper.className = "date__pub"; + + const articleDate = document.createElement("p"); + const pubDate = new Date(articleObject.publishedAt); + const ammendedDate = pubDate + .toString() + .replace("GMT+0100 (British Summer Time)", ""); + articleDate.textContent = ammendedDate; + articleDate.className = "article__date"; + + const articlePub = document.createElement("p"); + articlePub.textContent = articleObject.source.name; + + /*ASSEMBLE THE LIST ITEM*/ + articleLink.appendChild(articleTitle); + article.appendChild(articleLink); + + imageDescWrapper.appendChild(articleImage); + imageDescWrapper.appendChild(articleDescription); + article.appendChild(imageDescWrapper); + + datePubWrapper.appendChild(articleDate); + datePubWrapper.appendChild(articlePub); + article.appendChild(datePubWrapper); + + populateNewsFeed(article); +} + +// Populate the created list elements: +function populateNewsFeed(article) { + feed = document.querySelector(".articles__wrapper"); + if (pageNum === 1) { + feed.prepend(article); + } else { + feed.appendChild(article); + } +} + +//PROGRAM START +document.addEventListener("DOMContentLoaded", grabData()); +document.querySelector(".options").style.cursor = "pointer"; diff --git a/style.css b/style.css new file mode 100644 index 0000000..9060d8d --- /dev/null +++ b/style.css @@ -0,0 +1,234 @@ +* { + box-sizing: inherit; +} +body { + font-family: "Roboto Slab", serif; + box-sizing: border-box; + margin: 0; + padding: 0%; + display: flex; + flex-direction: column; + min-height: 100vh; +} + +header { + display: flex; + flex-direction: column; + justify-content: center; +} + +.home { + padding-left: 10px; + text-decoration: none; +} +.home:visited { + text-decoration: none; + color: black; +} + +/*.creeper { + height: 500px; + width: 500px; +}*/ +.not__found { + display: none; +} + +.oi__cheeky { + display: none; +} + +.page__title { + font-size: 2em; +} + +.article__link { + text-decoration: none; + color: black; + transition: font-size 0.2s ease-in-out; +} +.article__link:hover { + font-size: 1.05em; +} + +.article__link:visited { + text-decoration: none; + color: black; +} + +.articles__wrapper { + display: flex; + flex-direction: column; + margin: 0; + padding: 0; +} +.article__whole { + flex-grow: 1; + padding: 10px; + background: #ededed; +} +.article__whole:hover { + background: #cfcfcf; +} + +.options { + display: none; +} +.options > li:hover { + color: #858585; +} + +.refresh { + background: #fff; + padding: 5px; + font-size: 16pt; + height: 50px; + width: 100%; + border-right: 0px; + border-left: 0px; +} + +.refresh:focus { + outline: 0; +} + +.article__link { + display: flex; + flex-wrap: wrap; +} + +.image__desc { + display: flex; +} + +.date__pub { + display: flex; + justify-content: space-between; +} + +.article__image { + display: none; +} + +.article__describe { + display: flex; +} + +.article__date { + padding: 0px, 5px, 0px, 5px; +} + +footer { + display: flex; + flex-direction: column; +} + +.loadNext { + background: #ededed; + padding: 5px; + border: none; + font-size: 16pt; + font-weight: bold; + transition: all 0.1s ease-in-out; + height: 50px; + width: 100%; + align-self: center; + font-family: "Roboto Slab", serif; +} +.loadNext:hover { + background: #c2c2c2; +} + +.up { + display: none; + background: #fff; + border: none; + font-family: "Roboto Slab", serif; +} +.bottom__row { + display: flex; + justify-content: center; + font-family: "Roboto Slab", serif; +} + +@media (min-width: 768px) { + header { + flex-direction: row; + justify-content: space-around; + } + .search { + margin-left: 30px; + height: 40px; + font-size: 1.5em; + } + .search__button { + font-size: 1.5em; + } + + .refresh { + transition: all 0.1s ease-in-out; + align-self: center; + border: 2px solid black; + border-radius: 5px; + width: 200px; + padding: 10px, 15px, 10px, 15px; + } + .refresh:hover { + transform: scale(1.1); + } + .options { + display: flex; + align-self: center; + list-style: none; + padding: 0; + } + .options > li { + text-decoration: none; + padding: 10px; + } + .article__image { + display: flex; + padding-right: 10px; + max-width: 230px; + max-height: 100px; + width: auto; + height: auto; + } + + .up { + text-align: center; + display: flex; + margin-right: 20px; + transition: margin-bottom 0.2s; + } + .up:hover { + margin-bottom: 10px; + } + .up:focus { + outline: 0; + } + + .bottom__row { + display: flex; + justify-content: space-between; + } + .author { + padding-left: 10px; + } +} + +@media (min-width: 1440px) { + .article__whole { + padding-left: 100px; + } + .up { + width: 400px; + font-size: 1.2em; + } + .article__describe { + max-width: 900px; + } + .date__pub { + justify-content: space-around; + } +}