Tutorialul a fost postat original de mine, pe forumul de suport englez:https://help.forumotion.com/t160730-latest-publications-widget.
Widget-ul afiseaza ultimele publicatii(de pe pagina /publi, atunci cand este activata).
Demo:primul widget din partea dreapta, sus a forumului meu de teste, https://otesting.forumgratuit.ro/
Screenshot:
https://i.servimg.com/u/f33/19/98/30/15/screen40.png
Cod widget:
Obiectele lang si config pot fi modificate, precum si css-ul din partea de sus a codului. Enjoy!
Widget-ul afiseaza ultimele publicatii(de pe pagina /publi, atunci cand este activata).
Demo:primul widget din partea dreapta, sus a forumului meu de teste, https://otesting.forumgratuit.ro/
Screenshot:
https://i.servimg.com/u/f33/19/98/30/15/screen40.png
Cod widget:
Cod:
<div class="loader"><span></span></div>
<div class="publications"></div>
<div class="reload-publications"><span style="display:none"></span></div>
<div class="error"></div>
<style>
.publi:nth-child(2n) {
background: white;
}
.publi {
margin: -3px;
background: white;
border-bottom: 6px solid #2f2f2f;
}
.publi:nth-last-child(1) {
border-bottom: none;
}
.publi-top {
padding: 5px;
}
.publi-title {
font-size: 18px;
}
.publi-views {
background: #00689A;
color: white;
border-radius: 2px;
padding: 3px;
float: right;
display: inline-table;
}
.publi-info>span {
display: table;
padding: 5px;
padding-top: 0;
}
.reload-publications {
display: flex;
justify-content: center;
}
.reload-publications>span {
background: white;
padding: 3px;
margin: 5px;
margin-top: 10px;
cursor: pointer;
}
.reload-publications>span:hover {
box-shadow: 0 3px 6px rgba(0, 0, 0, 0.16);
}
.loader>span {
width: 10px;
height: 10px;
display: table;
border-radius: 100%;
border: 2px solid white;
border-left-color: #2f2f2f;
border-right-color: #2f2f2f;
animation: 1s infinite linear loader;
}
@keyframes loader {
0% {
transform: rotate(0deg) rotateX(20deg);
}
100% {
transform: rotate(180deg) rotateY(20deg);
}
}
.loader {
background: white;
margin: -3px;
margin-bottom: 0px;
display: flex;
justify-content: center;
padding: 5px;
}
</style>
<script>
let q = (e) => {
return document.querySelector(e);
};
let error = q(".error"),
publications = q(".publications");
let loader = q(".loader"),
refresh = q(".reload-publications>span");
let lang = {
error: "Eroare de incarcare a publicatiilor. Verifica conexiunea la internet, apoi apasa butonul 'Reincarca'",
reload: "Reincarca",
noLocalStorage: "Browserul tau nu suporta API-ul localStorage, sau API-ul JSON. Te rugam sa actualizezi browserul"
}
let config = {
number: 5, /* numarul de topicuri */
alwaysRefresh: false,
/* true:reincarca mereu publicatiile; false:nu reincarca mereu*/
expiration: 60 * 1000,
/* pentru cate milisecunde sunt salvate publicatiile */
}
let loading = 0;
let now = (new Date()).getTime();
let run = () => {
refresh.innerHTML = lang.reload;
refresh.addEventListener("click", () => {
if (loading) return;
loading = 1;
now = (new Date()).getTime();
publications.innerHTML = "";
error.innerHTML = "";
get();
})
if (!localStorage) {
error.innerHTML = lang.noLocalStorage;
return false;
}
/* Check if there's any saved data */
let number = localStorage.publiNumber;
if (number) {
if (number != config.number) {
/* if the number of notifications has changed, invalidate the cache */
localStorage.removeItem("publi")
localStorage.removeItem("publiTime");
localStorage.publiNumber = config.number;
}
} else localStorage.publiNumber = config.number;
let data = localStorage.publi,
time = localStorage.publiTime;
if ((data && now - parseInt(time) < config.expiration) && !config.alwaysRefresh) {
render(JSON.parse(data));
refresh.style.display = "table";
loader.style.display = "none";
} else {
get();
}
}
let save = (data) => {
localStorage.publi = JSON.stringify(data);
localStorage.publiTime = now;
}
let render = (data) => {
let html = "";
data.forEach(publi => {
html += "<div class='publi'><div class='publi-top'><span class='publi-title'>" +
"<a href='" + publi.link + "'>" + publi.title + "</a></span><span class='publi-views'>" + publi.views + "</span>" +
"</div><div class='publi-info'><span class='publi-author'>by " + publi.author + "</span>" +
"<span class='publi-date'>" + publi.date + "</span></div></div>"
})
publications.innerHTML = html;
}
let get = (callback) => {
/* fetch the latest config.number publications */
refresh.style.display = "none";
loader.style.display = "flex";
loading = 1;
fetch("/publi", {
credentials: "include"
}).then(response => {
return response.text();
})
.then(text => {
let dom = (new DOMParser()).parseFromString(text, "text/html");
let titles = Array.from(dom.querySelectorAll(".title")).slice(0, config.number);
let info = Array.from(dom.querySelectorAll(".inline")).slice(0, config.number);
let data = [];
for (let i = 0, len = titles.length; i < len; i++) {
let extra = info[i].children.length == 4;
/* for the first 3 publications,
the 'by' and the author's name are separated; this is a fix for that */
data.push({
title: titles[i].innerHTML,
link: titles[i].parentElement.getAttribute("href"),
author: info[i].children[0 + extra].children[0].innerHTML.replace("by ", ""),
date: info[i].children[1 + extra].children[0].innerHTML,
views: info[i].children[2 + extra].children[0].innerHTML,
})
}
save(data);
render(data);
callback && callback();
loading = 0;
refresh.style.display = "table";
loader.style.display = "none";
})
}
run();
</script>
Obiectele lang si config pot fi modificate, precum si css-ul din partea de sus a codului. Enjoy!