OSM diaries TOC

Adds a table of contents to the OpenStreetMap diaries page and highlights new posts and comments.

K instalaci tototo skriptu si budete muset nainstalovat rozšíření jako Tampermonkey, Greasemonkey nebo Violentmonkey.

You will need to install an extension such as Tampermonkey to install this script.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Violentmonkey.

K instalaci tohoto skriptu si budete muset nainstalovat rozšíření jako Tampermonkey nebo Userscripts.

You will need to install an extension such as Tampermonkey to install this script.

K instalaci tohoto skriptu si budete muset nainstalovat manažer uživatelských skriptů.

(Už mám manažer uživatelských skriptů, nechte mě ho nainstalovat!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(Už mám manažer uživatelských stylů, nechte mě ho nainstalovat!)

// ==UserScript==
// @name        OSM diaries TOC
// @namespace   https://github.com/marcows
// @description Adds a table of contents to the OpenStreetMap diaries page and highlights new posts and comments.
// @description:de Fügt ein Inhaltsverzeichnis zur OpenStreetMap Benutzer-Blogs-Seite hinzu und hebt neue Beiträge und Kommentare hervor.
// @include     *://www.openstreetmap.org/diary*
// @include     /^https?://www\.openstreetmap\.org/user/.*/diary[^/]*$/
// @version     3.0.1
// @license     WTFPL
// @icon        http://www.openstreetmap.org/assets/osm_logo.png
// @supportURL  https://github.com/marcows/osm-diaries-toc
// @compatible  firefox
// @compatible  chrome
// @compatible  opera
// @require     https://greasemonkey.github.io/gm4-polyfill/gm4-polyfill.js
// @grant       GM.getValue
// @grant       GM_getValue
// @grant       GM.setValue
// @grant       GM_setValue
// ==/UserScript==

(async function() {

var contentBox = document.querySelector(".content-body .content-inner");

var diaryPosts = document.querySelectorAll(".diary_post");

var articleLinks = document.querySelectorAll(".diary_post .mb-3 h2 > a");
var commentLinks = document.querySelectorAll(".diary_post .secondary-actions a[href$='#comments']");

var toc = document.createElement("table");
var olderNewer = document.createElement("span");

/* Create table of contents. */
for (var i = 0; i < articleLinks.length && i < commentLinks.length; i++) {
	var articleLink = articleLinks[i].cloneNode(true);
	var commentLink = commentLinks[i].cloneNode(true);

	var tablerow = document.createElement("tr");
	var cell, link;

	// Anchor name of the (original) article if not existing yet
	if (!articleLinks[i].name)
		articleLinks[i].name = "article" + i;

	/* Column 1: anchor link for scrolling down to article */
	link = document.createElement("a");
	link.innerHTML = "&nbsp;&dArr;&nbsp;";
	link.href = "#" + articleLinks[i].name;

	cell = document.createElement("td");
	cell.appendChild(link);
	tablerow.appendChild(cell);

	/* Column 2: link to article in own page */
	cell = document.createElement("td");
	cell.appendChild(articleLink);
	tablerow.appendChild(cell);

	/* Column 3: link to article comments in own page */
	cell = document.createElement("td");
	cell.style.whiteSpace = "nowrap";
	cell.appendChild(commentLink);
	tablerow.appendChild(cell);

	/* Highlighted if changed since last visit (new comments or entire new post) */

	// Diary entry ID:
	var key = commentLink.href.match(/\/([0-9]+)#/)[1];

	// Language dependent text, e.g. "No comments", "1 comment", "2 comments" etc.:
	var newVal = commentLink.textContent;
	var oldVal = await GM.getValue(key);

	if (newVal !== oldVal) {
		// New comment (or new post)
		commentLink.style.color = "red";
		// Add the previous content as link title
		commentLink.title = oldVal ? oldVal : "-";

		if (!oldVal) {
			// New post
			articleLink.style.color = "red";
		}

		GM.setValue(key, newVal);
	}

	toc.appendChild(tablerow);
}

contentBox.insertBefore(toc, diaryPosts[0]);

/* Duplicate the "older/newer entries" links from bottom of page to after the TOC. */
if (diaryPosts.length > 0) {
	var olderNewerNode = diaryPosts[diaryPosts.length - 1];

	while (olderNewerNode.nextSibling) {
		olderNewerNode = olderNewerNode.nextSibling;
		olderNewer.appendChild(olderNewerNode.cloneNode(true));
	}

	contentBox.insertBefore(olderNewer, diaryPosts[0]);
}

})();