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;
    }

})