Skip to content

Commit 7f5e6d2

Browse files
committed
Adding Day #71
1 parent 6782074 commit 7f5e6d2

File tree

6 files changed

+296
-1
lines changed

6 files changed

+296
-1
lines changed
+27
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
# Day #71
2+
3+
### Weather App
4+
In this tutorial ([Open in Youtube](https://youtu.be/yXl6N9UqpUQ)), we're diving into the world of web development to create a sleek and functional news aggregator website from scratch using HTML, CSS, and JavaScript.
5+
6+
🎥 In this video, you'll learn step-by-step how to:
7+
1. Set up the basic structure of our website using HTML.
8+
2. Style our website to perfection with CSS, making it visually appealing and user-friendly.
9+
Implement dynamic functionality using JavaScript to fetch and display news articles from various sources.
10+
3. Enhance user experience by adding features like search functionality and category filtering.
11+
4. Optimize our code for performance and responsiveness, ensuring our website looks great on all devices.
12+
13+
Whether you're a beginner looking to expand your coding skills or a seasoned developer seeking a fun project to tackle, this tutorial has something for everyone!
14+
So grab your favorite coding beverage ☕️, fire up your text editor, and let's embark on this coding adventure together. By the end of this video, you'll have a fully functional news aggregator website to impress your friends and add to your portfolio.
15+
16+
## Warning
17+
You need to get your own api key (in video we showed how!) and replace it in script.js file on line 1 :
18+
19+
```javascript
20+
const API_KEY = 'YOUR_API_KEY';
21+
```
22+
23+
24+
# Screenshot
25+
Here we have project screenshot :
26+
27+
![screenshot](screenshot.jpg)
+40
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
4+
<head>
5+
<meta charset="UTF-8">
6+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
7+
<link rel="stylesheet" href="style.css">
8+
<title>Day #71 - News Aggregator App | AsmrProg</title>
9+
</head>
10+
11+
<body>
12+
13+
<div class="container">
14+
<h1>News Aggregator</h1>
15+
16+
<div class="selectionContainer">
17+
<label for="category">Choose Category :</label>
18+
<select id="category">
19+
<option value="business">Business</option>
20+
<option value="entertainment">Entertainment</option>
21+
<option value="general">General</option>
22+
<option value="health">Health</option>
23+
<option value="science">Science</option>
24+
<option value="sports">Sports</option>
25+
<option value="technology">Technology</option>
26+
</select>
27+
<button id="fetchCategory">Fetch News</button>
28+
</div>
29+
30+
<div class="searchContainer">
31+
<input type="text" id="searchKeyword" placeholder="Search for news...">
32+
<button onclick="fetchNews(true)">Search Key</button>
33+
</div>
34+
<div id="newsContainer"></div>
35+
</div>
36+
37+
<script src="script.js"></script>
38+
</body>
39+
40+
</html>
415 KB
Loading
+91
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,91 @@
1+
const API_KEY = 'YOUR_API_KEY';
2+
3+
let currentPage = 1;
4+
let currentCategory = null;
5+
let currentKeyword = null;
6+
let isLoading = false;
7+
let lastArticleCount = 0;
8+
9+
function fetchNews(isSearching) {
10+
if (isLoading) return;
11+
12+
isLoading = true;
13+
let url;
14+
if (isSearching) {
15+
const keyword = document.getElementById('searchKeyword').value;
16+
url = `https://newsapi.org/v2/everything?q=${keyword}&apiKey=${API_KEY}&page=${currentPage}`;
17+
} else {
18+
const category = currentCategory || document.getElementById('category').value;
19+
url = `https://newsapi.org/v2/top-headlines?country=us&category=${category}&apiKey=${API_KEY}&page=${currentPage}`;
20+
}
21+
22+
fetch(url).then(response => response.json()).then(data => {
23+
const newsContainer = document.getElementById('newsContainer');
24+
if (currentPage === 1) {
25+
newsContainer.innerHTML = '';
26+
}
27+
28+
const articlesWithImage = data.articles.filter(article => article.urlToImage);
29+
30+
if (articlesWithImage.length === 0 || articlesWithImage.length === lastArticleCount) {
31+
displayNoMoreNews();
32+
return;
33+
}
34+
35+
lastArticleCount = articlesWithImage.length;
36+
37+
articlesWithImage.forEach(article => {
38+
const newsItem = `
39+
<div class="newsItem">
40+
<div class="newsImage">
41+
<img src="${article.urlToImage}" alt="${article.title}">
42+
</div>
43+
<div class="newsContent">
44+
<div class="info">
45+
<h5>${article.source.name}</h5>
46+
<span>|</span>
47+
<h5>${article.publishedAt}</h5>
48+
</div>
49+
<h2>${article.title}</h2>
50+
<p>${article.description}</p>
51+
<a href="${article.url}" target="_blank">Read More</a>
52+
</div>
53+
</div>
54+
`;
55+
newsContainer.innerHTML += newsItem;
56+
});
57+
58+
currentPage++;
59+
isLoading = false;
60+
}).catch(error => {
61+
console.error("There was an error fetching the news:", error);
62+
isLoading = false;
63+
});
64+
}
65+
66+
function displayNoMoreNews() {
67+
const newsContainer = document.getElementById('newsContainer');
68+
newsContainer.innerHTML += '<p>No more news to load.</p>';
69+
}
70+
71+
window.onscroll = function () {
72+
if ((window.innerHeight + window.scrollY) >= document.body.offsetHeight - 10) {
73+
if (currentKeyword) {
74+
fetchNews(true);
75+
} else {
76+
fetchNews(false);
77+
}
78+
}
79+
}
80+
81+
document.getElementById('searchKeyword').addEventListener('input', function () {
82+
currentPage = 1;
83+
currentCategory = null;
84+
currentKeyword = this.value;
85+
});
86+
87+
document.getElementById('fetchCategory').addEventListener('click', function () {
88+
currentPage = 1;
89+
currentKeyword = null;
90+
fetchNews(false);
91+
});
+136
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,136 @@
1+
@import url('https://fonts.googleapis.com/css2?family=Roboto:ital,wght@0,100;0,300;0,400;0,500;0,700;0,900;1,100;1,300;1,400;1,500;1,700;1,900&display=swap');
2+
3+
body{
4+
font-family: 'Roboto', sans-serif;
5+
background-color: #f5f5f5;
6+
margin: 0;
7+
padding: 0;
8+
}
9+
10+
.container{
11+
max-width: 900px;
12+
margin: 50px auto;
13+
padding: 30px;
14+
border-radius: 10px;
15+
background-color: #fff;
16+
transition: all 0.3s ease;
17+
}
18+
19+
.container:hover{
20+
box-shadow: 0 10px 30px rgba(0, 0, 0, 0.1);
21+
}
22+
23+
h1{
24+
text-align: center;
25+
margin-bottom: 30px;
26+
color: #333;
27+
border-bottom: 2px solid #e0e0e0;
28+
padding-bottom: 30px;
29+
}
30+
31+
.selectionContainer,
32+
.searchContainer{
33+
display: flex;
34+
align-items: center;
35+
justify-content: space-between;
36+
margin-bottom: 20px;
37+
}
38+
39+
label{
40+
font-size: 16px;
41+
margin-right: 10px;
42+
}
43+
44+
select,
45+
input[type="text"]{
46+
padding: 8px;
47+
flex: 1;
48+
border: 1px solid #e0e0e0;
49+
border-radius: 5px;
50+
outline: none;
51+
}
52+
53+
button{
54+
background-color: #000;
55+
color: #fff;
56+
padding: 8px 20px;
57+
border: none;
58+
border-radius: 6px;
59+
cursor: pointer;
60+
margin-left: 15px;
61+
transition: all 0.3s ease;
62+
}
63+
64+
.newsItem{
65+
display: flex;
66+
align-items: center;
67+
margin-top: 40px;
68+
border-bottom: 1px solid #e0e0e0;
69+
padding-bottom: 20px;
70+
}
71+
72+
.newsItem:last-child{
73+
border-bottom: none;
74+
}
75+
76+
.newsImage{
77+
flex: 1;
78+
max-width: 300px;
79+
}
80+
81+
.newsImage img{
82+
max-width: 100%;
83+
height: 180px;
84+
object-fit: cover;
85+
border-radius: 10px;
86+
}
87+
88+
.newsContent{
89+
flex: 2;
90+
margin-left: 20px;
91+
}
92+
93+
.newsContent .info{
94+
display: flex;
95+
align-items: center;
96+
gap: 8px;
97+
color: #888;
98+
margin-bottom: 12px;
99+
}
100+
101+
.newsContent .info h5{
102+
margin: 0;
103+
font-weight: 400;
104+
}
105+
106+
.newsContent h2{
107+
font-size: 18px;
108+
color: #444;
109+
margin-top: 0;
110+
max-height: 44px;
111+
overflow: hidden;
112+
}
113+
114+
.newsContent p{
115+
color: #777;
116+
margin: 10px 0 20px;
117+
font-size: 14px;
118+
max-height: 33px;
119+
overflow: hidden;
120+
}
121+
122+
.newsContent a{
123+
background-color: #000;
124+
color: #fff;
125+
padding: 8px 14px;
126+
font-size: 13px;
127+
border-radius: 6px;
128+
text-decoration: none;
129+
font-weight: bold;
130+
transition: all 0.3s ease;
131+
}
132+
133+
button:hover,
134+
.newsContent a:hover{
135+
background-color: #e4010b;
136+
}

README.md

+2-1
Original file line numberDiff line numberDiff line change
@@ -80,8 +80,9 @@ Here we have list of projects:
8080
68. JSON Parser
8181
69. Form Validation
8282
70. Calendar With Events
83+
71. News Aggregator App
8384

84-
## Where is rest 30 Projects
85+
## Where is rest 29 Projects
8586

8687
We create a project each 3 days with voting on our <a href="https://youtube.com/@AsmrProg" target="_blank">Youtube</a> channel.
8788
You can vote for upcoming projects on our channel **community** page :wink:

0 commit comments

Comments
 (0)