7
\$\begingroup\$

The following script is meant to be a user script, but it should work on the console. It takes the id of the question and adds the corresponding /posts/id/timeline link to the post-menu element, just besides others. It's meant to not have problem with other scripts. The same as above for the answers, just that in this case it should loop through all the answers and add its corresponding timeline link.

let question = document.getElementById("question");
let qid = question.dataset.questionid;
if (qid) {
    let span = document.createElement("span");
    let alink = document.createElement("a");
    alink.class = "userscript-timeline";
    alink.href = "/posts/" + Number(qid) + "/timeline";
    alink.title = "timeline for this question";
    alink.textContent = "timeline";
    span.appendChild(alink);
    question.getElementsByClassName("post-menu")[0].appendChild(span);
}
let answers = document.getElementsByClassName("answer");
if (answers) {
    for (let i = 0; i < answers.length; i += 1) {
        let aid = answers[i].dataset.answerid;
        let answer = document.getElementById("answer-" + aid);
        let span = document.createElement("span");
        let alink = document.createElement("a");
        alink.class = "userscript-timeline";
        alink.href = "/posts/" + Number(aid) + "/timeline";
        alink.title = "timeline for this answer";
        alink.textContent = "timeline";
        span.appendChild(alink);
        answer.getElementsByClassName("post-menu")[0].appendChild(span);
    }
}

I'm not sure if it's convenient to abstract the logic that create and adds the link, as I'm afraid it could introduce needless complexity. My naming sense could be better.

\$\endgroup\$
  • \$\begingroup\$ Huh, I didn't know the timeline thing existed - pretty neat! \$\endgroup\$ – Raystafarian Aug 15 '16 at 17:47
2
\$\begingroup\$

Direct per-attribute DOM building belongs to the '00s but, since you're using ES2015's let, let's use multiline template strings and make the final result of our code instantly readable:

let question = document.getElementById("question");
if (question) {
    question.querySelector(".post-menu").insertAdjacentHTML('beforeend', `
        <span>
            <a class="userscript-timeline" title="timeline for this question"
                href="/posts/${question.dataset.questionid}/timeline">timeline</a>
        </span>
    `);
}

for (let answer of document.getElementsByClassName("answer")) {
    answer.querySelector(".post-menu").insertAdjacentHTML('beforeend', `
        <span>
            <a class="userscript-timeline" title="timeline for this answer"
                href="/posts/${answer.dataset.answerid}/timeline">timeline</a>
        </span>
    `);
}

Notes:

  • .getElementsByClassName("abc")[0] ———> .querySelector(".abc")
    Of course the former is faster but it doesn't matter in our case.
  • getElementsByClassName can never be null, it's a live HTMLCollection, so we can directly use it in a loop.
  • insertAdjacentHTML speed is about the same or faster than manual node building.
\$\endgroup\$
1
\$\begingroup\$

I really like wOxxOm's answer I would just add a function to reduce code duplication.

let link = function(element, id, title) {
    element.querySelector(".post-menu").insertAdjacentHTML('beforeend', `
        <span>
            <a class="userscript-timeline" title="timeline for this ${title}"
                href="/posts/${id}/timeline">timeline</a>
        </span>
    `);
};

let question = document.getElementById("question");

if (question) {
    link(question, question.dataset.questionid, "question");
}

for (let answer of document.getElementsByClassName("answer")) {
    link(answer, answer.dataset.answerid, "answer");
}
\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.