简体   繁体   中英

Track when user clicks on buttons in localstorage

I am making a basic news website with different API's. I want to track in local storage which news articles the user clicks on and reads. At the moment it doesn't track when I click the link-btn , but instead it tracks when I reload the site.

The last code in the script is supposed to be the code to track when the user clicks the different articles. I know how to make it track if I click only 1 btn/article, but how do I track when there are multiple articles?

const apiKey = "API-KEY";
// display the news on the page
const fetchNews = async() => {
  const response = await fetch(
    "https://newsapi.org/v2/top-headlines?country=us&category=business&apiKey=d1b8b964fce34d61aa47037c7155f638"
  );
  const data = await response.json();
  return data;
};

let bigNews = document.getElementById("bigNews");
let smallNews1 = document.getElementById("smallNews1");
let smallNews2 = document.getElementById("smallNews2");
let smallNews3 = document.getElementById("smallNews3");
let smallNews4 = document.getElementById("smallNews4");
let smallNews5 = document.getElementById("smallNews5");
let smallNews6 = document.getElementById("smallNews6");

const displayNews = async() => {
  const news = await fetchNews();
  bigNews.innerHTML = `
  <div class="card">
  <img id="bigNewsImg" src="${news.articles[0].urlToImage}" class="card-img-top" alt="..."> 
  <div class="card-body">
    <h5 class="card-title">${news.articles[0].title}</h5>
    <a href="${news.articles[0].url}" class="btnLink">Read more</a>
  </div>
</div>
  `; //display the news on the page with the help of the template literal
};

displayNews();

//Ovenstående Kode er skrevet af GitHub Copilot

/*const displayBigNews = async () => {
  bigNewsImage = document.querySelector("bigNewsImage");
  bigNewsText = document.getElementById("bigNewsText").value;
  bigNewsTitle = document.getElementById("bigNewsTitle");
  bigNewsLink = document.getElementById("bigNewsLink");

  const news = await fetchNews();
  bigNewsImage.setAttribute("src", news.articles[0].urlToImage);
  //bigNewsText.innerHTML = news.articles[0].description;
  bigNewsLink.innerHTML = news.articles[0].url;
};
displayBigNews();*/

const displaySmallNews1 = async() => {
  const news = await fetchNews();
  smallNews1.innerHTML = `
  <div class="card">
  <img id="smallNews1Img" src="${news.articles[1].urlToImage}" class="card-img-top" alt="...">
  <div class="card-body">
    <h5 class="card-title">${news.articles[1].title}</h5>
    <a href="${news.articles[1].url}" class="btnLink">Read more</a>
  </div>
</div>
  `;
};

displaySmallNews1();

const displaySmallNews2 = async() => {
  const news = await fetchNews();
  smallNews2.innerHTML = `
  <div class="card">
  <img id="smallNews2Img" src="${news.articles[2].urlToImage}" class="card-img-top" alt="...">
  <div class="card-body">
    <h5 class="card-title">${news.articles[2].title}</h5>
    <a href="${news.articles[2].url}" class="btnLink">Read more</a>
  </div>
</div>
  `;
};

displaySmallNews2();

const displaySmallNews3 = async() => {
  const news = await fetchNews();
  smallNews3.innerHTML = `
  <div class="card">
  <img id="smallNews3Img" src="${news.articles[3].urlToImage}" class="card-img-top" alt="...">
  <div class="card-body">
    <h5 class="card-title">${news.articles[3].title}</h5>
    <a href="${news.articles[3].url}" class="btnLink">Read more</a>
  </div>
</div>
  `;
};

displaySmallNews3();

const displaySmallNews4 = async() => {
  const news = await fetchNews();
  smallNews4.innerHTML = `
  <div class="card">
  <img id="smallNews4Img" src="${news.articles[4].urlToImage}" class="card-img-top" alt="...">
  <div class="card-body">
    <h5 class="card-title">${news.articles[4].title}</h5>
    <a href="${news.articles[4].url}" class="btnLink">Read more</a>
  </div>
</div>
  `;
};

displaySmallNews4();

const displaySmallNews5 = async() => {
  const news = await fetchNews();
  smallNews5.innerHTML = `
  <div class="card">
  <img id="smallNews5Img" src="${news.articles[5].urlToImage}" class="card-img-top" alt="...">
  <div class="card-body">
    <h5 class="card-title">${news.articles[5].title}</h5>
    <a onclick="userArticles" href="${news.articles[5].url}" class="btnLink">Read more</a>
  </div>
</div>
  `;
};

displaySmallNews5();

const displaySmallNews6 = async() => {
  const news = await fetchNews();
  smallNews6.innerHTML = `
  <div class="card">
  <img id="smallNews6Img" src="${news.articles[6].urlToImage}" class="card-img-top" alt="...">
  <div class="card-body">
    <h5 class="card-title">${news.articles[6].title}</h5>
    <a onclick="userArticles" href="${news.articles[6].url}" class="btnLink">Read more</a>
  </div>
</div>
  `;
};

displaySmallNews6();



// track when the user clicks on btnLink in local storage

const userArticles = () => {
  let userArticles = localStorage.getItem("userArticles");
  if (userArticles == null) {
    userArticlesObj = [];
  } else {
    userArticlesObj = JSON.parse(userArticles);
  }
  userArticlesObj.push("userArticles");
  localStorage.setItem("userArticles", JSON.stringify(userArticlesObj));
}

userArticles();
body {
  height: 100vh;
}

#outerContainer {
  display: flex;
  width: auto;
}

#leftside {
  display: flex;
  height: auto;
  width: 10%;
  background-color: #373b53;
  flex-direction: column;
}

#heart {
  height: 20px;
  background-color: beige;
  cursor: pointer;
  margin-left: 30px;
  background-image: url(https://cdn-icons-png.flaticon.com/512/105/105220.png);
  background-size: 20px;
  background-repeat: no-repeat;
  background-position: center;
  margin-top: 50px;
  border-radius: 5px;
}

#house {
  height: 20px;
  background-color: beige;
  cursor: pointer;
  margin-top: 5px;
  margin-left: 30px;
  background-image: url(https://cdn4.iconfinder.com/data/icons/pictype-free-vector-icons/16/home-512.png);
  background-size: 20px;
  background-repeat: no-repeat;
  background-position: center;
  border-radius: 5px;
}

#top {
  display: flex;
  height: 40px;
  width: 100%;
  justify-content: flex-start;
  background: linear-gradient(to right, #373b53 0% 9.09%, white 9.09% 90%);
}

#input {
  border-radius: 15px;
  padding-left: 10%;
  width: 350px;
  margin-left: 15%;
  border: auto;
  background-image: url(https://cdn2.iconfinder.com/data/icons/ios-7-icons/50/search-512.png);
  background-repeat: no-repeat;
  background-position: left;
  padding-left: 15px;
  background-size: 20px;
}

#login {
  display: flex;
  justify-content: flex-end;
  margin-left: auto;
}

#profile {
  margin-right: 5%;
  margin-top: 5px;
  border-radius: 15px;
  border: auto;
  background-color: #373b53;
  color: white;
  cursor: pointer;
}

#userName {
  margin-right: 10px;
  margin-top: 20px;
  font-size: 15px;
}

#container {
  display: flex;
  background-color: rgb(206, 201, 201);
  flex-direction: row;
  width: 100%;
  height: auto;
}

#nyheder {
  display: flex;
  flex-direction: column;
  padding: 40px;
  width: auto;
  font-size: large;
  font-weight: bold;
}

#bigNews {
  display: flex;
  width: 600px;
  height: 200px;
  background-color: white;
  border-radius: 5%;
}

#smallNewsContainer {
  display: flex;
  flex-wrap: wrap;
}

#smallNews1 {
  display: flex;
  width: 190px;
  height: 150px;
  background-color: white;
  border-radius: 5%;
  margin-top: 2%;
  margin-bottom: 1%;
  margin-right: 2%;
}

#smallNews2 {
  display: flex;
  width: 190px;
  height: 150px;
  background-color: white;
  border-radius: 5%;
  margin-top: 2%;
  margin-bottom: 1%;
  margin-right: 2%;
}

#smallNews3 {
  display: flex;
  width: 190px;
  height: 150px;
  background-color: white;
  border-radius: 5%;
  margin-top: 2%;
  margin-bottom: 1%;
  margin-right: 2%;
}

#smallNews4 {
  display: flex;
  width: 190px;
  height: 150px;
  background-color: white;
  border-radius: 5%;
  margin-top: 1%;
  margin-bottom: 2%;
  margin-right: 2%;
}

#smallNews5 {
  display: flex;
  width: 190px;
  height: 150px;
  background-color: white;
  border-radius: 5%;
  margin-top: 1%;
  margin-bottom: 2%;
  margin-right: 2%;
}

#smallNews6 {
  display: flex;
  width: 190px;
  height: 150px;
  background-color: white;
  border-radius: 5%;
  margin-top: 1%;
  margin-bottom: 2%;
  margin-right: 2%;
}

#readMoreBtn1 {
  display: flex;
  width: 90px;
  height: 30px;
  background-color: white;
  border-radius: 10px;
  margin-top: 2%;
  margin-bottom: 2%;
  margin-right: 2%;
  justify-content: center;
  align-items: center;
  cursor: pointer;
  color: black;
  background-position: bottom left;
  margin-top: auto;
  margin-left: auto;
}

#readMoreBtn2 {
  display: flex;
  width: 90px;
  height: 30px;
  background-color: white;
  border-radius: 10px;
  margin-top: 2%;
  margin-bottom: 2%;
  margin-right: 2%;
  justify-content: center;
  align-items: center;
  color: black;
  background-position: bottom left;
  margin-top: auto;
  margin-left: auto;
}

#readMoreBtn3 {
  display: flex;
  width: 90px;
  height: 30px;
  background-color: white;
  border-radius: 10px;
  margin-top: 2%;
  margin-bottom: 2%;
  margin-right: 2%;
  justify-content: center;
  align-items: center;
  color: black;
  background-position: bottom left;
  margin-top: auto;
  margin-left: auto;
}

#readMoreBtn4 {
  display: flex;
  width: 90px;
  height: 30px;
  background-color: white;
  border-radius: 10px;
  margin-top: 2%;
  margin-bottom: 2%;
  margin-right: 2%;
  justify-content: center;
  align-items: center;
  color: black;
  background-position: bottom left;
  margin-top: auto;
  margin-left: auto;
}

#readMoreBtn5 {
  display: flex;
  width: 90px;
  height: 30px;
  background-color: white;
  border-radius: 10px;
  margin-top: 2%;
  margin-bottom: 2%;
  margin-right: 2%;
  justify-content: center;
  align-items: center;
  color: black;
  background-position: bottom left;
  margin-top: auto;
  margin-left: auto;
}

#readMoreBtn6 {
  display: flex;
  width: 90px;
  height: 30px;
  background-color: white;
  border-radius: 10px;
  margin-top: 2%;
  margin-bottom: 2%;
  margin-right: 2%;
  justify-content: center;
  align-items: center;
  color: black;
  background-position: bottom left;
  margin-top: auto;
  margin-left: auto;
}

#tidogvejr {
  display: flex;
  flex-direction: column;
  padding: 40px;
  width: auto;
}

#current-time {
  display: flex;
  width: auto;
  height: 200px;
  background-color: white;
  border-radius: 5%;
  font-size: 50px;
  justify-content: center;
  align-items: center;
}

#sunriseSunset {
  display: flex;
  flex-direction: row;
  width: auto;
  height: 100px;
  background-color: white;
  border-radius: 5%;
  margin-bottom: 10px;
  flex-direction: column;
}

.vejrprognose {
  display: flex;
  width: auto;
  height: auto;
  background-color: red;
  border-radius: 5%;
  margin-top: 20px;
}

#solopgang {
  font-size: large;
  width: 50%;
}

#sunrisePNG {
  display: flex;
  flex-direction: row;
  width: 35px;
  height: 30px;
  background-image: url(https://p.kindpng.com/picc/s/77-775474_its-a-sun-peaking-halfway-up-over-the.png);
  background-size: cover;
}

#sunset {
  font-size: large;
  width: 50%;
}

#sunsetPNG {
  display: flex;
  width: 35px;
  height: 35px;
  background-image: url(https://cdn-icons-png.flaticon.com/512/287/287668.png);
  background-size: cover;
}

#logOutImg {
  width: 50px;
  height: 50px;
  background-image: url("https://www.pngfind.com/pngs/m/339-3396821_png-file-svg-download-icon-logout-transparent-png.png");
  background-size: 20px;
  background-position: center;
  border-color: white;
  cursor: pointer;
  background-repeat: no-repeat;
}

#bigNewsImg {
  display: flex;
  width: 100%;
  height: 70%;
  background-color: white;
  border-radius: 5%;
  background-size: cover;
  background-position: center;
}

#smallNews1Img {
  width: 80%;
  height: 40%;
  background-color: white;
  border-radius: 5%;
  background-size: cover;
  background-position: center;
}

#smallNews2Img {
  width: 80%;
  height: 40%;
  background-color: white;
  border-radius: 5%;
  background-size: cover;
  background-position: center;
}

#smallNews3Img {
  width: 80%;
  height: 40%;
  background-color: white;
  border-radius: 5%;
  background-size: cover;
  background-position: center;
}

#smallNews4Img {
  width: 80%;
  height: 40%;
  background-color: white;
  border-radius: 5%;
  background-size: cover;
  background-position: center;
}

#smallNews5Img {
  width: 80%;
  height: 40%;
  background-color: white;
  border-radius: 5%;
  background-size: cover;
  background-position: center;
}

#smallNews6Img {
  width: 80%;
  height: 40%;
  background-color: white;
  border-radius: 5%;
  background-size: cover;
  background-position: center;
}

.card {
  display: flex;
  width: 100%;
  height: 100%;
  background-color: white;
  border-radius: 5%;
  background-size: cover;
  background-position: center;
  font-size: small;
  justify-content: flex-end;
}

.btnLink {
  display: flex;
  justify-content: flex-end;
  margin-right: 5%;
  margin-top: 0px;
}
<div id="top">
  <input type="text" placeholder="Search for news" id="input" />
  <div id="login">
    <div id="userName"></div>
    <button id="profile" onclick="goToProfile()">Go to profile</button>
    <button id="logOutImg" onclick="logOutClick()"></button>
  </div>
</div>
<div id="outerContainer">
  <div id="leftside">
    <div id="heart"></div>
    <div id="house"></div>
  </div>
  <div id="container">
    <div id="nyheder">
      Nyheder
      <div id="bigNews">
        <div id="bigNewsText"></div>
        <div id="bigNewsImage">
          <div id="bigNewsLink"></div>
        </div>
      </div>

      <div id="smallNewsContainer">
        <div id="smallNews1">
          <div id="smallNews1Img"></div>
          <div id="smallNews1Text"></div>
        </div>
        <div id="smallNews2">
          <div id="smallNews2Img"></div>
          <div id="smallNews2Text"></div>
        </div>
        <div id="smallNews3">
          <div id="smallNews3Img"></div>
          <div id="smallNews3Text"></div>
        </div>
        <div id="smallNews4">
          <div id="smallNews4Img"></div>
          <div id="smallNews4Text"></div>
        </div>
        <div id="smallNews5">
          <div id="smallNews5Img"></div>
          <div id="smallNews5Text"></div>
        </div>
        <div id="smallNews6">
          <div id="smallNews6Img"></div>
          <div id="smallNews6Text"></div>
        </div>
      </div>
    </div>
    <div id="tidogvejr">
      Tid
      <div id="current-time"></div>
      <h3>Vejr</h3>
      <div id="sunriseSunset">
        <div id="solopgang" class="solopgang"></div>
        <div id="sunrisePNG"></div>
        <div id="sunset" class="sunset"></div>
        <div id="sunsetPNG"></div>
      </div>
      <div id="vejrprognose" class="weatherWidget">Vejrprognose API</div>
    </div>
  </div>
</div>

This working snippet uses a variable named storedStuff as a proxy for local storage (as storage doesn't function here). It may point you in the right direction.

Your function has to know when an article has been clicked in order to add it to the store. The snippet achieves this with a click event listener that passes the ID of the relevant article to the function (you could pass any attribute, value or innerText or HTML).

The function receives the ID information as an argument and that is what is stored. A parsed version of the stored JSON can be processed by iterating the storage array, and its stored values used however you wish (in this case to display console messages of the accumulated storage)

 const articles=document.querySelectorAll(".article"); for (let i=0; i<articles.length; i++) { articles[i].addEventListener('click', e => userArticles(e.target.id)); } // next article; /* const userArticles = (id) => { console.clear(); console.log(id); } */ let storedStuff; const userArticles = (id) => { console.clear(); let userArticles = storedStuff; if (userArticles==null) { userArticlesObj = []; } else { userArticlesObj = JSON.parse(userArticles); } userArticlesObj.push(id); // store to local storage here; storedStuff=JSON.stringify(userArticlesObj); // console.log(userArticlesObj) userArticlesObj.forEach(element => {console.log(`article with id ${element} has been visited`); }) }
 .article { border: 1px solid black; height: 3em; width: 12em; background: yellow; margin: 3px; }
 <div class="article" id="art1">article 1</div> <div class="article" id="art2">article 2</div> <div class="article" id="art3">article 3</div> <div class="article" id="art4">article 4</div>

In order to apply this principle to your example, the function needs to receive an argument that is sent by a function call from an event listener attached to each article. Your revised function would be:

const userArticles = (id) => {
  let userArticles = localStorage.getItem("userArticles");
  if (userArticles == null) {
    userArticlesObj = [];
  } else {
    userArticlesObj = JSON.parse(userArticles);
  }
  userArticlesObj.push(id);
  localStorage.setItem("userArticles", JSON.stringify(userArticlesObj));
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM