diff --git a/index.html b/index.html new file mode 100644 index 0000000..528839e --- /dev/null +++ b/index.html @@ -0,0 +1,36 @@ + + + + + + + + UK News + + + + + + +
+
+ +
+ +
+
+
+
+ +
+ +
+
+ + + + + \ No newline at end of file diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..e9aee4a --- /dev/null +++ b/src/index.js @@ -0,0 +1,167 @@ +const url = + "https://newsapi.org/v2/top-headlines?" + + "country=gb&" + + "apiKey=7318e7fb7dc04d14af2f0fd675cfda53"; + +const req = new Request(url); + +// Fetch function for the main headlines +fetch(req) + .then(function(response) { + return response.json(); + }) + + .then(function(body) { + displayArticles(body); + }); + + +// Function which generates a div containing the article's headline, time, img, discription, source and link +function displayArticles(body) { + body.articles.forEach(article => { + + //Timestamp is converted into GMT date and time format + const ts = new Date(`${article.publishedAt}`); + const date = ts.toGMTString(); + + //If article does not have description it will not be displayed + if (article.description) { + const divNode = document.createElement("div"); + + //Two divs are generated due to the final layout for wide screens + // one with img and one without; + const articleSource= article.source.id ? article.source.id : article.source.name + + if (article.urlToImage) { + divNode.className = "article-div-w-img"; + + divNode.innerHTML = `

${article.title}

+ +

${date}

+ +
+ +

${article.description}

+ +

Source: ${ + article.source.name + }

+ +
+ + `; + } else { + divNode.className = "article-div"; + + divNode.innerHTML = `

${article.title}

+ +

${date}

+ +

${article.description}

+ +

Source: ${article.source.name}

+ +
`; + } + + // The newly created article div is added to the newsfeed + const parentNode = document.querySelector("#newsfeed"); + parentNode.appendChild(divNode); + }; + + }); +} + + +//Add event listener to the search form +document.querySelector("form").addEventListener("submit", e => { + e.preventDefault(); + let searchItem = document.querySelector("#search").value; + //The exisiting newsfeed is cleared before search results displayed + document.querySelector("#newsfeed").textContent = ""; + + const searchURL = + "https://newsapi.org/v2/everything?" + + `q=${searchItem}&` + + "from=2018-09-14&" + + "sortBy=popularity&" + + "language=en&" + + "apiKey=7318e7fb7dc04d14af2f0fd675cfda53"; + + const reqURL = new Request(searchURL); + + fetch(reqURL) + .then(function(response) { + return response.json(); + }) + + .then(function(body) { + displayArticles(body); + }); + + document.querySelector("#search").value = ""; +}); + + // Tried adding an event listener to 'More news from this source button', but it does not seem to work. + document.querySelectorAll(".news").addEventListener("click", e => { + + let requiredSource = e.target.dataset.source; + + document.querySelector("#newsfeed").textContent = ""; + let newSourceURL = + "https://newsapi.org/v2/top-headlines?" + + `sources=${requiredSource}&` + + "apiKey=7318e7fb7dc04d14af2f0fd675cfda53"; + + const source = new Request(newSourceURL); + + fetch(source) + .then(function(response) { + return response.json(); + }) + + .then(function(body) { + displayArticles(body); + //This is to remove 'More news from this source button' once the event listener function runs + document.querySelectorAll(".news").style.display = "none"; + }); + }); + +//Two functions are executed on scroll - sticky header and 'go to top' button +window.onscroll = function() { + myFunction(), scrollFunction(); +}; + +// myFunction() activates sticky header +var header = document.querySelector(".header"); +var sticky = header.offsetTop; +// Add the sticky class to the header when you reach its scroll position. Remove "sticky" when you leave the scroll position +function myFunction() { + if (window.pageYOffset >= sticky) { + header.classList.add("sticky"); + } else { + header.classList.remove("sticky"); + } +} + +// When the user scrolls down 20px from the top of the document, show the 'go to top' button +function scrollFunction() { + if (document.body.scrollTop > 20 || document.documentElement.scrollTop > 20) { + document.getElementById("myBtn").style.display = "block"; + } else { + document.getElementById("myBtn").style.display = "none"; + } +} + +// When the user clicks on the 'go to top' button, scroll to the top of the document +function topFunction() { + document.body.scrollTop = 0; // For Safari + + document.documentElement.scrollTop = 0; // For Chrome, Firefox, IE and Opera +} diff --git a/style.css b/style.css new file mode 100644 index 0000000..5a85609 --- /dev/null +++ b/style.css @@ -0,0 +1,189 @@ +body { + margin: 0px; +} + +html { + box-sizing: border-box; + font-family: "Ubuntu", Helvetica, Arial, sans-serif; +} +*, +*:before, +*:after { + /* display: none; */ + box-sizing: inherit; +} + +.header { + font-family: "Ubuntu", sans-serif; + font-size: 40px; + font-weight: 800; + background-color: #a2b6db; + margin: 0px; + padding: 0.2em; +} + +/* The sticky class is added to the header with JS when it reaches its scroll position */ +.sticky { + position: fixed; + top: 0; + width: 100%; +} + +/* Add some top padding to the page content to prevent sudden quick movement (as the navigation bar gets a new position at the top of the page (position:fixed and top:0) */ +.sticky + .main { + padding-top: 80px; +} + +/* Style the search field */ +form.search input[type="text"] { + padding: 10px; + font-size: 17px; + border: 1px solid grey; + float: left; + width: 80%; + background: #f1f1f1; +} + +/* Style the submit button */ +form.search button { + float: left; + width: 20%; + padding: 10px; + background: #bbd1e1; + color: white; + font-size: 17px; + border: 1px solid grey; + border-left: none; /* Prevent double borders */ + cursor: pointer; +} + +form.search button:hover { + background: #95b8d1; +} + +/* Clear floats */ +form.search::after { + content: ""; + clear: both; + display: table; +} + +main { + margin: 0px; +} + +/*No image displayed in mobile version*/ +img { + display: none; +} + +h2 { + font-size: 1.2em; + background-color: #d1ebe2; + margin: 0; +} + +h4 { + margin: 0.5em 0em 0em 0em; +} + +.article-div, +.article-div-w-img { + display: flex; + flex-flow: wrap; + background-color: #f7fbf9; + margin: 2em 1em 1em 1em; +} + +.title, +.date, +.link { + width: 100vw; +} + +.more-news { + align-self: flex-end; +} + +.source { + margin: 0em 2em 0em 0em; +} + +.news { + background-color: #d5b3c2; + border-radius: 6px; +} + +.news:hover { + background-color: #d64f89; +} + +footer { + text-align: right; + margin: 1em; + font-size: 70%; +} + +/* CSS relating to 'Go to top' button */ +#myBtn { + display: none; /* Hidden by default */ + position: fixed; /* Fixed/sticky position */ + bottom: 2em; + right: 1em; + z-index: 99; /* Make sure it does not overlap */ + border: none; + outline: none; + background-color: #a2b6db; + cursor: pointer; /* Add a mouse pointer on hover */ + padding: 15px; + border-radius: 10px; + font-size: 18px; +} + +#myBtn:hover { + background-color: #bbd1e1; +} + +@media (min-width: 768px) { + .header { + display: flex; + flex-direction: row; + justify-content: space-between; + } + + /* Article background colour changes on hover */ + .article-div-w-img:hover { + background-color: #f9eef3; + } + + /* Where the article has an image, the image and the description will be placed side by side */ + .article-div-w-img > .content, + .img { + width: 46vw; + } + + img { + display: block; + height: auto; + max-width: 97%; + } + + .link { + text-align: right; + } + + .article-div { + display: flex; + flex-flow: wrap; + } + + .article-div > .content { + width: 100vw; + } + + /* Changed 'Go to Top' button position for larger screen due to the general changes in conents position */ + #myBtn { + bottom: 3em; + right: 10em; + } +}