Project 2 - A Social News Web Page
Project Overview
Build a fully functional social news website with:
- Display news articles
- Like/dislike articles
- Comment on articles
- Filter articles by category
- Responsive design
Functional Requirements
- Display list of news articles
- Like/unlike functionality
- Add comments to articles
- Filter by category
- Responsive design
- Store data in browser
Technical Requirements
- Use modern DOM manipulation
- Event delegation for efficiency
- CSS for responsive layout
- Local storage for persistence
- Modular code structure
Project Structure
news-app/
├── index.html
├── style.css
├── script.js
└── data.js
HTML Structure
<!DOCTYPE html>
<html>
<head>
<title>Social News</title>
<link rel="stylesheet" href="style.css">
</head>
<body>
<header>
<h1>Social News</h1>
<nav>
<button class="filter-btn" data-category="all">All</button>
<button class="filter-btn" data-category="tech">Tech</button>
<button class="filter-btn" data-category="science">Science</button>
</nav>
</header>
<main>
<div id="articles" class="articles-container"></div>
</main>
<script src="data.js"></script>
<script src="script.js"></script>
</body>
</html>
JavaScript Implementation
class NewsApp {
constructor() {
this.articles = [];
this.currentFilter = "all";
this.init();
}
init() {
this.loadArticles();
this.render();
this.attachEventListeners();
}
loadArticles() {
this.articles = [
{
id: 1,
title: "JavaScript Tips",
content: "10 tips to improve...",
category: "tech",
likes: 45,
comments: []
}
// More articles...
];
}
render() {
let container = document.getElementById("articles");
container.innerHTML = "";
let filtered = this.currentFilter === "all"
? this.articles
: this.articles.filter(a => a.category === this.currentFilter);
filtered.forEach(article => {
container.innerHTML += this.createArticleHTML(article);
});
}
createArticleHTML(article) {
return `
<article class="article" data-id="${article.id}">
<h2>${article.title}</h2>
<p>${article.content}</p>
<div class="actions">
<button class="like-btn">👍 ${article.likes}</button>
<button class="comment-btn">💬 ${article.comments.length}</button>
</div>
</article>
`;
}
attachEventListeners() {
// Filter buttons
document.querySelectorAll(".filter-btn").forEach(btn => {
btn.addEventListener("click", (e) => {
this.currentFilter = e.target.dataset.category;
this.render();
});
});
// Like buttons
document.addEventListener("click", (e) => {
if (e.target.classList.contains("like-btn")) {
let articleId = e.target.closest(".article").dataset.id;
this.likeArticle(articleId);
}
});
}
likeArticle(articleId) {
let article = this.articles.find(a => a.id == articleId);
if (article) {
article.likes++;
this.render();
}
}
}
new NewsApp();
CSS Styling
body {
font-family: Arial, sans-serif;
margin: 0;
background: #f5f5f5;
}
header {
background: #333;
color: white;
padding: 20px;
text-align: center;
}
.articles-container {
max-width: 1000px;
margin: 20px auto;
}
.article {
background: white;
padding: 20px;
margin-bottom: 20px;
border-radius: 8px;
box-shadow: 0 2px 4px rgba(0,0,0,0.1);
}
.article h2 {
margin: 0 0 10px 0;
}
.actions button {
margin-right: 10px;
padding: 8px 16px;
border: none;
background: #007bff;
color: white;
border-radius: 4px;
cursor: pointer;
}
@media (max-width: 600px) {
.article {
padding: 15px;
}
}
Extended Features
Add Comments
addComment(articleId, commentText) {
let article = this.articles.find(a => a.id == articleId);
if (article) {
article.comments.push({
text: commentText,
timestamp: new Date()
});
this.render();
}
}
Search Functionality
searchArticles(query) {
return this.articles.filter(a =>
a.title.includes(query) ||
a.content.includes(query)
);
}
Learning Outcomes
After completing this project, you should be able to:
- ✅ Build interactive web applications
- ✅ Use event delegation efficiently
- ✅ Create responsive designs
- ✅ Manage complex state
- ✅ Implement filter and search functionality
Next Module: Module 21 - Building Web Applications