🏠 Home 

Pinboard - Sort Visible Links(modified)

A modified version of Pinboard - Sort Visible Links, compatible with Pinboard.in bookmarks with favicons

// ==UserScript==
// @name Pinboard - Sort Visible Links(modified)
// @namespace http://murklins.talkoncorners.net
// @description A modified version of Pinboard - Sort Visible Links, compatible with Pinboard.in bookmarks with favicons
// @version 0.1
// @include http://pinboard.in/*
// @include http://www.pinboard.in/*
// @include https://pinboard.in/*
// @include https://www.pinboard.in/*
// @exclude http://pinboard.in/popular/*
// @exclude http://www.pinboard.in/popular/*
// @exclude https://pinboard.in/popular/*
// @exclude https://www.pinboard.in/popular/*
// @exclude http://pinboard.in/add*
// @exclude http://www.pinboard.in/add*
// @exclude https://pinboard.in/add*
// @exclude https://www.pinboard.in/add*
// @exclude http://pinboard.in/url:*
// @exclude http://www.pinboard.in/url:*
// @exclude https://pinboard.in/url:*
// @exclude https://www.pinboard.in/url:*
// ==/UserScript==
var main_node;
var postArr = [];
// if can't find pinboard element, exit
main_node = document.getElementById("pinboard");
if (!main_node) {
return;
}
// gather up all the bookmarks and fill the postArr
var bookmarks = fillPostArr();
if (bookmarks.snapshotLength === 0) {
// no bookmarks, so exit
return;
}
// add the sorting options div just above the first bookmark
var firstBookmark =  getBookmarkContainer(bookmarks.snapshotItem(0));
var sortVisDiv = document.createElement("div");
sortVisDiv.id = "gm_sortVisDiv";
firstBookmark.parentNode.insertBefore(sortVisDiv, firstBookmark);
// add the sort links
sortVisDiv.appendChild(document.createTextNode("Visible Sorted By ("));
createSortLink("title", postSortTitle, sortVisDiv);
sortVisDiv.appendChild(document.createTextNode(" | "));
createSortLink("url", postSortUrl, sortVisDiv);
sortVisDiv.appendChild(document.createTextNode(" | "));
createSortLink("pop", postSortPop, sortVisDiv);
sortVisDiv.appendChild(document.createTextNode(" | "));
createSortLink("default", postSortDefault, sortVisDiv);
sortVisDiv.appendChild(document.createTextNode(")"));
function fillPostArr() {
// clear array
postArr = [];
// get all the bookmarks
var bookmarks = document.evaluate("//div[contains(@class, 'bookmark ')]", main_node, null,
XPathR###lt.ORDERED_NODE_SNAPSHOT_TYPE, null);
var p;
for (var i = 0; i < bookmarks.snapshotLength; i++) {
var b = bookmarks.snapshotItem(i);
// get the number of people who saved the link
var people = document.evaluate("./div[contains(@class, 'display')]/a[contains(@class, 'url_link')]",
b, null, XPathR###lt.ORDERED_NODE_SNAPSHOT_TYPE, null);
var popularity = 0;
if (people.snapshotLength > 0) {
popularity = people.snapshotItem(0).innerHTML;
// format is "3 others" so just take the piece before the space
popularity = popularity.split(" ")[0];
}
// get the link and title
var postLink = document.evaluate("./div[contains(@class, 'display')]/a[contains(@class, 'bookmark_title')]",
b, null,XPathR###lt.ORDERED_NODE_SNAPSHOT_TYPE, null);
var t = "";
var l = "";
if (postLink.snapshotLength > 0) {
//Using along with Pinboard.in bookmarks with favicons (http://userscripts.org/scripts/show/94151)
//would cause sorting by title unavailable.
//Use text rather than innerHTML to get bookmark title can fix this.
//t = postLink.snapshotItem(0).innerHTML;
t = postLink.snapshotItem(0).text;
l = postLink.snapshotItem(0).getAttribute("href");
}
p = getBookmarkContainer(b);
// add the post to the array
postArr[postArr.length] = new PopPost(p, i, t, l, popularity);
}
return bookmarks;
}
function createSortLink(linkText, sortFunction, parentDiv) {
var a = document.createElement("a");
a.innerHTML = linkText;
a.className = "gm_sortVisLink";
a.href = "";
if (linkText == "default") {
a.className = a.className + " gm_sortVisLinkOn";
}
parentDiv.appendChild(a);
a.addEventListener("click", function(event) {
event.stopPropagation();
event.preventDefault();
// get all the bookmarks
var bookmarks = document.evaluate("//div[contains(@class, 'bookmark ')]", main_node, null,
XPathR###lt.ORDERED_NODE_SNAPSHOT_TYPE, null);
if (bookmarks.snapshotLength != postArr.length) {
// woops! so the postArr no longer has the same number of posts in it as there are posts on the page
// usually this is because another GM script, like Autopagerize, has messed with the page since
// we first grabbed all the posts. No problem, though, just re-fill the array.
// But first, before we refill the post array, make sure we restore the default sort order to the
// posts that may have already benn sorted one or more times, otherwise our new default order
// will be... not very default.
doSort(bookmarks, postArr.length, postSortDefault, "default");
fillPostArr();
}
// do the sort!
doSort(bookmarks, bookmarks.snapshotLength, sortFunction, this.innerHTML);
}, false);
return a;
}
function doSort(bookmarks, numRemove, sortFunction, currentSortText) {
// first remove all the posts from the DOM
var list;
var next;
for (var i = 0; i < numRemove; i++) {
var post = getBookmarkContainer(bookmarks.snapshotItem(i));
list = post.parentNode;
if (post.nextSibling) {
next = post.nextSibling;
}
list.removeChild(post);
}
// why are autopagerize links getting added to the top of the list if a sort is triggered before the pagerize?
// WHYYYYYYYYYYYYYYYYYYY. I don't really want to read the autopagerize code, so let's assume that the next page's
// posts are pre-loaded into the bookmark list and we need to append our sorted links BEFORE them.
//var remainingChild;
//if (list.firstChild) {
//remainingChild = list.firstChild;
//}
// sort the post array using the passed in sort function and then add the posts in their new order as list children
postArr.sort(sortFunction);
/*
for (var i = 0; i < postArr.length; i++) {
//if (remainingChild) {
//list.insertBefore(postArr[i].post, remainingChild);
//}
if (next) {
list.insertBefore(postArr[i].post, next);
}
else {
list.appendChild(postArr[i].post);
}
}
*/
// insert the nodes back by finding the next sibling of the sort option div
// if no sibling exists, we'll just append to the sort option div's parent
var parent = sortVisDiv.parentNode;
var insertBefore = null;
if (sortVisDiv.nextSibling) {
insertBefore = sortVisDiv.nextSibling;
}
// add the posts in their new order
for (var i = 0; i < postArr.length; i++) {
if (insertBefore) {
parent.insertBefore(postArr[i].post, insertBefore);
}
else {
parent.appendChild(postArr[i].post);
}
}
// for compatibility with my own Pinboard - Date Lines GM script,
// hide date lines on all but default sort order
var dateLineDivs = document.evaluate("//div[contains(@class, 'gm_datelines_newdate')]", main_node, null,
XPathR###lt.ORDERED_NODE_SNAPSHOT_TYPE,
null);
for (var i = 0; i < dateLineDivs.snapshotLength; i++) {
if (currentSortText == "default") {
dateLineDivs.snapshotItem(i).style.display = "block";
}
else {
dateLineDivs.snapshotItem(i).style.display = "none";
}
}
// highlight this link to indicate that it is on, deselect the other links
var sortLinks = document.evaluate("//a[contains(@class, 'gm_sortVisLink')]", main_node, null,
XPathR###lt.ORDERED_NODE_SNAPSHOT_TYPE,
null);
for (var i = 0; i < sortLinks.snapshotLength; i++) {
sortLinks.snapshotItem(i).className = "gm_sortVisLink";
if (sortLinks.snapshotItem(i).innerHTML == currentSortText) {
sortLinks.snapshotItem(i).className = "gm_sortVisLinkOn";
}
}
}
function PopPost(p, d, t, h, pop) {
this.post = p;
this.defaultOrder = d;
this.title = t;
this.link = h;
this.pop = pop;
}
function postSortDefault(a, b) {
return a.defaultOrder - b.defaultOrder;
}
function postSortTitle(a, b) {
var x = a.title.toLowerCase();
var y = b.title.toLowerCase();
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
}
function postSortUrl(a, b) {
var x = a.link;
var y = b.link;
return ((x < y) ? -1 : ((x > y) ? 1 : 0));
}
function postSortPop(a, b) {
return b.pop - a.pop;
}
// bookmarks you can edit have an extra containing div, so look for it
// and use it as the main post node
function getBookmarkContainer(node) {
var container = node;
var parent = node.parentNode;
if (parent.id != "bookmarks") {
var node = parent.firstChild;
while (node) {
if (node.className == "edit_checkbox") {
container = parent;
break;
}
node = node.nextSibling;
}
}
return container;
}
GM_addStyle(
'div#gm_sortVisDiv { margin: 7px 0; }' +
'div#gm_sortVisDiv a.gm_sortVisLinkOn { color: blue; }' +
'div#gm_sortVisDiv a { color: #999; }'
);