Wait, what's a bookmarklet?
thehistoryoftheweb.com
thehistoryoftheweb.com
"Don't mess with paste" - for when signup forms expect you to hand-type your email address twice. javascript:void ["contextmenu","copy","paste","selectstart"].map(e=>document.addEventListener(e,e=>e.stopPropagation(),true))
"Nebula no-alt-#" - Nebula's video viewer annoying captures e.g. alt-3 to do the same as plain 3 (seek to 3/10 of the video currently playing), but I expect it to switch to the 3rd browser tab instead. YouTube doesn't do this. Luckily I can just activate this bookmarklet: javascript:void document.addEventListener("keydown",(e)=>void(e.altKey&&!isNaN(+e.key)&&e.stopPropagation()))
"canvas DL" - when playing skribbl.io and someone has made a nice drawing, this lets you download the current drawing as a PNG. javascript:var w=window.wdq||(window.wdq=document.createElement("a"));var p=/The word was '([^']*)'/g,pp=/<span>([^<>]+) is drawing now!/g,tt=document.body.innerHTML;var mm,nn,xx;while(mm=p.exec(tt))nn=mm;while(mm=pp.exec(tt))xx=mm;w.download=location.host+"_"+(nn?nn[1]+"_":"")+(xx?xx[1]+"_":"")+new Date().toISOString().replace(/:/g,"_");w.href=document.querySelector("canvas").toDataURL();w.click();
Don't Mess With Paste: https://bookmarkl.ink/ashtonmeuser/6e3869d8e468e016f22a4b4de...
Nebula No-Alt-#: https://bookmarkl.ink/ashtonmeuser/6e3869d8e468e016f22a4b4de...
Canvas DL: https://bookmarkl.ink/ashtonmeuser/6e3869d8e468e016f22a4b4de...
Feel free to add this if you want, I have it in my firefox called "UnfuckSlack" which puts the old slack UI back:
javascript:(function() { localStorage.setItem("localConfig_v2", localStorage.getItem("localConfig_v2").replace(/\"is_unified_user_client_enabled\":true/g, '\"is_unified_user_client_enabled\":false')); location.reload(); })();
A simple and sensible way to list bookmarklets may be scraping GitHub's own search [1]. Using a flag in gists such as `// bookmarklink-index` or similar may be a good way to go.
[1] https://gist.github.com/search?q=extension%3Ajs+bookmarklet_...
javascript:( function(){ let i, elements = document.querySelectorAll('body *'); for (i = 0; i < elements.length; i++) { if(getComputedStyle(elements[i]).position === 'fixed' || getComputedStyle(elements[i]).position === 'sticky') { elements[i].parentNode.removeChild(elements[i]); } } document.body.style.overflow = "auto"; document.body.style.position = "static"; })()
Which deletes those annoying page-covering popups like "sign up for my newsletter" or "you need to log in (even though the content is right there*)"``` javascript:(function(){document.querySelectorAll("body ").forEach(function(node){if(["fixed","sticky"].includes(getComputedStyle(node).position)){node.parentNode.removeChild(node)}});document.querySelectorAll("html ").forEach(function(node){var s=getComputedStyle(node);if("hidden"===s["overflow"]){node.style["overflow"]="visible"}if("hidden"===s["overflow-x"]){node.style["overflow-x"]="visible"}if("hidden"===s["overflow-y"]){node.style["overflow-y"]="visible"}});var htmlNode=document.querySelector("html");htmlNode.style["overflow"]="visible";htmlNode.style["overflow-x"]="visible";htmlNode.style["overflow-y"]="visible"})(); ```
((e,l)=>{[...e.querySelectorAll("body")].forEach((e=>{["fixed","sticky"].includes(l(e).position)&&e.parentNode.removeChild(e)})),[...e.querySelectorAll('html,[style\*="overflow"]')].forEach((e=>{["hidden"].includes(l(e).overflow)&&(e.style.overflow="visible"),["hidden"].includes(l(e)["overflow-x"])&&(e.style["overflow-x"]="visible"),["hidden"].includes(l(e)["overflow-y"])&&(e.style["overflow-y"]="visible")}));let o=e.querySelector("html");o.style.overflow=o.style["overflow-x"]=o.style["overflow-y"]="visible"})(document,getComputedStyle);
https://chat.openai.com/share/4c6710b5-9c81-415b-85fc-b33e69...A bookmarklet alone isn't so much a concern, both because it doesn't run automatically on all pages (only when clicked) and because, as you note, you can usually pretty easily audit what you add and you don't get automatic updates.
Unless the bookmarklet updates itself by loading code from another URL. This is blocked by some websites but not all.
For all of these I use an apple script that emulates typing one letter at a time, with a small delay because Citrix can't deal with typing which is too fast.
It's based on Force Paste: https://github.com/EugeneDae/Force-Paste
I invoke it with a shortcut (Alfred on macOS for example) and it's a life saver multiple times a day. Weirdly satisfying to watch happening =)
A nice implementation of this would detect that you pasted/auto-filled the original field and not prompt you to confirm unless you typed it slowly by hand.
You are my hero
Almost as old as when I started singing The Wreck of the Edmund Fitzgerald when asked if I could name all the Great Lakes.
Similarly, while prototyping an internal company wiki I made bookmarklets to fix some Sharepoint shenanigans and add features that otherwise would've required mucking about with extensions (tough when half the company was forced to use IE) or even worse, Sharepoint apps. The entire IT staff had a major WTF moment after explaining just how simple the whole thing was.
Firefox fixed this in a limited way: https://bugzilla.mozilla.org/show_bug.cgi?id=1478037 but other browsers don’t care or won’t
I made one to collapse all comments in a BitBucket PR page (just find each comment and nest it inside a <details> tag, with a <summary> containing the first line of the comment). It's widely used in PRs that deal with Atlantis/Terraform, because Atlantis leaves huge comments on PRs.
I was debugging a database issue the other day [0] and, being new to the firm, I asked "Hey, who is our DBA?"
Every junior SRE on the call asked "What's a DBA??"
0 - Client process hung and left an open transaction
I'm still not bored of it.
* Get Markdown link of the current page as [Title](url):
javascript:void function(){function e(){var e="";if(window.getSelection)e=window.getSelection().toString();else if(document.getSelection)e=document.getSelection().toString();else{if(!document.selection)return null;e=document.selection.createRange().text}return e}var t=e(),n=window.document.title,o=window.location.href,i=[];if(t){i.push("["+t+"]")}else{i.push("["+n+"]"),i.push("("+o+")")}window.prompt("created link",i.join(""))}();
* See current page on the Wayback Machine: javascript:void(window.open('https://web.archive.org/web/*/'+location.href.replace(/\/$/, '')));
* Twitter to Nitter: javascript:h=['nitter.it','nitter.snopyta.org','nitter.net']; location.href=location.href.replace(window.location.host,h[Math.floor(Math.random()*h.length)]);Markdown Link: https://bookmarkl.ink/ashtonmeuser/6e3869d8e468e016f22a4b4de...
Wayback Machine: https://bookmarkl.ink/ashtonmeuser/6e3869d8e468e016f22a4b4de...
Nitter: https://bookmarkl.ink/ashtonmeuser/6e3869d8e468e016f22a4b4de...
The gist also allow people to comment on the bookmarklet.
Of course - now they have a way of injecting arbitrary javascript code into the browser of the people using the service to bookmark the bookmarklet. Lack of trust sucks.
And (due to lack of trust) most applications make it hard to share javscripts links - so you need to instead instruct people to create a new bookmark and past the content into instead of right-clicking a link and clicking "bookmark".
The security risk angle is also a concern I share. If you take a look at the disclaimer at the bottom of my project README [1], you'll see this exact issue mentioned. Versioning gists and thus bookmarklets is discussed in the same document [2]. This locks bookmarklet source to a specific commit of the git repo underlying a gist.
[1] https://github.com/ashtonmeuser/bookmarklet-platform?tab=rea...
[2] https://github.com/ashtonmeuser/bookmarklet-platform?tab=rea...
> And (due to lack of trust) most applications make it hard to share javscripts links - so you need to instead instruct people to create a new bookmark and past [sic] the content into instead of right-clicking a link and clicking "bookmark".
This is mostly true for mobile browsers. For desktop, simply dragging the button to the bookmarks bar ought to do the trick. Please feel free to open an issue if you've found this not to be the case!
javascript:void(window.open('https://web.archive.org/save/'+location.href));
[2] https://bookmarkl.ink/ashtonmeuser/21427841853c9f2292c8f7d7a...
[3] https://bookmarkl.ink/ashtonmeuser/5e696524d986ba6c25af0df89...
It worked gloriously for a year or two, and then the internet decided to stop using structure and broke everything.
Edit: I made one. Its based on:
https://github.com/UserStyles/hacker-news-zenburn-dark
javascript:(()=>{var s=document.createElement('style');s.innerText=`*{color:#dcdccc!important;background-color:#404040!important}body%3Ecenter%3Etable%3Etbody%3Etr:first-child{background-color:#505050!important}body%3Ecenter%3Etable%3Etbody%3Etr:first-childa:hover{background:#404040!important}code,pre,input,textarea{background:#505050!important}a{color:#7F9F7F!important}.subtext%20a{color:#dcdccc!important}a:visited,a:visited%20span{color:#CC9393!important}a:hover,a:hover%20span{background:#505050!important}%60;document.head.appendChild(s)})();
Edit 2: It works on several other sites too. Cool!https://gist.github.com/aclarknexient/c39c83f2f97c3c6b1c307c...
Is this article not finished?
javascript:(function(){var newSS, styles='body { width: 25em !important; overflow: wrap; margin-left: auto; margin-right: auto; }'; if(document.createStyleSheet) { document.createStyleSheet("javascript:'"+styles+"'"); } else { newSS=document.createElement('link'); newSS.rel='stylesheet'; newSS.href='data:text/css,'+escape(styles); document.getElementsByTagName("head")[0].appendChild(newSS); } })();
Kill sticky: javascript:(function()%7B(function%20()%20%7Bvar%20i%2C%20elements%20%3D%20document.querySelectorAll('body%20*')%3Bfor%20(i%20%3D%200%3B%20i%20%3C%20elements.length%3B%20i%2B%2B)%20%7Bif%20(getComputedStyle(elements%5Bi%5D).position%20%3D%3D%3D%20'fixed')%20%7Belements%5Bi%5D.parentNode.removeChild(elements%5Bi%5D)%3B%7D%7D%7D)()%7D)()I often use a bookmarklet I wrote to remove the extra content from online recipes: https://github.com/kevlened/foodmarklet
It’s based on https://github.com/poundifdef/plainoldrecipe, but it works entirely in the client.
This changes the current page into a blank rich text editor where you can paste the recipe instead, which eliminates the Google Docs dependency.
I have one I use on my iPhone that shows page source. Comes in handy sometimes.
javascript:(function()%7Bvar%20a=window.open('about:blank').document;a.write('%3C!DOCTYPE%20html%3E%3Chtml%3E%3Chead%3E%3Ctitle%3ESource%20of%20'+location.href+'%3C/title%3E%3Cmeta%20name=%22viewport%22%20content=%22width=device-width%22%20/%3E%3C/head%3E%3Cbody%3E%3C/body%3E%3C/html%3E');a.close();var%20b=a.body.appendChild(a.createElement('pre'));b.style.overflow='auto';b.style.whiteSpace='pre-wrap';b.appendChild(a.createTextNode(document.documentElement.innerHTML))%7D)();
javascript:!function(){var e=window.open("","_blank");e.document.write("<!DOCTYPE html><html><head><title>Source of "+location.href+"</title><meta name='viewport' content='width=device-width, initial-scale=1.0'></head><body><pre></pre></body></html>"),e.document.body.querySelector("pre").textContent=document.documentElement.outerHTML,e.document.close()}();javascript:function%20c(){}c.prototype.get=function(){var%20a="";window.getSelection?a=window.getSelection().toString():document.selection&&"Control"!=document.selection.type&&(a=document.selection.createRange().text);return%20a};c.prototype.set=function(a){if(window.getSelection){var%20b=window.getSelection();b.rangeCount&&(b=b.getRangeAt(0),b.deleteContents(),b.insertNode(document.createTextNode(a)))}else%20document.selection&&document.selection.createRange&&(b=document.selection.createRange(),b.text=a)};try{var%20d=new%20c,e=atob(d.get());d.set(e)}catch(a){alert(a.message)};
Halfway between bookmarklets and browser extensions sit user scripts: arbitrary long scripts that are run by a specialized extension (usually, today, TamperMonkey).
They are incredibly powerful and can customize pretty much any webpage, with none of the limitations of bookmarklets, and very little of the hassle of creating a proper extension.
They're quite addictive.
But I have been making them at work to bypass and improve some quirks of Atlassian products for instance (JIRA and Confluence), and there they spread like wildfire.
data:text/html,<title>texed</title><body style=margin:0><textarea autofocus spellcheck=false style=width:100vw;height:100vh;resize:none;border:0;padding:6pt;font-family:monospace;font-size:large;background-color:rgb(22,22,22);color:lightyellow>Eg
javascript:/* name: /awesome# */alert(2+2)Still interesting to look at Chromium's source to see that they have unit tests for bookmarklets [1]. Also looks like people "frequently" report running JS from bookmarks as an XSS vulnerability [2]
[1] https://github.com/chromium/chromium/blob/0acce829e996f8387c...
[2] https://github.com/chromium/chromium/blob/0acce829e996f8387c...
/* comment */
Bookmarklets, like bookmarks, also have names.I didn't phrase it very well but I figured people would just drag and drop it in Chrome and see it for themselves.
> I didn't phrase it very well but I figured people would just drag and drop it in Chrome and see it for themselves.
I did. I spent way too long (15+ minutes) doing that, trying variations of the bookmarklet and user interactions to see if doing so would cause some observable difference and reveal some insight, and trying on different plausible (and implausible) interpretations of your comment.
When I drag and drop this to the Chrome bookmark bar, it will create a new bookmarklet with the name "awesome"
javascript:/* name: /awesome# */alert(2+2)
It doesn't seem to work on Chromium on Ubuntu. I don't have a Mac to try it on, perhaps someone else can try it.I mean does it need a line break as it is seen in your code?
They had a simple wysiwyg in the browser html editor, in the pre-Ajax era.
javascript:(function()%20{%20var%20s,e,i,ee=document.getElementsByTagName('*');%20for(i=0;%20e=ee[i];%20i++)%20{%20s=getComputedStyle(e);%20if%20(s%20&&%20s.position%20==%20'fixed')%20e.style.position='static';%20}%20})();javascript:var ni%3Ddocument.createNodeIterator(document.documentElement,NodeFilter.SHOW_ELEMENT,function(node)%7Breturn document.defaultView.getComputedStyle(node,null).getPropertyValue("position").match(/sticky|fixed/) %3F NodeFilter.FILTER_ACCEPT : NodeFilter.FILTER_REJECT%3B%7D)%3Bwhile(currentNode%3Dni.nextNode())%7Bconsole.log(currentNode.remove())%3B%7D
Wish there was easier way to customize/set favicon for bookmarklet. Right now you can export bookmark, edit in <A ICON> data, and import. If you have multiple chrome sessions you need to import on all devices within short period or icon will reset to default globe.
javascript: (function() { document.body.contentEditable = true; document.body.spellcheck = false; })();
---Longer bookmarklets: https://github.com/madacol/web-automation/tree/master/bookma...
- Highlight selected text
- chatgpt to markdown
- Convert images to base64 DataURL markdown embedding javascript:location.href="https://sci-hub.se/"+location.href; javascript: Qr = window.getSelection ? window.getSelection().toString() : document.selection.createRange().text; if (Qr) { void(window.open('https://sci-hub.se/' + String(Qr).replace(/^\s+|\s+$/g, ''))); } else { void(Qr = prompt('Enter URL/DOI to sci-hub it', '')); location.href = 'https://sci-hub.se/' + String(Qr).replace(/^\s+|\s+$/g, ''); } javascript:void(open("https://web.archive.org/save/" + document.location))
Archive current page with archive.today: javascript:void(open("https://archive.ph/?run=1&url=" + encodeURIComponent(document.location)))
Search Google Cache for current page: javascript:void(open("https://webcache.googleusercontent.com/search?q=cache:" + document.location))
Open current Reddit post in Reveddit: javascript:void(open("https://www.reveddit.com/" + document.location.pathname))EDIT: it can still be accessed from here https://news.ycombinator.com/bookmarklet.html
EDIT 2: the bookmarklet is also linked from HN's "submit" page, just below the form.
javascript:window.location=%22http://news.ycombinator.com/submitlink?u=%22+encodeURIComponent(document.location)+%22&t=%22+encodeURIComponent(document.title)`javascript:(()=>{b=document.createElement("button");b.onclick=()=>{document.documentElement.requestFullscreen();b.remove()};b.style="all:reset;position:fixed;z-index:9999;left:0%;top:0%;width:100%;height:100%;background-color:lightpink";b.innerText="Full Screen";document.body.appendChild(b)})()`
It pops up a giant red button, as user interaction is required for fullscreen
I also made some overlay grid helpers, like 8h and 8v which create some overlay pass through elements and render red grid lines(8px spacing) using css. This is like an alignment tool for every page.
The bad thing is that Chrome and Edge don't highlight bookmarks by default when searching and makes one to type the top arrow key. Firefox used to be better in this regard, with the bookmarklet highlighted and ready to hit. The workaround for Chrome and Edge is to make the bookmarklet a search engine, that makes the bookmarklet selected by default.
Bookmarklets and custom search engines (for various online documentation sites, or plain jira, or aws) can be a productivity booster.
I wouldn't be able to navigate aws ssm without my trusty ssm search engine. Same for the others: EC2, CF, S3.
I should be using bookmarklets more though.
Everything is stored in the URL, actually I am just thinking I should add offline first support.
https://jstrieb.github.io/projects/hidden-bookmarks/
Every clicked bookmarklet concatenates a character to a passphrase used for AES decryption. The encrypted text and current passphrase are stored as intermediate state in the URL hash. When it decrypts, it redirects. If it doesn't decrypt, it goes to a fallback page as if it was a regular bookmark.
It was mostly a fun proof-of-concept, but I am hopeful that the technique has actually been useful to someone.
```javascript:var url = new String(location.href); var re = new RegExp('(https?:\/\/)([a-zA-Z0-9.]+)((\/r\/.\/)(comments.))?'); var res = url.match(re); // go to the root URL root_url = res[1] + res[2]; // If we are in a subreddit, go to the subreddit
re = new RegExp('.*reddit.com'); if( res[2].match(re)) { if (typeof res[3] !== 'undefined' && typeof res[4] != 'undefined') { root_url = root_url + res[4]; } } location.href=root_url;```
javascript:some_code
You would write: snippet:name
Snippets are much easier to write because snippets are edited in normal multiline editor with console and stuff.Most of my bookmarklets are specific to work projects and I save them in the repo itself in a top-level bookmarklets.js file so I can use VSCode to edit them. (Then I just copy and paste them into the browser bookmark.)
Mhm, snippets seem to be chrome only
javascript:window.location='https://web.archive.org/web/*/'+document.location
javascript:location="https://translate.google.com/translate?hl=&sl=auto&tl=en&u="+location
On any page, I can type ctrl-L (select address bar), gs, enter, and I get the page translated to English.A couple more:
Wayback machine: javascript:location="https://archive.md/submit/?url="+location
12 foot ladder: javascript:location="https://12ft.io/proxy?q="+locationRotate images 90° clockwise:
javascript:(()=>{var imgs = document.getElementsByTagName("img");for (var img of imgs){img.setAttribute("style","transform:rotate(90deg);");}})(); javascript:document.querySelectorAll('img').forEach(img => img.setAttribute('style','transform:rotate(90deg);'))Over the years I’ve built one up that recognizes various record ID formats or other record numbers and automatically takes you to that record or forwards you to the site if you paste the entire url.
It has a few other keyword shortcuts to save on monotonous clicks.
Nowadays with slack and people being a bit web savvier in general it’s not as useful as it once was, but you’d be surprised how annoying it is to enter jira ticket ids over and over.
These you posted are really great
"The Bookmarks bar faded to the background more. Bookmarklets are still in use, and still quite useful, but they are …."
They are what?
"Show HN: All the new bookmarklets."
:-)
Speed up video/audio on youtube
javascript:(function() { (document.querySelector('video') || document.querySelector('audio')).playbackRate = (+prompt('How many times normal speed?') || 1); })();
Bypass paywall javascript:location.href='https://archive.is/?run=1&url=%27+encodeURIComponent(document.location.href) Shift+, or . for changing the speed.
They cannot be customized though.data:text/html,<script>now=new Date();alert(`Today is DOY ${1+Math.floor((now.getTime()-new Date(now.getFullYear(),0,1).getTime())/8.64E7)}`);</script>
javascript:(function(){alert(window.location.href.replace(/\/edit.*$/, '/edit?usp=sharing%27));})()Firefox doesn't directly support bookmarklets, IIRC, so instead I use a custom search engine with a bookmarklet for the URL to accomplish the same thing.
My first Bookmarklet: When is my next payday? My job used to pay salary monthly, on second last working day of month (Sun to Thu was working week). I eagerly used to count the days remaining for next payday. I realized that Javascript can do this for me. PayDay was born. I still have the code at https://gitlab.com/davchana/payday/-/blob/beta/payday_v1_01_... Coincidently this was my first project on Gitlab.
Then, Google Chrome used to remember passwords, but there was no password manager inbuilt to view passwords. I found this View Passwords code at https://ostermiller.org/bookmarklets/viewpass.js & minified it & have been using it since last 12 years, in a mobile with ViewPasswords name. The only change I did was making the div containing found passwords contenteditable to make it easy to copy. I have been using it since 2012. Somewhere in between these years I lost the original code but I came across it again in 2023.
I also made my own version of fancy view passwords, code at https://gitlab.com/davch/bookmarklets/-/blob/master/viewPass... but I tend to use the original one more often.
One of the proudest bookmarklet is CAJobAppsGSV2 (California Job Apps Google Apps Script v2). CA has a standard way of applying for government jobs, where you create templates per position title & then apply it by going through 5 or 6 pages. This BM looks at the address, a switch fires up the function, that function choses the correct dropdown values & clicks appropriate buttons & also saves some data in SessionStorage. After the confirmation it adds a div to the box, which on clicked upon closes itself. The BM prepares data from storage & page, & fires up a POST request to Google Apps Web Script, which saves it as a line item to a sheet. While doing this, it logs the statuses to the div.
I use BMs for fixing up the print layout of TripCase Tickets, to fetch & get data on clipborad about my paystub, quickshortcuts to data at who.is & xe.com.
javascript:var%20p=document.getElementsByTagName('*');for(i=0;i%3Cp.length;i++)%7Bif(p%5Bi%5D.style.fontSize)%7Bvar%20s=parseInt(p%5Bi%5D.style.fontSize.replace(%22px%22,%22%22));%7Delse%7Bvar%20s=12;%7Ds+=8;p%5Bi%5D.style.fontSize=s+%22px%22%7D
I guess it IS a security concern to run arbitrary javascript inside the slack app of another user.
But makes sharing bookmarklets that way harder.
For mobile Chrome:
- Create a new bookmark
- Replace the bookmarked link with the bookmarklet javaScript code, e.g., javascript:alert('hello world')
- To use the bookmarklet, start typing the bookmark name in the address bar until the auto-complete displays the bookmark, and then click on it.
For mobile Safari,
- Create a new bookmark and replace the URL with your javaScript code
- To use the bookmarklet, tap on the bookmarklet name from the bookmarks menu
(The edit was to better format my comment)
I can’t remember if I’ve done this before. It seems like something I’ve done.
javascript:eval(atob('c2V0SW50ZXJ2YWwoZnVuY3Rpb24gKCkgewogICAgdmFyIGVsZW0gPSBkb2N1bWVudC5nZXRFbGVtZW50c0J5Q2xhc3NOYW1lKCd5dHAtYWQtc2tpcC1idXR0b24geXRwLWJ1dHRvbicpWzBdOwogICAgaWYgKGVsZW0pIHsKICAgICAgICBlbGVtLmNsaWNrKCk7CiAgICB9Cn0sIDEwMDApOw=='))
https://medium.com/making-instapaper/bookmarklets-are-dead-d...