The twitter clone is my ninth project of Scrimba Front-End course, in this course I build the duplication of twitter from scratch and structure the code to finish the layout design.
The Twitter Clone is my ninth static website, building the small features step by step and make sure the code is easily to read.
I start the Scrimba Module 5 course- Essential JavaScript Concepts and learn how to use advanced JavaScript. At the end of the course, I follow the instruction to finish the Twitter Clone, take a look at the → Twitter Clone.
- Learn how to set the textarea for user to input their replies, and render the replies.
- Insert the icons from the "Font Awesome CDN" website.
- Increase & Decrease the number of the "likes" and "tweets" icons.
- Change the color of icons when clicking.
- Render the replies by getting their UUID, and improving the UX.
Designing a twitter clone social media website requires following some rules and taking into consideration about each scrum tutorial. This project can be split into several small parts.
-
Take control of the data from Textarea when clicking button, then make sure the size of textarea fixed.
ℹ️ [TEXTAREA] GET to know more about the element. → W3School
-
resize for textarea element.
textarea{
border: none;
padding: 10px;
margin: 0 0 20px 0;
height: 60px;
width: 100%;
font-size: 20px;
line-height: 30px;
resize: none; //keeps textarea the same size
}
Look through how to use .forEach() → .forEach()
const characters = [
{
title: 'Ninja',
emoji: '🥷',
powers: ['agility', 'jsstealth', 'aggression'],
},
{
title: 'Sorcerer',
emoji: '🧙',
powers: ['magic', 'invisibility', 'necromancy'],
},
{
title: 'Ogre',
emoji: '👹',
powers: ['power', 'stamina', 'shapeshifting'],
},
{
title: 'Unicorn',
emoji: '🦄',
powers: [ 'flight', 'power', 'purity'],
}
]
characters.forEach(function(character){ //The purpose of using forEach is to make the code easy to read.
console.log(character)
//The result shows below.
//{title: "Ninja", emoji: "🥷", powers: ["agility", "stealth", "aggression"]}
//{title: "Sorcerer", emoji: "🧙", powers: ["magic", "invisibility", "necromancy"]}
//{title: "Ogre", emoji: "👹", powers: ["power", "stamina", "shapeshifting"]}
//{title: "Unicorn", emoji: "🦄", powers: ["flight", "power", "purity"]}
Explaination why should we use CDN. → AWS The icon examples which we can get from here. → FONT-AWESOME-CDN
<section class="icons-bar">
<i class="fa-solid fa-house"></i>
<i class="fa-solid fa-location-dot"></i> //Get icon resource class name //Have to understand the concept of the data attribute.
<i class="fa-regular fa-envelope"></i>
<i class="fa-regular fa-calendar-days"></i> //This is the example of how to use the data-attribute in the class.
</section>
document.addEventListener('click', function(e) {
if (e.target.dataset.share){
console.log(e.target.dataset.share) //output is image-1, review the code above,after clicking: output shows "image"
} //if return T then the data-share inside data element //The output is DOMStringMap {share: "image-1"}
})
import { tweetsData } from './data.js'
const tweetInput = document.getElementById('tweet-input')
const tweetBtn = document.getElementById('tweet-btn')
tweetBtn.addEventListener('click', function(){
console.log(tweetInput.value)
})
document.addEventListener('click', function(e){
if(e.target.dataset.like){
handleLikeClick(e.target.dataset.like)
}
})
function handleLikeClick(tweetId){
const targetTweetObj = tweetsData.filter(function(tweet){
return tweet.uuid === tweetId //if the tweet id is the same of the loop id,then return true
})[0] //The output is object, not array
targetTweetObj.likes++ //increase the like number when clicking
console.log(tweetsData)
}
//Make sure to listen to the button
document.addEventListener('click', function(e){
if(e.target.dataset.like){
handleLikeClick(e.target.dataset.like)
}
function handleLikeClick(tweetId){
const targetTweetObj = tweetsData.filter(function(tweet){
return tweet.uuid === tweetId
})[0]
if (targetTweetObj.isLiked){
targetTweetObj.likes--
}
else{
targetTweetObj.likes++
}
targetTweetObj.isLiked = !targetTweetObj.isLiked //The goal is to flip the boolean.
render()
}
const galleryContainer = document.getElementById('gallery-container')
let isLiked = false
let isShared = false
document.addEventListener('click', function(e){
if(e.target.dataset.heart){
isLiked = !isLiked //flip the boolean short-hand
render()
}
else if(e.target.dataset.share){
isShared = !isShared //flip the boolean short-hand
render()
}
})
function render(){
let heartClass = '' //initialize the variable
let shareClass = ''
if(isLiked){
heartClass = 'liked' //if "isLiked" is true then set up the Class to "liked"
}
if(isShared){
shareClass = 'shared'
}
let imageHtml = `
<div id="image-1" class="img-container">
<img src="dino2.jpeg" alt="Man in front of dinosaur">
<div class="social-icons-container">
<i class="fa-solid fa-heart ${heartClass}" data-heart="image-1"></i>
<i class="fa-solid fa-share ${shareClass}" data-share="image-1"></i>
</div>
`
galleryContainer.innerHTML = imageHtml
}
render()
<section class="gallery-container" id="gallery-container">
</section>
.liked{
color: #f80000; /* red */
}
.shared{
color: limegreen;
}
function getFeedHtml(){
let feedHtml = ``
tweetsData.forEach(function(tweet){ //loop through the object
let likeIconClass = ''
if (tweet.isLiked){
likeIconClass = 'liked'
}
let retweetIconClass = ''
if (tweet.isRetweeted){
retweetIconClass = 'retweeted'
}
if(tweet.replies.length > 0){
console.log(tweet.uuid) //check the length of the tweet if there is any replies then output its UUID
}
}
import { v4 as uuidv4 } from 'https://jspm.dev/uuid'; //import the UUID JS
const cars = [
{
brand: 'Nissan',
model: 'Leaf',
price: 3000,
uuid: '4fb2b6b7-c7ee-4c80-8de1-390e89f43d7f'
},
{
brand: 'Toyota',
model: 'Prius',
price: 6000,
uuid: '82a13f62-d239-46a2-a94f-020189338e1a'
},
]
cars.push({
brand: 'Tesla',
model: 'Model S',
price: '🤦♂️',
uuid: uuidv4() //Input function
})
console.log(cars)
<html>
<head>
<link rel="stylesheet" href="index.css">
</head>
<body>
<script src="index.js" type="module"></script> //setting to module
</body>
</html>
function handleTweetBtnClick(){
tweetsData.unshift({ //tweet the post in the beginning of the object
handle: `@Scrimba`,
profilePic: `images/scrimbalogo.png`,
likes: 0,
retweets: 0,
tweetText: tweetInput.value,
replies: [],
isLiked: false,
isRetweeted: false,
uuid: uuidv4()
})
render()
}
function handleTweetBtnClick(){
const tweetInput = document.getElementById('tweet-input')
if(tweetInput.value){ //If the value in the textarea exists then push the data into the array.
tweetsData.unshift({
handle: `@Scrimba`,
profilePic: `images/scrimbalogo.png`,
likes: 0,
retweets: 0,
tweetText: tweetInput.value,
replies: [],
isLiked: false,
isRetweeted: false,
uuid: uuidv4()
})
render()
tweetInput.value = ''
}
}