Good idea. There's a few minor niggles, though:
Don't use
unsafeWindow
, this will break in Chrome and will not even work in Firefox+Greasemonkey if the effective@grant
changes.Avoid leading
*
wildcards in@includes
, if you can help it. This is a big performance hit.@match
limits the wildcard scope and performs much better and reports the sites/security correctly on Chrome. This gets all current SE sites:// @match *://*.askubuntu.com/questions/* // @match *://*.onstartups.com/questions/* // @match *://*.serverfault.com/questions/* // @match *://*.stackapps.com/questions/* // @match *://*.stackexchange.com/questions/* // @match *://*.stackoverflow.com/questions/* // @match *://*.superuser.com/questions/*
The regex
match
needs to be more robust, to account for all legal characters in the URL, and for anchors.Use injection so that the script will work on most userscript-capable browsers (Chrome, Firefox, Opera, Safari, etc.).
Mathoverflow.net is not an SE site! Use math.stackexchange.com for that. mathoverflow.net also does not appear to support the timeline view/page.
Here's a variant of the script I've been using (It works on Chrome and Firefox, and should work on most other userscript-capable browsers):
Easy install URL at GitHub for Greasemonkey, Tampermonkey, Scriptish, etc.
// ==UserScript==
// @name Stack Exchange: Add Timeline Button to questions
// @description Adds a "View Timeline" Button to Stack Exchange sites
// @namespace StackExchange
// @match *://*.askubuntu.com/questions/*
// @match *://*.onstartups.com/questions/*
// @match *://*.serverfault.com/questions/*
// @match *://*.stackapps.com/questions/*
// @match *://*.stackexchange.com/questions/*
// @match *://*.stackoverflow.com/questions/*
// @match *://*.superuser.com/questions/*
// ==/UserScript==
function addTimelineButton ($) {
var buttonText = "View Timeline";
var timelineLink = "#";
var postNum = 0;
var postMatch = location.pathname.match (/questions\/(\d+)\D/i);
if (postMatch && postMatch.length > 1) {
postNum = postMatch[1];
timelineLink = location.protocol + "//"
+ location.host
+ "/posts/"
+ postNum + "/timeline"
;
}
else {
buttonText = "Path error 1";
}
var targetNode = $(".favoritecount");
if (targetNode.length) {
targetNode.after ('<a href="' + timelineLink + '">' + buttonText + '</a>');
}
else if (
postNum
&& $("#content div.subheader > h1:contains('Page Not Found')").length == 0
) {
alert ("From Timeline script: Unexpected Page layout.");
}
}
withPages_jQuery (addTimelineButton);
function withPages_jQuery (NAMED_FunctionToRun) {
//--- Use named functions for clarity and debugging...
var funcText = NAMED_FunctionToRun.toString ();
var funcName = funcText.replace (/^function\s+(\w+)\s*\((.|\n|\r)+$/, "$1");
var script = document.createElement ("script");
script.textContent = funcText + "\n\n";
script.textContent += 'jQuery(document).ready( function () {' + funcName + '(jQuery);} );';
document.body.appendChild (script);
};