js thoughts widget (take 2)
And after all of that, I decided it might be nice to have my thoughts widget run off a Google Sheet, in a manner inspired by Ayano's comments widget (which is what I use for my guestbook).
Upside: now, I can update it easily from anywhere I have internet service, rather than only from my computer. Also, I don't have to rebuild my site every time I add a new entry.
Downside: load time is now noticeably slower, and I'm wondering how much worse it'll get once I have more than a handful of entries. I finished fifteen minutes ago and I'm honestly debating switching back already.
Regardless, I thought I'd share the code for this too, in case anyone found it useful. The only real difference from the instructions I gave Thursday in terms of set up is that you'll need the URL to a (public) Google Sheet. It also makes the Python script unnecessary.
javascript
const indexUrl = `/pages/thoughts.html` // the location of your full index
const recentCt = 3; // how many thoughts to show in "recent thoughts"
const sheetUrl = `{{URL}}`; // the url of your google spreadsheet
let thoughts = [];
function formatThought(thought) {
var timestamp = new Date(thought.time);
let year = timestamp.getFullYear();
let month = months[timestamp.getMonth()];
let day = timestamp.getDate();
let min = timestamp.getMinutes();
let hour = timestamp.getHours();
let time = ``;
if (hour > 12) {
hour = hour - 12;
time = `${String(hour)}:${min} PM`
} else if (hour == 0) {
hour = 12;
time = `${String(hour)}:${min} AM`
} else if (hour == 12) {
time = `${String(hour)}:${min} PM`
} else {
time = `${String(hour)}:${min} AM`
}
let date = `${time} • ${month} ${day}, ${year}`
let html = `<div class="thought">
<div class="body">${thought.text}</div>
<div class="date">${date}</div>
</div>`;
return html;
}
const tElements = {
index: {id: "thoughtsIndex", html: ""},
recent: {id: "recentThoughts", html: ""}
};
let fetchData = new Promise(function (resolve, reject) {
fetch(sheetUrl).then(response => {
if (!response.ok) {reject('Could not find Google Sheet with that URL')} // Checking for a 404
else {
response.text().then(data => {
if (!data) {reject('Invalid data pulled from sheet')}
resolve(data);
})
}
})
})
fetchData.then(result => {
const json = JSON.parse(result.split('\n')[1].replace(/google.visualization.Query.setResponse(|);/g, ''));
if (json.table.parsedNumHeaders > 0) {
for (let r in json.table.rows) {
thoughts.push({time: json.table.rows[r].c[0].f, text: json.table.rows[r].c[1].v})
}
}
let allMonths = [];
for (i of thoughts) {
var timestamp = new Date(i.time);
let year = timestamp.getFullYear();
let month = months[timestamp.getMonth()];
i.month = `${month} ${year}`;
allMonths.push(`${month} ${year}`);
}
let uniqMonth = [...new Set(allMonths)];
for (let month of uniqMonth) {
tElements.index.html += `<h2 id="${month.replace(/\s/g, "_")}">${month}</h2>`
for (let i of thoughts) {
if (i.month = month) tElements.index.html += formatThought(i);
}
}
if (thoughts.length < recentCt) {
for (let i in thoughts) {
tElements.recent.html += formatThought(thoughts[i]);
}
} else {
for (let i = 0; i < recentCt; i++) {
tElements.recent.html += formatThought(thoughts[i]);
}
tElements.recent.html += `<a href="${indexUrl}"><p>more thoughts →</p></a>`
}
for (let i in tElements) {
let selection = document.getElementById(tElements[i].id);
if (selection) selection.innerHTML = tElements[i].html;
}
})