About
parkrun Launch Returnees lists finishers who were at both the location’s launch event (event #1) and the results page you are viewing (e.g. Cruickshank Park results).
Where it works
It runs on dated single-event results URLs. It does not run on latestresults pages or on the launch results page itself.
What you see
A scrollable list of people who appear in both the launch field and the current results, with links to their parkrunner profiles.
Privacy and data
The script fetches the public launch results page in your browser. Launch participant details are cached in browser local storage for 24 hours (keyed per page URL) so repeat visits avoid refetching immediately. Nothing is sent to the author or any third party.
Version 1.2.2 Updated
Screenshot
Install
Recommended: userscript. Bookmarklet works where a userscript manager isn’t available.
Userscript (recommended)
Install parkrun Launch Returnees
First time? Userscript basics and installation steps
What is a userscript?
A userscript is a small piece of JavaScript that runs in your browser and enhances specific websites. These scripts work with parkrun event pages, parkrunner profile pages, and results pages, and can be used with any userscript manager including Userscripts, Tampermonkey, Violentmonkey, or any compatible browser extension.
Installation steps
-
Install a userscript manager for your browser:
- Desktop: Userscripts (Safari), Tampermonkey (Chrome, Firefox, Edge, Opera), or Violentmonkey (Orion)
- iOS: Userscripts (Safari) or Violentmonkey (Orion)
- Android: Install Kiwi Browser, then install Tampermonkey or Violentmonkey from the Chrome Web Store.
- Click the Install button above for this script.
- Click “Install” when prompted by your userscript manager.
Bookmarklet
A bookmarklet is a bookmark whose URL is JavaScript. Use it on browsers that support bookmarks but not userscript managers.
Drag this link to your bookmarks bar:
parkrun Launch Returnees bookmarklet
Mobile bookmarklet setup and full code
Mobile bookmarklet
On mobile browsers that let you edit bookmark URLs:
- Copy the JavaScript code below to your clipboard.
- Create a new bookmark for any page.
- Edit the bookmark and replace its URL with the code you copied.
- Navigate to the relevant parkrun page.
- Select the bookmark to run the script.
javascript:function _toConsumableArray(e){return _arrayWithoutHoles(e)||_iterableToArray(e)||_unsupportedIterableToArray(e)||_nonIterableSpread()}function _nonIterableSpread(){throw new TypeError("Invalid attempt to spread non-iterable instance.\nIn order to be iterable, non-array objects must have a [Symbol.iterator]() method.")}function _unsupportedIterableToArray(e,r){var t;if(e)return"string"==typeof e?_arrayLikeToArray(e,r):"Map"===(t="Object"===(t={}.toString.call(e).slice(8,-1))&&e.constructor?e.constructor.name:t)||"Set"===t?Array.from(e):"Arguments"===t||/^(?:Ui|I)nt(?:8|16|32)(?:Clamped)?Array$/.test(t)?_arrayLikeToArray(e,r):void 0}function _iterableToArray(e){if("undefined"!=typeof Symbol&&null!=e[Symbol.iterator]||null!=e["@@iterator"])return Array.from(e)}function _arrayWithoutHoles(e){if(Array.isArray(e))return _arrayLikeToArray(e)}function _arrayLikeToArray(e,r){(null==r||r>e.length)&&(r=e.length);for(var t=0,n=Array(r);t<r;t++)n[t]=e[t];return n}function _regenerator(){var y,e="function"==typeof Symbol?Symbol:{},r=e.iterator||"@@iterator",t=e.toStringTag||"@@toStringTag";function n(e,r,t,n){var o,a,i,c,u,l,s,f,p,r=r&&r.prototype instanceof m?r:m,r=Object.create(r.prototype);return _regeneratorDefine2(r,"_invoke",(o=e,a=t,s=n||[],f=!1,p={p:l=0,n:0,v:y,a:d,f:d.bind(y,4),d:function(e,r){return i=e,c=0,u=y,p.n=r,h}},function(e,r,t){if(1<l)throw TypeError("Generator is already running");for(f&&1===r&&d(r,t),c=r,u=t;(g=c<2?y:u)||!f;){i||(c?c<3?(1<c&&(p.n=-1),d(c,u)):p.n=u:p.v=u);try{if(l=2,i){if(g=i[e=c?e:"next"]){if(!(g=g.call(i,u)))throw TypeError("iterator result is not an object");if(!g.done)return g;u=g.value,c<2&&(c=0)}else 1===c&&(g=i.return)&&g.call(i),c<2&&(u=TypeError("The iterator does not provide a '"+e+"' method"),c=1);i=y}else if((g=(f=p.n<0)?u:o.call(a,p))!==h)break}catch(e){i=y,c=1,u=e}finally{l=1}}return{value:g,done:f}}),!0),r;function d(e,r){for(c=e,u=r,g=0;!f&&l&&!t&&g<s.length;g++){var t,n=s[g],o=p.p,a=n[2];3<e?(t=a===r)&&(u=n[(c=n[4])?5:c=3],n[4]=n[5]=y):n[0]<=o&&((t=e<2&&o<n[1])?(c=0,p.v=r,p.n=n[1]):o<a&&(t=e<3||n[0]>r||a<r)&&(n[4]=e,n[5]=r,p.n=a,c=0))}if(t||1<e)return h;throw f=!0,r}}var h={};function m(){}function o(){}function a(){}var g=Object.getPrototypeOf,e=[][r]?g(g([][r]())):(_regeneratorDefine2(g={},r,function(){return this}),g),i=a.prototype=m.prototype=Object.create(e);function c(e){return Object.setPrototypeOf?Object.setPrototypeOf(e,a):(e.__proto__=a,_regeneratorDefine2(e,t,"GeneratorFunction")),e.prototype=Object.create(i),e}return _regeneratorDefine2(i,"constructor",o.prototype=a),_regeneratorDefine2(a,"constructor",o),_regeneratorDefine2(a,t,o.displayName="GeneratorFunction"),_regeneratorDefine2(i),_regeneratorDefine2(i,t,"Generator"),_regeneratorDefine2(i,r,function(){return this}),_regeneratorDefine2(i,"toString",function(){return"[object Generator]"}),(_regenerator=function(){return{w:n,m:c}})()}function _regeneratorDefine2(e,r,t,n){var a=Object.defineProperty;try{a({},"",{})}catch(e){a=0}(_regeneratorDefine2=function(e,r,t,n){function o(r,t){_regeneratorDefine2(e,r,function(e){return this._invoke(r,t,e)})}r?a?a(e,r,{value:t,enumerable:!n,configurable:!n,writable:!n}):e[r]=t:(o("next",0),o("throw",1),o("return",2))})(e,r,t,n)}function asyncGeneratorStep(e,r,t,n,o,a,i){try{var c=e[a](i),u=c.value}catch(e){return void t(e)}c.done?r(u):Promise.resolve(u).then(n,o)}function _asyncToGenerator(c){return function(){var e=this,i=arguments;return new Promise(function(r,t){var n=c.apply(e,i);function o(e){asyncGeneratorStep(n,r,t,o,a,"next",e)}function a(e){asyncGeneratorStep(n,r,t,o,a,"throw",e)}o(void 0)})}}_asyncToGenerator(_regenerator().m(function e(){var i,s,u,l,r,c,f,p,d,y,h,m,g,t,n;return _regenerator().w(function(e){for(;;)switch(e.n){case 0:if(n=function(){return(n=_asyncToGenerator(_regenerator().m(function e(){var r,t,n,o,a,i,c=arguments;return _regenerator().w(function(e){for(;;)switch(e.n){case 0:if(t=null!=(t=(r=0<c.length&&void 0!==c[0]?c[0]:{}).pathname)?t:window.location.pathname,/\/results\/\d{4}-\d{2}-\d{2}\/?$/.test(t)){e.n=1;break}return e.a(2);case 1:if(g(document))return e.a(2);e.n=2;break;case 2:return n=null!=(n=r.origin)?n:window.location.origin,i=t.match(/\/([^/]+)\/results\/\d{4}-\d{2}-\d{2}/),i=i[1],i="".concat(n,"/").concat(i,"/results/1/"),o=u(),e.n=3,l(i);case 3:a=e.v,i=_toConsumableArray(o.keys()).filter(function(e){return a.has(e)}),m(i,o,a,n);case 4:return e.a(2)}},e)}))).apply(this,arguments)},t=function(){return n.apply(this,arguments)},g=function(e){var e=e.querySelector("h3 span.format-date"),e=null==e?void 0:e.closest("h3");return!!e&&"#1"===(null==(e=(e=e.querySelectorAll("span"))[e.length-1])?void 0:e.textContent.trim())},m=function(e,r,t,n){var o=h(),a=f("Participants Who Attended the Launch Event");o.appendChild(a),0===e.length?(a=p("No attendees from the launch event were present at the latest event."),o.appendChild(a)):(a=y(e,r,t,n),o.appendChild(a)),c(o)},h=function(){var e=document.createElement("div");return e.id="parkrun-launch-returnees",e.style.width="100%",e.style.maxWidth="800px",e.style.margin="20px auto",e.style.padding="15px",e.style.backgroundColor=i.backgroundColor,e.style.borderRadius="8px",e.style.boxShadow="0 2px 4px rgba(0,0,0,0.1)",e.style.color=i.textColor,e},y=function(e,r,t,n){var o=document.createElement("div"),a=(o.style.maxHeight="400px",o.style.overflow="auto",document.createElement("ul"));return a.style.listStyleType="none",a.style.padding="0",a.style.margin="0",a.style.textAlign="center",e.forEach(function(e){e=d(e,r,t,n);a.appendChild(e)}),o.appendChild(a),o},d=function(e,r,t,n){var o=document.createElement("li"),a=document.createElement("a"),n=(a.href="".concat(n,"/parkrunner/").concat(e,"/"),a.target="_blank",r.get(e)||t.get(e)||"Unknown parkrunner");return a.textContent="".concat(n," (A").concat(e,")"),a.style.color=i.linkColor,a.style.textDecoration="none",o.appendChild(a),o},p=function(e){var r=document.createElement("p");return r.textContent=e,r.style.textAlign="center",r.style.fontWeight="bold",r},f=function(e){var r=document.createElement("h3");return r.textContent=e,r.style.textAlign="center",r.style.marginBottom="15px",r.style.color=i.headerColor,r},c=function(e){var r=document.querySelector("h3");r&&r.parentNode?r.nextSibling?r.parentNode.insertBefore(e,r.nextSibling):r.parentNode.appendChild(e):document.body.insertBefore(e,document.body.firstChild)},r=function(){return(r=_asyncToGenerator(_regenerator().m(function e(r){var t,n,o,a,i,c,u,l;return _regenerator().w(function(e){for(;;)switch(e.p=e.n){case 0:if(t="parkrun-launch-returnees-".concat(r),e.p=1,n=localStorage.getItem(t))if(n=JSON.parse(n),o=n.data,n=n.timestamp,Date.now()-n<s)return e.a(2,new Map(o));e.n=2;break;case 2:return e.n=3,fetch(r);case 3:return n=e.v,e.n=4,n.text();case 4:for(o=e.v,l=new DOMParser,l=l.parseFromString(o,"text/html"),a=l.querySelectorAll('a[href*="/parkrunner/"]'),i=new Map,c=0;c<a.length;c++)(u=a[c].href.match(/\/parkrunner\/(\d+)/))&&i.set(u[1],a[c].textContent.trim());return l={data:Array.from(i.entries()),timestamp:Date.now()},localStorage.setItem(t,JSON.stringify(l)),e.a(2,i);case 5:return e.p=5,l=e.v,console.error("Error fetching or parsing:",r,l),e.a(2,new Map)}},e,null,[[1,5]])}))).apply(this,arguments)},l=function(e){return r.apply(this,arguments)},u=function(){for(var e=document.querySelectorAll('a[href*="/parkrunner/"]'),r=new Map,t=0;t<e.length;t++){var n=e[t].href.match(/\/parkrunner\/(\d+)/);n&&r.set(n[1],e[t].textContent.trim())}return r},document.getElementById("parkrun-launch-returnees"))return e.a(2);e.n=1;break;case 1:i={backgroundColor:"#2b223d",headerColor:"#FFA300",textColor:"#EEE",linkColor:"#53BA9D"},s=864e5,"undefined"!=typeof module&&module.exports?module.exports={extractCurrentPageParticipants:u,fetchEventParticipants:l,displayReturnees:m,isLaunchEvent:g,init:t}:t();case 2:return e.a(2)}},e)}))();