-
Notifications
You must be signed in to change notification settings - Fork 34
Responsive-news-reader #31
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: master
Are you sure you want to change the base?
Changes from all commits
976c122
5aa5636
c32b762
8a1c31d
608a11c
56d0a83
cdc7701
83ec6d9
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,36 @@ | ||
| <!DOCTYPE html> | ||
| <html lang="en"> | ||
|
|
||
| <head> | ||
| <meta charset="UTF-8"> | ||
| <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no"> | ||
| <meta http-equiv="X-UA-Compatible" content="ie=edge"> | ||
| <title>UK News</title> | ||
| <link rel="stylesheet" href="style.css"> | ||
| <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/4.7.0/css/font-awesome.min.css"> | ||
| <link href="https://fonts.googleapis.com/css?family=Ubuntu" rel="stylesheet"> | ||
| </head> | ||
|
|
||
| <body> | ||
| <div class="app"> | ||
| <div class="header"> | ||
| <div class="logo">UK News</div> | ||
| <div class="search_form"> | ||
| <form class="search"> | ||
| <input id='search' type="text" placeholder="Search all news..."> | ||
| <button type="submit"><i class="fa fa-search"></i></button> | ||
| </form> | ||
| </div> | ||
| </div> | ||
| <div class="main"> | ||
| <div id="newsfeed"> | ||
|
|
||
| </div> | ||
| <button onclick="topFunction()" id="myBtn" title="Go to top">Go to Top</button> | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
| </div> | ||
| </div> | ||
| <script src="src/index.js"></script> | ||
| </body> | ||
| <footer>Powered by News API</footer> | ||
|
|
||
| </html> | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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 = `<div class="title"><h2>${article.title}</h2></div> | ||
|
|
||
| <div class="date"><h4>${date}</h4></div> | ||
|
|
||
| <div class="img"><img src="${article.urlToImage}"></div> | ||
|
|
||
| <div class="content"><p>${article.description}</p></div> | ||
|
|
||
| <div class="source"><h4>Source: ${ | ||
| article.source.name | ||
| }</h4></div> | ||
|
|
||
| <div class="more-news"><button class="news" data-source="${articleSource}">More headlines from this source</button></div> | ||
|
|
||
| <div class="link"><a href="${ | ||
| article.url | ||
| }">Read all about it</a></div>`; | ||
| } else { | ||
| divNode.className = "article-div"; | ||
|
|
||
| divNode.innerHTML = `<div class="title"><h2>${article.title}</h2></div> | ||
|
|
||
| <div class="date"><h4>${date}</h4></div> | ||
|
|
||
| <div class="content"><p>${article.description}</p></div> | ||
|
|
||
| <div class="source"><h4>Source: ${article.source.name}</h4></div> | ||
|
|
||
| <div class="more-news"><button class="news" data-source="${articleSource}>More headlines from this source</button></div> | ||
|
|
||
| <div class="link"><a href="${ | ||
| article.url | ||
| }">Read all about it</a></div>`; | ||
| } | ||
|
|
||
| // 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 => { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. querySelectorAll returns a NodeList and we can't set an event handler on it. It would have to be done on each element in list individually |
||
|
|
||
| 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(); | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. the function calls should be separated by |
||
| }; | ||
|
|
||
| // 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() { | ||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. function could have a more descriptive name |
||
| 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 | ||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -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; | ||
| } | ||
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
It would be better to keep event handler setting in JS rather than apply inline