├── COPYING
├── README
├── _toolbar
├── 00-read.js
├── 05-prev.js
├── 10-next.js
├── 15-ffwd.js
├── 20-untrack.js
├── 25-nocookie.js
├── 90-rmi.js
└── README
├── bookmarks-without-parameters.html
├── bookmarks.html
├── content
├── README
├── alt2title.js
├── comparecells.js
├── ffwd.js
├── freeviddy.js
├── fullimg.js
├── jump.js
├── nocookie.js
├── read.js
├── rmi.js
├── rmo.js
├── sort.js
└── vidspeed.js
├── development
├── README
├── addcss.js
├── b64.js
├── dumphtml.js
├── html.js
├── len.js
├── magic.js
├── reconsole.js
├── reloadcss.js
├── text.js
├── title.js
├── urldec.js
└── urlenc.js
├── forms
├── README
├── checkpass.js
├── freeform.js
├── frmblank.js
├── frmcomp.js
├── frmfill.js
├── frmget.js
├── frmpost.js
└── showpass.js
├── generate-bookmarks-html
├── language
├── README
├── dictionaries
│ ├── README
│ ├── ac.js
│ ├── dewikt.js
│ ├── dict.js
│ ├── enwikt.js
│ ├── eswikt.js
│ ├── frwikt.js
│ ├── itwikt.js
│ ├── mw.js
│ ├── nlwikt.js
│ ├── nowikt.js
│ ├── oed.js
│ ├── ptwikt.js
│ ├── ruwikt.js
│ ├── svwikt.js
│ ├── thes.js
│ ├── ud.js
│ ├── vd.js
│ ├── viwikt.js
│ ├── vw.js
│ └── zhwikt.js
├── shuo.js
└── translations
│ ├── 2de.js
│ ├── 2en.js
│ ├── 2es.js
│ ├── 2fr.js
│ ├── 2it.js
│ ├── 2nl.js
│ ├── 2no.js
│ ├── 2pt.js
│ ├── 2ru.js
│ ├── 2sv.js
│ ├── 2vi.js
│ ├── 2zh.js
│ └── README
├── navigation
├── README
├── back.js
├── link.js
├── linksto.js
├── linktitles.js
├── next.js
├── prev.js
├── refer.js
├── relink.js
├── rmh.js
├── rmhq.js
├── rmq.js
├── rmqh.js
├── root.js
├── unarchive.js
├── untrack.js
└── up.js
├── search
├── README
├── bimg.js
├── ddg.js
├── ddimg.js
├── e.js
├── eimg.js
├── g.js
├── gc.js
├── gimg.js
├── go.js
├── gs.js
├── img.js
├── maps
│ ├── README
│ ├── bmap.js
│ ├── drive.js
│ ├── fly.js
│ ├── map.js
│ ├── mapi.js
│ ├── ride.js
│ ├── transit.js
│ └── walk.js
├── search.js
├── tineye.js
├── tw.js
├── tweep.js
├── wb.js
├── wikipedia
│ ├── 2comm.js
│ ├── README
│ ├── anyw.js
│ ├── dew.js
│ ├── enw.js
│ ├── esw.js
│ ├── frw.js
│ ├── itw.js
│ ├── nlw.js
│ ├── now.js
│ ├── ptw.js
│ ├── ruw.js
│ ├── svw.js
│ ├── viw.js
│ ├── wikiv.js
│ └── zhw.js
├── yanimg.js
├── yt.js
└── yttop.js
├── site-specific
├── README
├── discogs.js
├── emo.js
├── githublet.js
├── kbo.js
├── printriodos.js
├── redtop.js
├── somanp.js
└── strava
│ ├── README
│ ├── pace2speed.js
│ ├── sact.js
│ ├── sath.js
│ ├── sclub.js
│ ├── shide.js
│ ├── sseg.js
│ └── sstats.js
├── snippets.bash
└── tests
├── README
└── content
└── sort
└── tables.html
/COPYING:
--------------------------------------------------------------------------------
1 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
2 | Version 2, December 2004
3 |
4 | Copyright (C) 2011–2021 Jan Moesen
5 |
6 | Everyone is permitted to copy and distribute verbatim or modified
7 | copies of this license document, and changing it is allowed as long
8 | as the name is changed.
9 |
10 | DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
11 | TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
12 |
13 | 0. You just DO WHAT THE FUCK YOU WANT TO.
14 |
--------------------------------------------------------------------------------
/README:
--------------------------------------------------------------------------------
1 | Jan Moesen’s bookmarklets
2 |
3 | A collection of time-saving and life-enhancing (ahem) bookmarklets.
4 |
5 | These bookmarklets are used for various purposes, but they all share the same
6 | goal: make web browsing and development easier and more efficient.
7 |
8 | I like giving my bookmarklets keywords so I can use my address bar as a
9 | command line. (If you speak Dutch, check out this presentation from 2011:
10 | http://kak.be/phl.)
11 |
12 | The bookmarklets are stored here as separate script files. You can copy and
13 | paste them into your bookmarks manager, or import them wholesale using the
14 | generated `bookmarks.html` file.
15 |
16 | Feel free to fork and create pull requests: http://kak.be/bookmarklets
17 |
18 | See COPYING for licence details. Or “license details”, if you are so inclined.
19 |
--------------------------------------------------------------------------------
/_toolbar/00-read.js:
--------------------------------------------------------------------------------
1 | ../content/read.js
--------------------------------------------------------------------------------
/_toolbar/05-prev.js:
--------------------------------------------------------------------------------
1 | ../navigation/prev.js
--------------------------------------------------------------------------------
/_toolbar/10-next.js:
--------------------------------------------------------------------------------
1 | ../navigation/next.js
--------------------------------------------------------------------------------
/_toolbar/15-ffwd.js:
--------------------------------------------------------------------------------
1 | ../content/ffwd.js
--------------------------------------------------------------------------------
/_toolbar/20-untrack.js:
--------------------------------------------------------------------------------
1 | ../navigation/untrack.js
--------------------------------------------------------------------------------
/_toolbar/25-nocookie.js:
--------------------------------------------------------------------------------
1 | ../content/nocookie.js
--------------------------------------------------------------------------------
/_toolbar/90-rmi.js:
--------------------------------------------------------------------------------
1 | ../content/rmi.js
--------------------------------------------------------------------------------
/_toolbar/README:
--------------------------------------------------------------------------------
1 | Bookmarks toolbar
2 |
3 | These are the bookmarklets I keep on the bookmarklets toolbar for quick access
4 | with the mouse. For instance, when browsing a web comic, it is easier to keep
5 | the cursor positioned over the "Next »" and just keep clicking it, rather than
6 | typing "next" every time. (Or looking for the "Next" link on the web
7 | page itself.)
8 |
--------------------------------------------------------------------------------
/content/README:
--------------------------------------------------------------------------------
1 | Content
2 |
3 | Tweak the page's content.
4 |
--------------------------------------------------------------------------------
/content/alt2title.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Set the IMG@title to the IMG@alt attribute. If the image already has a title
3 | * attribute, separate the title and alt text with a blank line.
4 | *
5 | * @title Alt to title
6 | */
7 | (function alt2title() {
8 | var processedDocuments = [];
9 |
10 | (function execute(document) {
11 | /* Recurse for (i)frames. */
12 | try {
13 | Array.from(document.querySelectorAll('frame, iframe, object[type^="text/html"], object[type^="application/xhtml+xml"]')).forEach(
14 | elem => { try { execute(elem.contentDocument) } catch (e) { } }
15 | );
16 | } catch (e) {
17 | /* Catch and ignore exceptions for out-of-domain access. */
18 | }
19 |
20 | if (processedDocuments.indexOf(document) > -1) {
21 | return;
22 | }
23 |
24 | processedDocuments.push(document);
25 |
26 | function setTitleForElement(element) {
27 | if (!element || element.hasBeenProcessedByAlt2Title)
28 | {
29 | return;
30 | }
31 |
32 | var newTitle = '';
33 | if (element.hasAttribute('title')) {
34 | newTitle = element.getAttribute('title') + '\n\n';
35 | }
36 |
37 | if (!element.hasAttribute('alt')) {
38 | newTitle += '(Missing alt text)';
39 | } else {
40 | var alt = element.getAttribute('alt');
41 |
42 | if (alt === '') {
43 | newTitle += '(Empty alt text)';
44 | } else {
45 | newTitle += 'Alt text: “' + alt + '”';
46 | }
47 | }
48 |
49 | element.setAttribute('title', newTitle);
50 |
51 | console.log('Alt to title: setting title for ', element, ' to: ', newTitle);
52 |
53 | element.hasBeenProcessedByAlt2Title = true;
54 | };
55 |
56 | /* Process all existing images. */
57 | var imageSelector = 'img, input[type="image"], area';
58 | [].forEach.call(document.querySelectorAll(imageSelector), setTitleForElement);
59 |
60 | /* Add a hover handler for images that may be added in the future. */
61 | document.addEventListener('mousemove', function (e) {
62 | var element;
63 | if (e.target && typeof e.target.closest === 'function' && (element = e.target.closest(imageSelector))) {
64 | setTitleForElement(element);
65 | }
66 | }, false);
67 | })(document);
68 | })();
69 |
--------------------------------------------------------------------------------
/content/ffwd.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Speed up the video and audio playback rate, starting from 10x back to 1x by
3 | * executing this bookmarklet multiple times. Executing it once more after the
4 | * normal speed will restart the cycle from the maximum speed again.
5 | *
6 | * @title FFWD ⏩
7 | */
8 | (function ffwd() {
9 | 'use strict';
10 |
11 | const playbackRates = [10, 4, 2, 1.5, 1];
12 |
13 | let playbackRateToUse = undefined;
14 |
15 | /* Recursively execute the logic on the document and its sub-documents. */
16 | function execute(document) {
17 | let allMedia = Array.from(document.querySelectorAll('video, audio'));
18 |
19 | /* Find video and audio inside the shadow DOM of custom elements (Web Components). */
20 | const notRegularHtmlElementsSelector = 'a,abbr,address,area,article,aside,audio,b,base,bdi,bdo,blockquote,body,br,button,canvas,caption,cite,code,col,colgroup,data,datalist,dd,del,details,dfn,dialog,div,dl,dt,em,embed,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,head,header,hgroup,hr,html,i,iframe,img,input,ins,kbd,label,legend,li,link,main,map,mark,math,math *,menu,meta,meter,nav,noscript,object,ol,optgroup,option,output,p,param,picture,pre,progress,q,rp,rt,ruby,s,samp,script,section,select,slot,small,source,span,strong,style,sub,summary,sup,svg,svg *,table,tbody,td,template,textarea,tfoot,th,thead,time,title,tr,track,u,ul,var,video,wbr'
21 | .split(',')
22 | .map(s => `:not(${s})`)
23 | .join('');
24 |
25 | Array.from(document.querySelectorAll(notRegularHtmlElementsSelector))
26 | .filter(elem => elem.shadowRoot)
27 | .forEach(elem => allMedia = allMedia.concat(Array.from(elem.shadowRoot.querySelectorAll('video, audio'))));
28 |
29 | allMedia.forEach(media => {
30 | /* Determine the playback rate to use on all video/audio, based
31 | * on the first element encountered. */
32 | if (typeof playbackRateToUse === 'undefined') {
33 | for (let i = 0; i < playbackRates.length; i++) {
34 | if (media.playbackRate >= playbackRates[i]) {
35 | playbackRateToUse = i === playbackRates.length - 1
36 | ? playbackRates[0]
37 | : playbackRates[i + 1];
38 | break;
39 | }
40 | }
41 | }
42 |
43 | media.playbackRate = playbackRateToUse;
44 |
45 | /* Indicate the new playback rate (speed) for the media element. */
46 | let visibleMediaContainer = media;
47 | let rect = visibleMediaContainer.getBoundingClientRect();
48 | while (
49 | (rect.height <= 0 || rect.width <= 0)
50 | && (visibleMediaContainer = visibleMediaContainer.parentNode)
51 | && (typeof visibleMediaContainer.getBoundingClientRect === 'function')
52 | ) {
53 | rect = visibleMediaContainer.getBoundingClientRect();
54 | }
55 |
56 | const indicator = document.createElementNS('http://www.w3.org/1999/xhtml', 'div');
57 | indicator.textContent = media.playbackRate + '×';
58 | indicator.setAttribute('style', `
59 | display: flex;
60 | position: fixed;
61 | left: ${Math.max(0, rect.left)}px;
62 | top: ${Math.max(0, rect.top)}px;
63 | z-index: 10000;
64 | width: ${rect.width}px;
65 | height: ${rect.height}px;
66 | font-size: ${rect.height / 10}px;
67 | justify-content: center;
68 | align-items: center;
69 | color: rgba(0, 0, 0, 1);
70 | text-shadow: 0 0 10px rgba(255, 255, 255, 1);
71 | transition: all 0.75s ease-out;
72 | pointer-events: none;
73 | `.replace(/^\s*|\s*$/gm, ''));
74 |
75 | document.body.appendChild(indicator);
76 |
77 | /* Animate and remove the indicator. */
78 | setTimeout(_ => {
79 | setTimeout( _ => indicator.remove(), 750);
80 |
81 | indicator.setAttribute('style', indicator.getAttribute('style') + `
82 | font-size: ${rect.height}px;
83 | color: rgba(0, 0, 0, 0);
84 | text-shadow: 0 0 10px rgba(255, 255, 255, 0);
85 | `.replace(/^\s*|\s*$/gm, ''));
86 | }, 0);
87 | });
88 |
89 | /* Recurse for (i)frames. */
90 | try {
91 | Array.from(document.querySelectorAll('frame, iframe, object[type^="text/html"], object[type^="application/xhtml+xml"]')).forEach(
92 | elem => { try { execute(elem.contentDocument) } catch (e) { } }
93 | );
94 | } catch (e) {
95 | /* Catch and ignore exceptions for out-of-domain access. */
96 | }
97 | }
98 |
99 | execute(document);
100 | })();
101 |
--------------------------------------------------------------------------------
/content/freeviddy.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Free the VIDEO elements: get rid of overlays, and enable the native controls.
3 | *
4 | * Useful on https://www.instagram.com/ where the stupid overlays prevent
5 | * showing the controls and triggering the context menu, so you don’t know how
6 | * long the video will take and can't play the video in full screen mode.
7 | *
8 | * @title Free Viddy
9 | */
10 | (function freeviddy() {
11 | "use strict";
12 |
13 | /* Recursively execute the main logic on the document and its sub-documents. */
14 | function execute(document) {
15 | document.addEventListener('mousemove', function debouncer(event) {
16 | clearTimeout(debouncer.timeoutId);
17 | debouncer.timeoutId = setTimeout(function () {
18 | let elementsUnderPointer = document.elementsFromPoint(event.clientX, event.clientY);
19 | let overlaysToRemove = [];
20 |
21 | for (let i = 0; i < elementsUnderPointer.length; i++) {
22 | if (elementsUnderPointer[i].tagName.toUpperCase() === 'VIDEO' && !elementsUnderPointer[i].xxxJanFreeViddyProcessed) {
23 | let video = elementsUnderPointer[i];
24 | video.controls = true;
25 | video.xxxJanFreeViddyProcessed = true;
26 |
27 | if (i === 0) {
28 | console.log('Free Viddy: found video without overlays:', video);
29 | } else {
30 | overlaysToRemove = elementsUnderPointer.slice(0, i);
31 | console.log(`Free Viddy: found video with ${i} overlays:`, video);
32 | }
33 |
34 | break;
35 | }
36 | }
37 |
38 | if (overlaysToRemove.length) {
39 | overlaysToRemove.forEach(element => element.remove());
40 | }
41 | }, 50);
42 | });
43 |
44 | /* Recurse for (i)frames. */
45 | try {
46 | Array.from(document.querySelectorAll('frame, iframe, object[type^="text/html"], object[type^="application/xhtml+xml"]')).forEach(
47 | elem => { try { execute(elem.contentDocument) } catch (e) { } }
48 | );
49 | } catch (e) {
50 | /* Catch and ignore exceptions for out-of-domain access. */
51 | }
52 | }
53 |
54 | execute(document);
55 | })();
56 |
--------------------------------------------------------------------------------
/content/rmi.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Remove all the IFRAMEs that are off-site or do not have a “src” attribute.
3 | * These are typically used for ads and unwanted external content.
4 | * navigation etc.
5 | *
6 | * IFRAMEs without a “src” attribute are also used for sandboxing untrusted
7 | * content, e.g. on mailinator.com, but I have not yet found a way to
8 | * distinguish between src-less IFRAMEs for ads and src-less IFRAMEs for
9 | * “regular” content. Maybe try to guess based on the dimensions? Meh.
10 | *
11 | * @title rm IFRAMEs
12 | */
13 | (function rmi() {
14 | /* Keep track of the HTMLDocument instances we have processed. */
15 | let processed = new Set();
16 |
17 | /**
18 | * Is the given node empty-ish? I.e., does it lack child elements and
19 | * non-whitespace text?
20 | */
21 | function isEmpty(node) {
22 | return !node || (!node.childElementCount && (typeof node.textContent !== 'string' || node.textContent.trim() === ''));
23 | }
24 |
25 | /* The main function. */
26 | (function execute(document) {
27 | if (!document || typeof document.querySelectorAll !== 'function' || processed.has(document)) {
28 | return;
29 | }
30 |
31 | processed.add(document);
32 |
33 | /* Process all IFRAMEs. */
34 | Array.from(document.querySelectorAll('iframe:not(#xxxJanConsole)')).forEach(iframe => {
35 | let shouldDelete = false;
36 | try {
37 | shouldDelete = iframe.contentDocument === null || iframe.src === '';
38 | } catch (e) {
39 | shouldDelete = true;
40 | }
41 |
42 | if (shouldDelete) {
43 | console.log('rm IFRAMEs: found suspicious IFRAME to delete: ', iframe);
44 | let parentNode = iframe.parentNode;
45 | iframe.remove();
46 |
47 | while (parentNode && isEmpty(parentNode)) {
48 | console.log('rm IFRAMEs: found empty parent node to delete: ', parentNode);
49 | let oldParentNode = parentNode;
50 | parentNode = parentNode.parentNode;
51 | oldParentNode.remove();
52 | }
53 | } else {
54 | console.log('rm IFRAMEs: found non-suspicious IFRAME to recurse into: ', iframe);
55 | execute(iframe.contentDocument);
56 | }
57 | });
58 | })(document);
59 | })();
60 |
--------------------------------------------------------------------------------
/content/vidspeed.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Change the video and audio speed (playback rate).
3 | *
4 | * @title Set video speed
5 | */
6 | (function vidspeed() {
7 | "use strict";
8 |
9 | /* Recursively get all video and audio for the document and its sub-documents. */
10 | function getMedia(document) {
11 | let allMedia = Array.from(document.querySelectorAll('video, audio'));
12 |
13 | /* Find video and audio inside the shadow DOM of custom elements (Web Components). */
14 | const notRegularHtmlElementsSelector = 'a,abbr,address,area,article,aside,audio,b,base,bdi,bdo,blockquote,body,br,button,canvas,caption,cite,code,col,colgroup,data,datalist,dd,del,details,dfn,dialog,div,dl,dt,em,embed,fieldset,figcaption,figure,footer,form,h1,h2,h3,h4,h5,h6,head,header,hgroup,hr,html,i,iframe,img,input,ins,kbd,label,legend,li,link,main,map,mark,math,math *,menu,meta,meter,nav,noscript,object,ol,optgroup,option,output,p,param,picture,pre,progress,q,rp,rt,ruby,s,samp,script,section,select,slot,small,source,span,strong,style,sub,summary,sup,svg,svg *,table,tbody,td,template,textarea,tfoot,th,thead,time,title,tr,track,u,ul,var,video,wbr'
15 | .split(',')
16 | .map(s => `:not(${s})`)
17 | .join('');
18 |
19 | Array.from(document.querySelectorAll(notRegularHtmlElementsSelector))
20 | .filter(elem => elem.shadowRoot)
21 | .forEach(elem => allMedia = allMedia.concat(Array.from(elem.shadowRoot.querySelectorAll('video, audio'))));
22 |
23 | /* Recurse for frames and iframes. */
24 | try {
25 | Array.from(
26 | document.querySelectorAll('frame, iframe, object[type^="text/html"], object[type^="application/xhtml+xml"]')
27 | ).forEach(
28 | elem => allMedia = allMedia.concat(getMedia(elem.contentDocument))
29 | );
30 | } catch (e) {
31 | /* Catch exceptions for out-of-domain access, but do not do anything with them. */
32 | }
33 |
34 | return allMedia;
35 | }
36 |
37 | let allMedia = getMedia(document);
38 |
39 | /* Make sure there are media elements. */
40 | if (!allMedia.length) {
41 | return;
42 | }
43 |
44 | /* Try to get the parameter string from the bookmarklet/search query.
45 | * If there is no parameter, prompt the user. */
46 | let s = (function () { /*%s*/; }).toString()
47 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
48 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
49 | .replace(/\u0025s/, '');
50 |
51 | if (s === '') {
52 | s = prompt('Specify the speed (playback rate) as a number, with 1 being 100%. For example, 1.25 = 125%, 0.75 = 75%, and 1 = 100%.', allMedia[0].playbackRate);
53 | }
54 |
55 | if (s) {
56 | allMedia.forEach(media => {
57 | media.playbackRate = s;
58 |
59 | /* Indicate the new playback rate (speed) for the media element. */
60 | let visibleMediaContainer = media;
61 | let rect = visibleMediaContainer.getBoundingClientRect();
62 | while (
63 | (rect.height <= 0 || rect.width <= 0)
64 | && (visibleMediaContainer = visibleMediaContainer.parentNode)
65 | && (typeof visibleMediaContainer.getBoundingClientRect === 'function')
66 | ) {
67 | rect = visibleMediaContainer.getBoundingClientRect();
68 | }
69 |
70 | const indicator = document.createElementNS('http://www.w3.org/1999/xhtml', 'div');
71 | indicator.textContent = media.playbackRate + '×';
72 | indicator.setAttribute('style', `
73 | display: flex;
74 | position: fixed;
75 | left: ${Math.max(0, rect.left)}px;
76 | top: ${Math.max(0, rect.top)}px;
77 | z-index: 10000;
78 | width: ${rect.width}px;
79 | height: ${rect.height}px;
80 | font-size: ${rect.height / 10}px;
81 | justify-content: center;
82 | align-items: center;
83 | color: rgba(0, 0, 0, 1);
84 | text-shadow: 0 0 10px rgba(255, 255, 255, 1);
85 | transition: all 0.75s ease-out;
86 | pointer-events: none;
87 | `.replace(/^\s*|\s*$/gm, ''));
88 |
89 | document.body.appendChild(indicator);
90 |
91 | /* Animate and remove the indicator. */
92 | setTimeout(_ => {
93 | setTimeout( _ => indicator.remove(), 750);
94 |
95 | indicator.setAttribute('style', indicator.getAttribute('style') + `
96 | font-size: ${rect.height}px;
97 | color: rgba(0, 0, 0, 0);
98 | text-shadow: 0 0 10px rgba(255, 255, 255, 0);
99 | `.replace(/^\s*|\s*$/gm, ''));
100 | }, 0);
101 | });
102 | }
103 | })();
104 |
--------------------------------------------------------------------------------
/development/README:
--------------------------------------------------------------------------------
1 | Development
2 |
3 | Tools to help development.
4 |
--------------------------------------------------------------------------------
/development/addcss.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Add the specified CSS to the current document.
3 | *
4 | * @title Add CSS
5 | */
6 | (function addcss(document, s) {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | s = s || (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter your CSS code:');
62 | } else if (s.includes('~') && !s.includes('{')) {
63 | /* Only replace `~` with the active selection if the entire parameter
64 | * string does not look like a CSS rule. For this bookmarklet, `~` is
65 | * more likely to refer to the sibling combinator, e.g. `p ~ ul` than
66 | * to the “replace this with the selection” magic like in the other
67 | * bookmarklets. */
68 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
69 | }
70 |
71 | if (s) {
72 | (document.head || document.body || document.documentElement).appendChild(document.createElementNS('http://www.w3.org/1999/xhtml', 'style')).textContent = s;
73 |
74 | /* Recurse for frames and iframes. */
75 | try {
76 | Array.prototype.slice.call(document.querySelectorAll('frame, iframe, object[type^="text/html"], object[type^="application/xhtml+xml"]')).forEach(function (elem) {
77 | addcss(elem.contentDocument, s);
78 | });
79 | } catch (e) {
80 | /* Catch exceptions for out-of-domain access, but do not do anything with them. */
81 | }
82 | }
83 | })(document);
84 |
--------------------------------------------------------------------------------
/development/b64.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Convert plain text to Base64 and back. It determines which conversion to do.
3 | *
4 | * @title Base64
5 | */
6 | (function b64() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the text to encode/decode using Base64:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | var result, operation;
68 |
69 | /* The try/catch block wraps the atob() call and the fake exception to force btoa(). */
70 | try {
71 | /* A string "looks like Base64" if it:
72 | * - uses only the Base64 alphabet [A-Za-z0-9+/] (with optional trailing "=")
73 | * - has at least one uppercase character followed by a lowercase character
74 | * (or the other way around) other than at the beginning of the string.
75 | * This way, strings like "test" or "Hello", which are valid Base64 strings
76 | * will not be decoded, since they most likely are not really Base64 encoded.
77 | */
78 | if (!s.trim().match(/^[A-Za-z0-9+/]+([A-Z][a-z]|[a-z][A-Z])[A-Za-z0-9+/]*={0,2}$/)) {
79 | throw 'I guess this should be encoded, rather than encoded.';
80 | }
81 | s = s.trim();
82 | result = atob(s);
83 | operation = 'decoded';
84 | }
85 | catch (e) {
86 | result = btoa(s);
87 | operation = 'encoded';
88 | }
89 |
90 | var text = 'The Base64 ' + operation + ' string of "' + s + '" is:\n\n' + result;
91 |
92 | /* Replace the original document's HTML with our result. */
93 | HTMLDocument.prototype.open.call(document, 'text/plain; charset=UTF-8');
94 | HTMLDocument.prototype.write.call(document, text);
95 | HTMLDocument.prototype.close.call(document);
96 | }
97 | })();
98 |
--------------------------------------------------------------------------------
/development/html.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Render the specified or selected text as HTML.
3 | *
4 | * @title View as HTML
5 | */
6 | (function html() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter your HTML snippet:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | /* Replace the original document's HTML with the desired HTML. */
68 | HTMLDocument.prototype.open.call(document, 'text/html; charset=UTF-8');
69 | HTMLDocument.prototype.write.call(document, s);
70 | HTMLDocument.prototype.close.call(document);
71 | }
72 | })();
73 |
--------------------------------------------------------------------------------
/development/len.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Show the length of the given string.
3 | *
4 | * @title Show length
5 | */
6 | (function len() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter your string to measure:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | /* To count the number of characters, we cannot rely on String.length
68 | * because of astral chars. Use this code from BestieJS to deal with
69 | * those:
70 | * https://github.com/bestiejs/punycode.js/blob/8164242ef1/punycode.js#L99-126
71 | */
72 | var codePoints = [], counter = 0, length = s.length, value, extra;
73 | while (counter < length) {
74 | value = s.charCodeAt(counter++);
75 | if ((value & 0xF800) === 0xD800) {
76 | extra = s.charCodeAt(counter++);
77 | if ((value & 0xFC00) != 0xD800 || (extra & 0xFC00) != 0xDC00) {
78 | alert('Illegal UTF-16 sequence, but continuing anyway.');
79 | }
80 | value = ((value & 0x3FF) << 10) + (extra & 0x3FF) + 0x10000;
81 | }
82 | codePoints.push(value);
83 | }
84 | var numChars = codePoints.length;
85 |
86 | /* To count the number of bytes, we URL-encode the string so the
87 | * non-ASCII characters are encoded as sequences of %XX. We then
88 | * replace those triplets by a single character, "x", and count the
89 | * number of characters in the resulting string.
90 | */
91 | var numBytes = encodeURI(s).replace(/%../g, 'x').length;
92 |
93 | /* Shorten the string before displaying, if necessary. */
94 | var maxDisplayLength = 64;
95 | if (numChars > maxDisplayLength) {
96 | var encodeUtf16 = function (value) {
97 | var output = '';
98 | if ((value & 0xF800) == 0xD800) {
99 | alert('Invalid UTF-16 value, but continuing anyway.');
100 | }
101 | if (value > 0xFFFF) {
102 | value -= 0x10000;
103 | output += String.fromCharCode(value >>> 10 & 0x3FF | 0xD800);
104 | value = 0xDC00 | value & 0x3FF;
105 | }
106 | output += String.fromCharCode(value);
107 | return output;
108 | };
109 | s = codePoints.slice(0, maxDisplayLength / 2).map(encodeUtf16).join('')
110 | + '…'
111 | + codePoints.slice(numChars - maxDisplayLength / 2 + 1).map(encodeUtf16).join('');
112 | }
113 |
114 | var displayString = numChars === numBytes
115 | ? 'The number of characters in the ASCII string "' + s + '" is: '
116 | : 'The number of characters in the non-ASCII string "' + s + '" (' + numBytes + ' UTF-8 bytes) is: ';
117 | prompt(displayString, numChars);
118 | }
119 | })();
120 |
--------------------------------------------------------------------------------
/development/magic.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Use GCHQ’s CyberChef to magically determine what the input data is, e.g.
3 | * a Base64-encoded string of gzipped plaintext, a JSON Web Token, …
4 | *
5 | * By default, this bookmarklet tells CyberChef to only go two levels deep to
6 | * save time and energy.
7 | *
8 | * E.g. `magic H4sIAL8d32UAAyvJSFXIL8pMz8xLzFEoyEnMzCtJrSjRAwByt2jzFwAAAA`
9 | * will use CyberChef to produce this recipe:
10 | * 1) `From_Base64('A-Za-z0-9+/=',true,false)`
11 | * 2) `Gunzip()`
12 | * which leads to: `the original plaintext.`
13 | *
14 | * @title CyberChef Magic
15 | */
16 | (function magic(document) {
17 | 'use strict';
18 |
19 | /* Try to get the parameter string from the bookmarklet/search query.
20 | * Fall back to the current text selection, if any. If those options
21 | * both fail, prompt the user. */
22 | let s = (function () { /*%s*/; }).toString()
23 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
24 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
25 | .replace(/\u0025s/, '');
26 |
27 | /**
28 | * Get the active text selection, diving into frames and
29 | * text controls when necessary and possible.
30 | */
31 | function getActiveSelection(document) {
32 | if (!document || typeof document.getSelection !== 'function') {
33 | return '';
34 | }
35 |
36 | if (!document.activeElement) {
37 | return document.getSelection() + '';
38 | }
39 |
40 | const activeElement = document.activeElement;
41 |
42 | /* Recurse for FRAMEs and IFRAMEs. */
43 | try {
44 | if (
45 | typeof activeElement.contentDocument === 'object'
46 | && activeElement.contentDocument !== null
47 | ) {
48 | return getActiveSelection(activeElement.contentDocument);
49 | }
50 | } catch (e) {
51 | return document.getSelection() + '';
52 | }
53 |
54 | /* Get the selection from inside a text control. */
55 | if (typeof activeElement.value === 'string') {
56 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
57 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
58 | }
59 |
60 | return activeElement.value;
61 | }
62 |
63 | /* Get the normal selection. */
64 | return document.getSelection() + '';
65 | }
66 |
67 | if (s === '') {
68 | s = getActiveSelection(document) || prompt('Please enter your input data for CyberChef’s magic mode:');
69 | } else {
70 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection(document) + '$2');
71 | }
72 |
73 | if (s) {
74 | location = 'https://gchq.github.io/CyberChef/#recipe=Magic(2,false,false,%27%27)&input=' + encodeURIComponent(btoa(s).replace(/=*$/, ''));
75 | }
76 | })(document);
77 |
--------------------------------------------------------------------------------
/development/reconsole.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Restore window.console to its native state.
3 | *
4 | * @title Re-console
5 | */
6 | (function reconsole() {
7 | 'use strict';
8 |
9 | /* Sometimes all it takes to revert back to the original `console`, is to
10 | * delete the imposter. */
11 | delete window.console;
12 |
13 | /* But if that didn’t work, create an IFRAME and use its `console`. */
14 | if (!window.console) {
15 | const iframe = document.body.appendChild(document.createElement('iframe'));
16 | window.console = iframe.contentWindow.console;
17 | }
18 | })();
19 |
--------------------------------------------------------------------------------
/development/reloadcss.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Reload all external style sheets.
3 | *
4 | * @title Reload CSS
5 | */
6 | (function reloadcss() {
7 | /**
8 | * Reload the given style sheet by creating a new LINK element with the updated URL.
9 | *
10 | * @param mixed item Either a StyleSheet or a CSSRule; something with "href" and "media.mediaText".
11 | */
12 | function update(item) {
13 | if (item.disabled) {
14 | return;
15 | }
16 |
17 | var timestamp = +new Date() + '';
18 | var paramName = 'janbm-date', paramRegex = new RegExp('([?&])' + paramName + '=[0-9]{' + timestamp.length + '}\\b');
19 |
20 | /* Replace the previous timestamp query string parameter, if present. If not, add it. */
21 | var newHref = item.href.replace(paramRegex, '');
22 | if(!newHref.match(paramRegex)) {
23 | newHref += ~newHref.indexOf('?')
24 | ? '&' + paramName + '=' + timestamp
25 | : '?' + paramName + '=' + timestamp;
26 | }
27 |
28 | /* Get the full @media rule for the nested style. */
29 | var tmpItem = item;
30 | var allMedia = [];
31 | while (tmpItem) {
32 | tmpItem.media.mediaText && allMedia.unshift(tmpItem.media.mediaText);
33 | tmpItem = tmpItem.parentStyleSheet;
34 | }
35 |
36 | /* Reload the style sheet by creating a new LINK element with the updated URL. */
37 | var newStyleSheet = document.createElementNS('http://www.w3.org/1999/xhtml', 'link');
38 | newStyleSheet.rel = 'StyleSheet';
39 | newStyleSheet.media = allMedia.join(', ');
40 | newStyleSheet.href = newHref;
41 | (document.head || document.body || document.documentElement).appendChild(newStyleSheet);
42 | item.disabled = true;
43 | }
44 |
45 | Array.prototype.slice.call(document.styleSheets).forEach(function (styleSheet, i) {
46 | if (!styleSheet.href) {
47 | /* Inline style sheets can still refer to external style sheets using @import rules. */
48 | Array.prototype.slice.call(styleSheet.cssRules).forEach(function (cssRule) {
49 | if (cssRule.type === cssRule.IMPORT_RULE) {
50 | update(cssRule);
51 | }
52 | });
53 | return;
54 | }
55 |
56 | update(styleSheet);
57 | });
58 | })();
59 |
--------------------------------------------------------------------------------
/development/text.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Render the specified or selected text as plain text.
3 | *
4 | * @title View as text
5 | */
6 | (function text() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the text to show:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | /* Replace the original document's HTML with our text. */
68 | HTMLDocument.prototype.open.call(document, 'text/html; charset=UTF-8');
69 | HTMLDocument.prototype.write.call(document, '' + s);
70 | HTMLDocument.prototype.close.call(document);
71 | }
72 | })();
73 |
--------------------------------------------------------------------------------
/development/title.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Set the document title to the specified text.
3 | *
4 | * @title Set title
5 | */
6 | (function title() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the title:', document.title);
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s !== null) {
67 | document.title = s;
68 |
69 | /* Also update the og:title META tags. (Used by the “link” bookmarklet.) */
70 | Array.from(document.querySelectorAll('meta[property="og:title"], meta[property="twitter:title"]')).forEach(
71 | title => title.setAttribute('content', s)
72 | );
73 | }
74 | })();
75 |
--------------------------------------------------------------------------------
/development/urldec.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Decode all %XX bytes into a (hopefully) readable string.
3 | *
4 | * @title URL-decode
5 | */
6 | (function urldec() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the text to URL-decode:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | /* Replace the original document's HTML with our generated text. */
68 | HTMLDocument.prototype.open.call(document, 'text/plain; charset=UTF-8');
69 | HTMLDocument.prototype.write.call(document, decodeURIComponent(s));
70 | HTMLDocument.prototype.close.call(document);
71 | }
72 | })();
73 |
--------------------------------------------------------------------------------
/development/urlenc.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Change every character to its percent-encoded form (%XX), even if they are
3 | * URL-safe. (This makes "URL-encode" a bit of a misnomer.)
4 | *
5 | * I use this mainly for pranks. If I want to reply with a link to Google
6 | * Images, I will typically obfuscate the search term so as not to give it
7 | * away immediately. For example:
8 | * https://www.google.com/images?q=cool+story+bro
9 | * https://www.google.com/images?q=%63%6F%6F%6C%20%73%74%6F%72%79%20%62%72%6F
10 | *
11 | * @title URL-encode
12 | */
13 | (function urlenc() {
14 | /* Try to get the parameter string from the bookmarklet/search query.
15 | Fall back to the current text selection, if any. If those options
16 | both fail, prompt the user.
17 | */
18 | var s = (function () { /*%s*/; }).toString()
19 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
20 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
21 | .replace(/\u0025s/, '');
22 |
23 | /**
24 | * Get the active text selection, diving into frames and
25 | * text controls when necessary and possible.
26 | */
27 | function getActiveSelection(doc) {
28 | if (arguments.length === 0) {
29 | doc = document;
30 | }
31 |
32 | if (!doc || typeof doc.getSelection !== 'function') {
33 | return '';
34 | }
35 |
36 | if (!doc.activeElement) {
37 | return doc.getSelection() + '';
38 | }
39 |
40 | var activeElement = doc.activeElement;
41 |
42 | /* Recurse for FRAMEs and IFRAMEs. */
43 | try {
44 | if (
45 | typeof activeElement.contentDocument === 'object'
46 | && activeElement.contentDocument !== null
47 | ) {
48 | return getActiveSelection(activeElement.contentDocument);
49 | }
50 | } catch (e) {
51 | return doc.getSelection() + '';
52 | }
53 |
54 | /* Get the selection from inside a text control. */
55 | if (typeof activeElement.value === 'string') {
56 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
57 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
58 | }
59 |
60 | return activeElement.value;
61 | }
62 |
63 | /* Get the normal selection. */
64 | return doc.getSelection() + '';
65 | }
66 |
67 | if (s === '') {
68 | s = getActiveSelection() || prompt('Please enter the text to URL-encode:');
69 | } else {
70 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
71 | }
72 |
73 | if (s) {
74 | s = s.split('').map(function (c) {
75 | return '%' + ('0' + c.charCodeAt(0).toString(16)).slice(-2);
76 | }).join('').toUpperCase();
77 |
78 | /* Replace the original document's HTML with our generated text. */
79 | HTMLDocument.prototype.open.call(document, 'text/plain; charset=UTF-8');
80 | HTMLDocument.prototype.write.call(document, s);
81 | HTMLDocument.prototype.close.call(document);
82 | }
83 | })();
84 |
--------------------------------------------------------------------------------
/forms/README:
--------------------------------------------------------------------------------
1 | Forms
2 |
3 | Manipulate HTML forms.
4 |
--------------------------------------------------------------------------------
/forms/checkpass.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Check whether password and probable password confirmation INPUTs have the
3 | * same value.
4 | *
5 | * @title Check passwords
6 | */
7 | (function checkpass() {
8 | "use strict";
9 |
10 | function execute(document) {
11 | let needsStyleSheet = false;
12 |
13 | Array.from(document.querySelectorAll('form input[type="password"], form input[autocomplete="new-password"]')).forEach(input => {
14 | if (input.form.xxxJanHasCheckpass) {
15 | return;
16 | }
17 |
18 | /* Make sure there are at least two password INPUTs. If there
19 | * are two inputs (regardless of their INPUT@type) having the
20 | * INPUT@autocomplete attribute set to `new-password`, we use
21 | * those two.
22 | *
23 | * Otherwise, look for inputs whose INPUT@type is `password`.
24 | * If there are more than two, assume only the last two to be
25 | * “linked”. For instance, on a form to change your password,
26 | * there are typically three password INPUTs: your current
27 | * password, the new password, and a confirmation for the new
28 | * password. On a registration form, there are typically just
29 | * two password INPUTs, one for the password, and one for the
30 | * confirmation. */
31 | let allPasswordInputs = Array.from(input.form.querySelectorAll('input[autocomplete="new-password"]'));
32 | if (allPasswordInputs.length < 2) {
33 | allPasswordInputs = Array.from(input.form.querySelectorAll('input[type="password"]'));
34 | }
35 |
36 | if (allPasswordInputs.length < 2) {
37 | return;
38 | }
39 |
40 | let firstIndex = allPasswordInputs.length - 2;
41 | let secondIndex = allPasswordInputs.length - 1;
42 | function comparePasswords() {
43 | if (allPasswordInputs[firstIndex].value === allPasswordInputs[secondIndex].value) {
44 | allPasswordInputs[firstIndex].classList.remove('xxxJanPasswordMismatch');
45 | allPasswordInputs[secondIndex].classList.remove('xxxJanPasswordMismatch');
46 | } else {
47 | allPasswordInputs[secondIndex].classList.add('xxxJanPasswordMismatch');
48 | allPasswordInputs[firstIndex].classList.add('xxxJanPasswordMismatch');
49 | }
50 | }
51 |
52 | allPasswordInputs[firstIndex].addEventListener('input', comparePasswords);
53 | allPasswordInputs[secondIndex].addEventListener('input', comparePasswords);
54 | comparePasswords();
55 |
56 | input.form.xxxJanHasCheckpass = true;
57 |
58 | needsStyleSheet = true;
59 | });
60 |
61 | /* Add the style sheet for the (mis)matching password INPUTs. */
62 | if (needsStyleSheet) {
63 | let styleSheet = document.getElementById('xxxJanCheckpassCss');
64 | if (!styleSheet) {
65 | styleSheet = document.createElementNS('http://www.w3.org/1999/xhtml', 'style');
66 | styleSheet.id = 'xxxJanCheckpassCss';
67 | styleSheet.textContent = `
68 | .xxxJanPasswordMismatch {
69 | box-shadow: none !important;
70 | background: #f44 !important;
71 | color: #fff !important;
72 | }
73 | `;
74 | document.head.appendChild(styleSheet);
75 | }
76 | }
77 |
78 | /* Recurse for (i)frames. */
79 | try {
80 | Array.from(document.querySelectorAll('frame, iframe, object[type^="text/html"], object[type^="application/xhtml+xml"]')).forEach(
81 | elem => { try { execute(elem.contentDocument) } catch (e) { } }
82 | );
83 | } catch (e) {
84 | /* Catch and ignore exceptions for out-of-domain access. */
85 | }
86 | }
87 |
88 | execute(document);
89 | })();
90 |
--------------------------------------------------------------------------------
/forms/frmblank.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Make all forms open in a new window/tab.
3 | *
4 | * @title Form _blank
5 | */
6 | (function frmblank(document) {
7 | Array.prototype.slice.call(document.forms || document.getElementsByTagName('form')).forEach(function (form) {
8 | form.target = '_blank';
9 | Array.prototype.slice.call(form.querySelectorAll('input[type="submit"], input[type="image"], button:not([type]), button[type="submit"]')).forEach(function (submit) {
10 | submit.parentNode.insertBefore(document.createTextNode(' [_blank]'), submit.nextSibling);
11 | });
12 | });
13 |
14 | /* Recurse for frames and iframes. */
15 | try {
16 | Array.prototype.slice.call(document.querySelectorAll('frame, iframe, object[type^="text/html"], object[type^="application/xhtml+xml"]')).forEach(function (elem) {
17 | frmblank(elem.contentDocument);
18 | });
19 | } catch (e) {
20 | /* Catch exceptions for out-of-domain access, but do not do anything with them. */
21 | }
22 | })(document);
23 |
--------------------------------------------------------------------------------
/forms/frmcomp.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Enable autocompletion on all forms and elements.
3 | *
4 | * @title Enable autocomplete
5 | */
6 | (function frmcomp(document) {
7 | [].slice.call(document.forms).forEach(function (form) {
8 | if (form.autocomplete === '' || form.autocomplete === 'off') {
9 | console.log('Enable autocomplete: enabling on form: ', form);
10 | form.autocomplete = 'on';
11 | }
12 |
13 | [].slice.call(form.elements).forEach(function (element) {
14 | if (element.autocomplete === '' || element.autocomplete === 'off') {
15 | console.log('Enable autocomplete: enabling on element: ', element);
16 | element.autocomplete = 'on';
17 | }
18 | });
19 | });
20 |
21 | /* Recurse for frames and iframes. */
22 | try {
23 | [].slice.call(document.querySelectorAll('frame, iframe, object[type^="text/html"], object[type^="application/xhtml+xml"]')).forEach(function (elem) {
24 | autocomp(elem.contentDocument);
25 | });
26 | } catch (e) {
27 | /* Catch exceptions for out-of-domain access, but do not do anything with them. */
28 | }
29 | })(document);
30 |
--------------------------------------------------------------------------------
/forms/frmfill.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Fill the text inputs with their label contents, their placeholders, titles,
3 | * names or IDs. Fill other, more specialised inputs, with “sensible” defaults.
4 | *
5 | * @title Form fill
6 | */
7 | (function frmfill() {
8 | /* See if there are options specified as the parameter to the bookmarklet. */
9 | let s = (function () { /*%s*/; }).toString()
10 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
11 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
12 | .replace(/\u0025s/, '');
13 |
14 | /* “Be liberal in what you accept”: “--only-fill required only” is fine, too. :-) */
15 | let shouldOnlyFillRequired = s.match(/^(--)?(only[ -])?(fill[ -])?required([ -]only)?$/);
16 |
17 | function execute(document) {
18 | Array.from(document.querySelectorAll('input, textarea, select')).forEach(input => {
19 | /* If the input already has a value, bail out. */
20 | if (input.value !== '') {
21 | return;
22 | }
23 |
24 | /* If the input is not required, and we should only fill required inputs, bail out. */
25 | if (shouldOnlyFillRequired && !(input.required || input.className.match(/required/i))) {
26 | return;
27 | }
28 |
29 | /* “Difficult” input types: do not try to do anything. */
30 | if (['hidden', 'file', 'password', 'color'].indexOf(input.type) > -1) {
31 | return;
32 | }
33 |
34 | /* Checkboxes and radio buttons: check. */
35 | if (input.type === 'checkbox' || input.type === 'radio') {
36 | input.checked = true;
37 | return;
38 | }
39 |
40 | /* E-mail inputs: use the host name for a throwaway e-mail address at mailinator.com (using a less common alias). */
41 | if (input.type === 'email' || [input.name, input.id, input.title, input.placeholder].join(' ').match(/\be-?mail\b/i)) {
42 | input.value = location.hostname.replace(/^www\./, '') + '@veryrealemail.com';
43 | return;
44 | }
45 |
46 | /* Numeric inputs: use the lowest allowed number (or 1). */
47 | if (input.type === 'number' || input.type === 'range') {
48 | input.value = input.min === ''
49 | ? 1
50 | : input.min;
51 | return;
52 | }
53 |
54 | /* Date/datetime inputs: use the current date/datetime. */
55 | if (input.type === 'date') {
56 | input.valueAsDate = new Date();
57 | return;
58 | }
59 |
60 | if (input.type === 'datetime-local' || input.type === 'datetime') {
61 | input.value = new Date().toISOString().replace(/\..*$/, '');
62 | return;
63 | }
64 |
65 | /* Time inputs: use the lowest allowed time (or noon). */
66 | if (input.type === 'time') {
67 | input.value = input.min === ''
68 | ? '12:00'
69 | : input.min;
70 | return;
71 | }
72 |
73 | /* All other inputs: use the label, if any. */
74 | if (input.labels && input.labels[0]) {
75 | input.value = input.labels[0].textContent
76 | .trim()
77 | /* Get rid of the common “*” required indicator. */
78 | .replace(/(^\*\s*)|(\s*\*$)/, '')
79 | /* Get rid of the trailing colon in “Label text here:”. */
80 | .replace(/\s*:$/, '');
81 |
82 | if (input.value !== '') {
83 | return;
84 | }
85 | }
86 |
87 | /* In case there is no label, fall back to other attributes (in decreasing order of usefulness). */
88 | var attributes = [
89 | 'placeholder',
90 | 'title',
91 | 'name',
92 | 'id'
93 | ];
94 |
95 | for (var i = 0; i < attributes.length; i++) {
96 | var attribute = attributes[i];
97 | if (input[attribute]) {
98 | input.value = input[attribute];
99 | return;
100 | }
101 | }
102 | });
103 |
104 | /* Recurse for (i)frames. */
105 | try {
106 | Array.from(document.querySelectorAll('frame, iframe, object[type^="text/html"], object[type^="application/xhtml+xml"]')).forEach(
107 | elem => { try { execute(elem.contentDocument) } catch (e) { } }
108 | );
109 | } catch (e) {
110 | /* Catch and ignore exceptions for out-of-domain access. */
111 | }
112 | }
113 |
114 | execute(document);
115 | })();
116 |
--------------------------------------------------------------------------------
/forms/frmget.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Make all forms use GET.
3 | *
4 | * @title Form GET
5 | */
6 | (function frmget(document) {
7 | Array.prototype.slice.call(document.forms || document.getElementsByTagName('form')).forEach(function (form) {
8 | form.method = 'get';
9 | Array.prototype.slice.call(form.querySelectorAll('input[type="submit"], input[type="image"], button:not([type]), button[type="submit"]')).forEach(function (submit) {
10 | submit.parentNode.insertBefore(document.createTextNode(' [GET]'), submit.nextSibling);
11 | });
12 | });
13 |
14 | /* Recurse for frames and iframes. */
15 | try {
16 | Array.prototype.slice.call(document.querySelectorAll('frame, iframe, object[type^="text/html"], object[type^="application/xhtml+xml"]')).forEach(function (elem) {
17 | frmget(elem.contentDocument);
18 | });
19 | } catch (e) {
20 | /* Catch exceptions for out-of-domain access, but do not do anything with them. */
21 | }
22 | })(document);
23 |
--------------------------------------------------------------------------------
/forms/frmpost.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Make all forms use POST.
3 | *
4 | * @title Form POST
5 | */
6 | (function frmpost(document) {
7 | Array.prototype.slice.call(document.forms || document.getElementsByTagName('form')).forEach(function (form) {
8 | form.method = 'post';
9 | Array.prototype.slice.call(form.querySelectorAll('input[type="submit"], input[type="image"], button:not([type]), button[type="submit"]')).forEach(function (submit) {
10 | submit.parentNode.insertBefore(document.createTextNode(' [POST]'), submit.nextSibling);
11 | });
12 | });
13 |
14 | /* Recurse for frames and iframes. */
15 | try {
16 | Array.prototype.slice.call(document.querySelectorAll('frame, iframe, object[type^="text/html"], object[type^="application/xhtml+xml"]')).forEach(function (elem) {
17 | frmpost(elem.contentDocument);
18 | });
19 | } catch (e) {
20 | /* Catch exceptions for out-of-domain access, but do not do anything with them. */
21 | }
22 | })(document);
23 |
--------------------------------------------------------------------------------
/forms/showpass.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Convert password inputs to normal text inputs and back again.
3 | *
4 | * @title Show passwords
5 | */
6 | (function showpass(document) {
7 | Array.prototype.slice.call(document.querySelectorAll('input:not([type]), input[type="text"], input[type="password"]')).forEach(function (input) {
8 | if (input.type === 'password') {
9 | input.wasPassword = true;
10 | input.type = 'text';
11 | } else if (input.wasPassword) {
12 | input.type = 'password';
13 | }
14 | });
15 |
16 | /* Recurse for frames and iframes. */
17 | try {
18 | Array.prototype.slice.call(document.querySelectorAll('frame, iframe, object[type^="text/html"], object[type^="application/xhtml+xml"]')).forEach(function (elem) {
19 | showpass(elem.contentDocument);
20 | });
21 | } catch (e) {
22 | /* Catch exceptions for out-of-domain access, but do not do anything with them. */
23 | }
24 | })(document);
25 |
--------------------------------------------------------------------------------
/language/README:
--------------------------------------------------------------------------------
1 | Language
2 |
3 | Dictionaries, translators, …
4 |
--------------------------------------------------------------------------------
/language/dictionaries/README:
--------------------------------------------------------------------------------
1 | Dictionaries
2 |
--------------------------------------------------------------------------------
/language/dictionaries/ac.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text in the Arch Chinese dictionary.
3 | *
4 | * @title Arch Chinese
5 | */
6 | (function ac() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the word(s) to look up in the Arch Chinese dictionary:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | location = 'https://www.archchinese.com/chinese_english_dictionary.html?find=' + encodeURIComponent(s);
68 | }
69 | })();
70 |
--------------------------------------------------------------------------------
/language/dictionaries/dewikt.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text in the German Wiktionary.
3 | *
4 | * @title German Wiktionary
5 | */
6 | (function dewikt() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the word(s) to look up in the German Wiktionary:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | location = 'https://de.wiktionary.org/wiki/' + encodeURIComponent(s);
68 | }
69 | })();
70 |
--------------------------------------------------------------------------------
/language/dictionaries/dict.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text on Dictionary.com.
3 | *
4 | * @title Dictionary.com
5 | */
6 | (function dict() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the word(s) to look up on Dictionary.com:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | location = 'https://www.dictionary.com/browse/' + encodeURIComponent(s);
68 | }
69 | })();
70 |
--------------------------------------------------------------------------------
/language/dictionaries/enwikt.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text in the English Wiktionary.
3 | *
4 | * @title English Wiktionary
5 | */
6 | (function enwikt() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the word(s) to look up in the English Wiktionary:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | location = 'https://en.wiktionary.org/wiki/' + encodeURIComponent(s);
68 | }
69 | })();
70 |
--------------------------------------------------------------------------------
/language/dictionaries/eswikt.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text in the Spanish Wiktionary.
3 | *
4 | * @title Spanish Wiktionary
5 | */
6 | (function eswikt() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the word(s) to look up in the Spanish Wiktionary:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | location = 'https://es.wiktionary.org/wiki/' + encodeURIComponent(s);
68 | }
69 | })();
70 |
--------------------------------------------------------------------------------
/language/dictionaries/frwikt.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text in the French Wiktionary.
3 | *
4 | * @title French Wiktionary
5 | */
6 | (function frwikt() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the word(s) to look up in the French Wiktionary:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | location = 'https://fr.wiktionary.org/wiki/' + encodeURIComponent(s);
68 | }
69 | })();
70 |
--------------------------------------------------------------------------------
/language/dictionaries/itwikt.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text in the Italian Wiktionary.
3 | *
4 | * @title Italian Wiktionary
5 | */
6 | (function itwikt() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the word(s) to look up in the Italian Wiktionary:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | location = 'https://it.wiktionary.org/wiki/' + encodeURIComponent(s);
68 | }
69 | })();
70 |
--------------------------------------------------------------------------------
/language/dictionaries/mw.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text using Merriam-Webster.
3 | *
4 | * @title Merriam-Webster
5 | */
6 | (function mw() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the word(s) to look up using Merriam-Webster:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | location = 'https://www.merriam-webster.com/dictionary/' + encodeURIComponent(s);
68 | }
69 | })();
70 |
--------------------------------------------------------------------------------
/language/dictionaries/nlwikt.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text in the Dutch Wiktionary.
3 | *
4 | * @title Dutch Wiktionary
5 | */
6 | (function nlwikt() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the word(s) to look up in the Dutch Wiktionary:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | location = 'https://nl.wiktionary.org/wiki/' + encodeURIComponent(s);
68 | }
69 | })();
70 |
--------------------------------------------------------------------------------
/language/dictionaries/nowikt.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text in the Norwegian Wiktionary.
3 | *
4 | * @title Norwegian Wiktionary
5 | */
6 | (function nowikt() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the word(s) to look up in the Norwegian Wiktionary:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | location = 'https://no.wiktionary.org/wiki/' + encodeURIComponent(s);
68 | }
69 | })();
70 |
--------------------------------------------------------------------------------
/language/dictionaries/oed.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text in the Oxford English dictionary.
3 | *
4 | * @title O.E.D.
5 | */
6 | (function oed() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the word(s) to look up in the Oxford English dictionary:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | location = 'https://en.oxforddictionaries.com/definition/' + encodeURIComponent(s);
68 | }
69 | })();
70 |
--------------------------------------------------------------------------------
/language/dictionaries/ptwikt.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text in the Portuguese Wiktionary.
3 | *
4 | * @title Portuguese Wiktionary
5 | */
6 | (function ptwikt() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the word(s) to look up in the Portuguese Wiktionary:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | location = 'https://pt.wiktionary.org/wiki/' + encodeURIComponent(s);
68 | }
69 | })();
70 |
--------------------------------------------------------------------------------
/language/dictionaries/ruwikt.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text in the Russian Wiktionary.
3 | *
4 | * @title Russian Wiktionary
5 | */
6 | (function ruwikt() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the word(s) to look up in the Russian Wiktionary:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | location = 'https://ru.wiktionary.org/wiki/' + encodeURIComponent(s);
68 | }
69 | })();
70 |
--------------------------------------------------------------------------------
/language/dictionaries/svwikt.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text in the Swedish Wiktionary.
3 | *
4 | * @title Swedish Wiktionary
5 | */
6 | (function svwikt() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the word(s) to look up in the Swedish Wiktionary:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | location = 'https://sv.wiktionary.org/wiki/' + encodeURIComponent(s);
68 | }
69 | })();
70 |
--------------------------------------------------------------------------------
/language/dictionaries/thes.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text on Thesaurus.com.
3 | *
4 | * @title Thesaurus.com
5 | */
6 | (function thes() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the word(s) to look up on Thesaurus.com:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | location = 'https://www.thesaurus.com/browse/' + encodeURIComponent(s);
68 | }
69 | })();
70 |
--------------------------------------------------------------------------------
/language/dictionaries/ud.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text in the Urban Dictionary.
3 | *
4 | * @title Urban Dictionary
5 | */
6 | (function ud() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the word(s) to look up in the Urban Dictionary:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | location = 'https://www.urbandictionary.com/define.php?term=' + encodeURIComponent(s);
68 | }
69 | })();
70 |
--------------------------------------------------------------------------------
/language/dictionaries/vd.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text in the Dutch Van Dale dictionary.
3 | *
4 | * @title Van Dale
5 | */
6 | (function vd() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the word(s) to look up in the Dutch Van Dale dictionary:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | location = 'https://www.vandale.nl/gratis-woordenboek/nederlands/betekenis/' + encodeURIComponent(s);
68 | }
69 | })();
70 |
--------------------------------------------------------------------------------
/language/dictionaries/viwikt.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text in the Vietnamese Wiktionary.
3 | *
4 | * @title Vietnamese Wiktionary
5 | */
6 | (function viwikt() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the word(s) to look up in the Vietnamese Wiktionary:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | location = 'https://vi.wiktionary.org/wiki/' + encodeURIComponent(s);
68 | }
69 | })();
70 |
--------------------------------------------------------------------------------
/language/dictionaries/vw.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text in the “Flemish” dictionary.
3 | *
4 | * @title Vlaams Woordenboek
5 | */
6 | (function vw() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the word(s) to look up in the “Flemish” dictionary:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | location = 'https://www.vlaamswoordenboek.be/definities/search?definition[q]=' + encodeURIComponent(s);
68 | }
69 | })();
70 |
--------------------------------------------------------------------------------
/language/dictionaries/zhwikt.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text in the (Mandarin) Chinese Wiktionary.
3 | *
4 | * @title (Mandarin) Chinese Wiktionary
5 | */
6 | (function zhwikt() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the word(s) to look up in the (Mandarin) Chinese Wiktionary:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | location = 'https://zh.wiktionary.org/wiki/' + encodeURIComponent(s);
68 | }
69 | })();
70 |
--------------------------------------------------------------------------------
/language/shuo.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Use Naver’s text-to-speech on the selected (Mandarin Chinese) text.
3 | *
4 | * @title Shuō (说)
5 | */
6 | (function shuo() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the text to speak:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | var mp3Url = 'http://tts.cndic.naver.com/tts/mp3ttsV1.cgi?spk_id=250&text_fmt=0&pitch=100&volume=200&speed=80&wrapper=0&enc=0&text=' + encodeURI(s);
68 | new Audio(mp3Url).play().catch(error => alert('Could not play Naver’s text-to-speech. This can have many causes, including ad and tracker blockers.\n\nError: ' + error + '\n\nOriginal text:\n' + s));
69 | }
70 | })();
71 |
--------------------------------------------------------------------------------
/language/translations/README:
--------------------------------------------------------------------------------
1 | Translators
2 |
--------------------------------------------------------------------------------
/navigation/README:
--------------------------------------------------------------------------------
1 | Navigation
2 |
3 | Get around easier.
4 |
--------------------------------------------------------------------------------
/navigation/back.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Go back to the previous page, or, failing that, to the referring page.
3 | *
4 | * @title Go back
5 | */
6 | (function back() {
7 | if (history.length > 1) {
8 | history.back();
9 | /* Go to the referrer when back() did not seem to have worked. */
10 | window.setTimeout(goToReferrer, 250);
11 | } else {
12 | goToReferrer();
13 | }
14 |
15 | function goToReferrer() {
16 | if (document.referrer) {
17 | location = document.referrer;
18 | }
19 | }
20 | })();
21 |
--------------------------------------------------------------------------------
/navigation/linktitles.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Add the links' HREFs to their tooltips.
3 | *
4 | * @title Add link titles
5 | */
6 | (function linktitles() {
7 | Array.prototype.slice.call(document.links).forEach(function (link) {
8 | if (link.title.indexOf(link.href) < 0) {
9 | link.title = link.title
10 | ? link.title + ' [' + link.href + ']'
11 | : link.href;
12 | }
13 | });
14 | })();
15 |
--------------------------------------------------------------------------------
/navigation/refer.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Go to the specified or selected URL using the current page as the referrer.
3 | *
4 | * @title Surf with referrer
5 | */
6 | (function refer() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the destination URL:', location);
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | location = s;
68 | }
69 | })();
70 |
--------------------------------------------------------------------------------
/navigation/relink.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Replace all external links with new “A” elements with the same @href,
3 | * @class and inner HTML content, but without any previously attached event
4 | * handlers.
5 | *
6 | * Mainly useful for Google search result pages when trying to copy links
7 | * directly off those pages, so Google does not obfuscate them with tracker
8 | * garbage (which happens on click, before the link URL has been copied).
9 | *
10 | * @title Re-link
11 | */
12 | (function relink() {
13 | 'use strict';
14 |
15 | /* Recursively execute the logic on the document and its sub-documents. */
16 | function execute(document) {
17 | let thisDomain = location.protocol + '//' + location.hostname + '/';
18 | Array.from(document.querySelectorAll('a[href]:not([href^="/"]):not([href^="' + thisDomain + '"])')).forEach(a => {
19 | let newA = document.createElementNS('http://www.w3.org/1999/xhtml', 'a');
20 | newA.href = a.href;
21 | newA.setAttribute('class', a.getAttribute('class'));
22 | newA.innerHTML = a.innerHTML;
23 | a.replaceWith(newA);
24 | console.log('relink: Replaced', a, 'with', newA);
25 | });
26 |
27 | /* Recurse for (i)frames. */
28 | try {
29 | Array.from(document.querySelectorAll('frame, iframe, object[type^="text/html"], object[type^="application/xhtml+xml"]')).forEach(
30 | elem => { try { execute(elem.contentDocument) } catch (e) { } }
31 | );
32 | } catch (e) {
33 | /* Catch and ignore exceptions for out-of-domain access. */
34 | }
35 | }
36 |
37 | execute(document);
38 | })();
39 |
--------------------------------------------------------------------------------
/navigation/rmh.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Remove the hash from the current page's URL, but keep the query string.
3 | *
4 | * @title Remove hash
5 | */
6 | (function rmh() {
7 | var oldLocation = ('' + location);
8 | var newLocation = oldLocation.replace(/#.*/, '');
9 |
10 | if (newLocation !== oldLocation) {
11 | /* See if the user wants to replace the URL without reloading. */
12 | var s = (function () { /*%s*/; }).toString()
13 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
14 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
15 | .replace(/\u0025s/, '');
16 | if ((' ' + s + ' ').match(/ --(no|skip)-reload /)) {
17 | history.pushState({}, document.title, newLocation);
18 | } else {
19 | location = newLocation;
20 | }
21 | }
22 | })();
23 |
--------------------------------------------------------------------------------
/navigation/rmhq.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Remove the hash and query string from the current page's URL.
3 | *
4 | * This is the same as "rmqh".
5 | *
6 | * @title Remove hash and query
7 | */
8 | (function rmhq() {
9 | var oldLocation = ('' + location);
10 | var newLocation = oldLocation.replace(/[#?].*/, '');
11 |
12 | if (newLocation !== oldLocation) {
13 | /* See if the user wants to replace the URL without reloading. */
14 | var s = (function () { /*%s*/; }).toString()
15 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
16 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
17 | .replace(/\u0025s/, '');
18 | if ((' ' + s + ' ').match(/ --(no|skip)-reload /)) {
19 | history.pushState({}, document.title, newLocation);
20 | } else {
21 | location = newLocation;
22 | }
23 | }
24 | })();
25 |
--------------------------------------------------------------------------------
/navigation/rmq.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Remove the query string from the current page's URL, but keep the hash.
3 | *
4 | * @title Remove query
5 | */
6 | (function rmq() {
7 | var oldLocation = ('' + location);
8 | var newLocation = oldLocation.replace(/^([^#]*)\?[^#]*(#.*)?/, '$1$2');
9 |
10 | if (newLocation !== oldLocation) {
11 | /* See if the user wants to replace the URL without reloading. */
12 | var s = (function () { /*%s*/; }).toString()
13 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
14 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
15 | .replace(/\u0025s/, '');
16 | if ((' ' + s + ' ').match(/ --(no|skip)-reload /)) {
17 | history.pushState({}, document.title, newLocation);
18 | } else {
19 | location = newLocation;
20 | }
21 | }
22 | })();
23 |
--------------------------------------------------------------------------------
/navigation/rmqh.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Remove the query string and hash from the current page's URL.
3 | *
4 | * This is the same as "rmhq".
5 | *
6 | * @title Remove query and hash
7 | */
8 | (function rmqh() {
9 | var oldLocation = ('' + location);
10 | var newLocation = oldLocation.replace(/[#?].*/, '');
11 |
12 | if (newLocation !== oldLocation) {
13 | /* See if the user wants to replace the URL without reloading. */
14 | var s = (function () { /*%s*/; }).toString()
15 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
16 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
17 | .replace(/\u0025s/, '');
18 | if ((' ' + s + ' ').match(/ --(no|skip)-reload /)) {
19 | history.pushState({}, document.title, newLocation);
20 | } else {
21 | location = newLocation;
22 | }
23 | }
24 | })();
25 |
--------------------------------------------------------------------------------
/navigation/root.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Go to the root directory, or the Nth directory starting from the root.
3 | *
4 | * For example, when you are on "https://www.example.com/foo/bar/baz":
5 | * - executing "/" goes to "https://www.example.com/"
6 | * - executing "/ 1" goes to "https://www.example.com/foo/"
7 | * - executing "/ 2" goes to "https://www.example.com/foo/bar/"
8 | * - executing "/ quux" goes to "https://www.example.com/quux"
9 | *
10 | * @title Go to the root
11 | * @keyword /
12 | */
13 | (function () {
14 | /* Try to get the parameter string from the bookmarklet/search query. */
15 | var s = (function () { /*%s*/; }).toString()
16 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
17 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
18 | .replace(/\u0025s/, '');
19 |
20 | var level = parseInt(s, 10);
21 | if (s !== '') {
22 | if (isNaN(level)) {
23 | return location = '/' + s;
24 | } else {
25 | level = Math.max(0, level || 0);
26 | }
27 | }
28 |
29 | var parts = document.location.pathname.split('/');
30 | var newParts = parts.slice(0, (level || 0) + 1);
31 | if (newParts.length < parts.length) {
32 | newParts.push('');
33 | }
34 | location = newParts.join('/');
35 | })();
36 |
--------------------------------------------------------------------------------
/navigation/unarchive.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Rewrite links to the Internet Archive Wayback Machine’s saved pages back to
3 | * the original URIs.
4 | *
5 | * @title Unarchive Wayback Machine links
6 | */
7 | (function unarchive() {
8 | 'use strict';
9 |
10 | /* Recursively execute the logic on the document and its sub-documents. */
11 | function execute(document) {
12 | const isOnArchiveDotOrg = document.location.host === 'web.archive.org';
13 | let wbASelectors;
14 |
15 | if (isOnArchiveDotOrg) {
16 | wbASelectors = [
17 | /* The Wayback Machine does not rewrite *all* HREF attributes
18 | * in the HTML source. Relative HREFs are left alone, e.g. on
19 | * :
20 | *
21 | * ``
22 | *
23 | * vs.
24 | *
25 | * ``
26 | *
27 | * So we have to check the HREF for *every* A element to get its
28 | * resolved URI.
29 | */
30 | 'a[href]'
31 | ];
32 | } else {
33 | wbASelectors = [
34 | 'a[href^="//web.archive.org/web/"]',
35 | 'a[href^="http://web.archive.org/web/"]',
36 | 'a[href^="https://web.archive.org/web/"]'
37 | ];
38 | }
39 |
40 | /* Wombat (the Wayback Machine’s JS library) dynamically rewrites URIs by
41 | * intercepting calls to `{get,set}Attribute('href')` and the `a.href` getter
42 | * and setter. However, calls to `setAttributeNS` are *not* intercepted. Take
43 | * advantage of the `a.href` interceptor that returns the resolved original URI
44 | * and use `setAttributeNS` to override the Wayback Machine’s rewritten HREF.
45 | *
46 | * On pages outside of web.archive.org, `a.href` returns the full archive.org
47 | * URI, so we have to strip it ourselves.
48 | */
49 | Array.from(document.querySelectorAll(wbASelectors.join(', '))).forEach(a => {
50 | let originalUri = a.href;
51 |
52 | if (!isOnArchiveDotOrg) {
53 | originalUri = originalUri.replace(/^https?\:\/\/web.archive\.org\/web\/([^\/]+\/)?(https?:\/\/.*)/, '$2');
54 | }
55 |
56 | a.setAttributeNS('', 'href', originalUri);
57 | });
58 |
59 | /* Recurse for (i)frames. */
60 | try {
61 | Array.from(document.querySelectorAll('frame, iframe, object[type^="text/html"], object[type^="application/xhtml+xml"]')).forEach(
62 | elem => { try { execute(elem.contentDocument) } catch (e) { } }
63 | );
64 | } catch (e) {
65 | /* Catch and ignore exceptions for out-of-domain access. */
66 | }
67 | }
68 |
69 | execute(document);
70 | })();
71 |
--------------------------------------------------------------------------------
/navigation/up.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Go to the parent "directory". Note that this function tries to be somewhat
3 | * smart about it:
4 | * - If the path ends in a slash, go to the parent directory.
5 | * - If the path looks like the default index, go to the parent directory and
6 | * use the same filename.
7 | * - For all other paths, go to the containing directory.
8 | *
9 | * For example:
10 | * - "/foo/bar/baz/" becomes "/foo/bar/"
11 | * - "/foo/bar/baz/index.html" becomes "/foo/bar/index.html"
12 | * - "/foo/bar/baz" becomes "/foo/bar/" (which in turn will become "/foo/")
13 | *
14 | * @title Go up
15 | * @keyword ..
16 | */
17 | (function () {
18 | var parts = location.pathname.split('/');
19 | if (parts.length === 2) {
20 | /* If we are in a leaf of the root, always go to "/". This way, */
21 | /* /foo/index.html will go to /index.html, but /index.html will */
22 | /* go to /. */
23 | parts[parts.length - 1] = '';
24 | } else if (parts[parts.length - 1] === '' ||
25 | parts[parts.length - 1].match(/^(default|index)(\..*)?$/)) {
26 | /* Move the (posibly empty) index filename up one level. */
27 | parts[parts.length - 2] = parts.pop();
28 | } else {
29 | /* Remove the last leaf. */
30 | parts[parts.length - 1] = '';
31 | }
32 | location = parts.join('/');
33 | })();
34 |
--------------------------------------------------------------------------------
/search/README:
--------------------------------------------------------------------------------
1 | Search engines
2 |
--------------------------------------------------------------------------------
/search/bimg.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Search Bing Images. For reverse image search, specify the URL as the first parameter.
3 | *
4 | * @title Bing Images
5 | */
6 | (function bimg() {
7 | 'use strict';
8 |
9 | /* Try to get the parameter string from the bookmarklet/search query.
10 | * Fall back to the current text selection, if any. If those options
11 | * both fail, prompt the user. */
12 | let s = (function () { /*%s*/; }).toString()
13 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
14 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
15 | .replace(/\u0025s/, '');
16 |
17 | /**
18 | * Get the active text selection, diving into frames and
19 | * text controls when necessary and possible.
20 | */
21 | function getActiveSelection(document) {
22 | if (!document || typeof document.getSelection !== 'function') {
23 | return '';
24 | }
25 |
26 | if (!document.activeElement) {
27 | return document.getSelection() + '';
28 | }
29 |
30 | const activeElement = document.activeElement;
31 |
32 | /* Recurse for FRAMEs and IFRAMEs. */
33 | try {
34 | if (
35 | typeof activeElement.contentDocument === 'object'
36 | && activeElement.contentDocument !== null
37 | ) {
38 | return getActiveSelection(activeElement.contentDocument);
39 | }
40 | } catch (e) {
41 | return document.getSelection() + '';
42 | }
43 |
44 | /* Get the selection from inside a text control. */
45 | if (typeof activeElement.value === 'string') {
46 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
47 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
48 | }
49 |
50 | return activeElement.value;
51 | }
52 |
53 | /* Get the normal selection. */
54 | return document.getSelection() + '';
55 | }
56 |
57 | if (s === '') {
58 | s = getActiveSelection(document) || prompt('Please enter your Bing Images search query or image URL:');
59 | } else {
60 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection(document) + '$2');
61 | }
62 |
63 | if (s) {
64 | /* If the parameter looks like a URL, use reverse image search. */
65 | if (s.match(/^(\w+:(\/\/)?)?[^\s]+(\.[^\s]+)+\//))
66 | {
67 | location = 'https://www.bing.com/images/search?view=detailv2&iss=sbi&FORM=SBIIRP&sbisrc=UrlPaste&q=imgurl:' + encodeURIComponent(s) + '&idpbck=1';
68 | return;
69 | }
70 |
71 | location = 'https://www.bing.com/images/search?q=' + encodeURIComponent(s);
72 | }
73 | })(document);
74 |
--------------------------------------------------------------------------------
/search/ddg.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Search DuckDuckGo for the given text, numbering the search result pages.
3 | *
4 | * @title DuckDuckGo
5 | */
6 | (function ddg() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter your DuckDuckGo search query:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | location = 'https://duckduckgo.com/?ia=web&kv=1&q=' + encodeURIComponent(s);
68 | }
69 | })();
70 |
--------------------------------------------------------------------------------
/search/ddimg.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Search DuckDuckGo for images for the given text.
3 | *
4 | * @title DuckDuckGo image search
5 | */
6 | (function ddimg(document) {
7 | 'use strict';
8 |
9 | /* Try to get the parameter string from the bookmarklet/search query.
10 | * Fall back to the current text selection, if any. If those options
11 | * both fail, prompt the user. */
12 | let s = (function () { /*%s*/; }).toString()
13 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
14 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
15 | .replace(/\u0025s/, '');
16 |
17 | /**
18 | * Get the active text selection, diving into frames and
19 | * text controls when necessary and possible.
20 | */
21 | function getActiveSelection(document) {
22 | if (!document || typeof document.getSelection !== 'function') {
23 | return '';
24 | }
25 |
26 | if (!document.activeElement) {
27 | return document.getSelection() + '';
28 | }
29 |
30 | const activeElement = document.activeElement;
31 |
32 | /* Recurse for FRAMEs and IFRAMEs. */
33 | try {
34 | if (
35 | typeof activeElement.contentDocument === 'object'
36 | && activeElement.contentDocument !== null
37 | ) {
38 | return getActiveSelection(activeElement.contentDocument);
39 | }
40 | } catch (e) {
41 | return document.getSelection() + '';
42 | }
43 |
44 | /* Get the selection from inside a text control. */
45 | if (typeof activeElement.value === 'string') {
46 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
47 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
48 | }
49 |
50 | return activeElement.value;
51 | }
52 |
53 | /* Get the normal selection. */
54 | return document.getSelection() + '';
55 | }
56 |
57 | if (s === '') {
58 | s = getActiveSelection(document) || prompt('Please enter your DuckDuckGo image search query:');
59 | } else {
60 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection(document) + '$2');
61 | }
62 |
63 | if (s) {
64 | location = 'https://duckduckgo.com/?ia=images&iax=images&q=' + encodeURIComponent(s);
65 | }
66 | })(document);
67 |
--------------------------------------------------------------------------------
/search/e.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Search using Ecosia, for “A better planet with every search”.
3 | *
4 | * @title Ecosia
5 | */
6 | (function e(document) {
7 | 'use strict';
8 |
9 | /* Try to get the parameter string from the bookmarklet/search query.
10 | * Fall back to the current text selection, if any. If those options
11 | * both fail, prompt the user. */
12 | let s = (function () { /*%s*/; }).toString()
13 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
14 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
15 | .replace(/\u0025s/, '');
16 |
17 | /**
18 | * Get the active text selection, diving into frames and
19 | * text controls when necessary and possible.
20 | */
21 | function getActiveSelection(document) {
22 | if (!document || typeof document.getSelection !== 'function') {
23 | return '';
24 | }
25 |
26 | if (!document.activeElement) {
27 | return document.getSelection() + '';
28 | }
29 |
30 | const activeElement = document.activeElement;
31 |
32 | /* Recurse for FRAMEs and IFRAMEs. */
33 | try {
34 | if (
35 | typeof activeElement.contentDocument === 'object'
36 | && activeElement.contentDocument !== null
37 | ) {
38 | return getActiveSelection(activeElement.contentDocument);
39 | }
40 | } catch (e) {
41 | return document.getSelection() + '';
42 | }
43 |
44 | /* Get the selection from inside a text control. */
45 | if (typeof activeElement.value === 'string') {
46 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
47 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
48 | }
49 |
50 | return activeElement.value;
51 | }
52 |
53 | /* Get the normal selection. */
54 | return document.getSelection() + '';
55 | }
56 |
57 | if (s === '') {
58 | s = getActiveSelection(document) || prompt('Please enter your Ecosia web search query:');
59 | } else {
60 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection(document) + '$2');
61 | }
62 |
63 | if (s) {
64 | location = 'https://www.ecosia.org/search?q=' + encodeURIComponent(s);
65 | }
66 | })(document);
67 |
--------------------------------------------------------------------------------
/search/eimg.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Search using Ecosia Images, for “A better planet with every search”.
3 | *
4 | * @title Ecosia Images
5 | */
6 | (function eimg(document) {
7 | 'use strict';
8 |
9 | /* Try to get the parameter string from the bookmarklet/search query.
10 | * Fall back to the current text selection, if any. If those options
11 | * both fail, prompt the user. */
12 | let s = (function () { /*%s*/; }).toString()
13 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
14 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
15 | .replace(/\u0025s/, '');
16 |
17 | /**
18 | * Get the active text selection, diving into frames and
19 | * text controls when necessary and possible.
20 | */
21 | function getActiveSelection(document) {
22 | if (!document || typeof document.getSelection !== 'function') {
23 | return '';
24 | }
25 |
26 | if (!document.activeElement) {
27 | return document.getSelection() + '';
28 | }
29 |
30 | const activeElement = document.activeElement;
31 |
32 | /* Recurse for FRAMEs and IFRAMEs. */
33 | try {
34 | if (
35 | typeof activeElement.contentDocument === 'object'
36 | && activeElement.contentDocument !== null
37 | ) {
38 | return getActiveSelection(activeElement.contentDocument);
39 | }
40 | } catch (e) {
41 | return document.getSelection() + '';
42 | }
43 |
44 | /* Get the selection from inside a text control. */
45 | if (typeof activeElement.value === 'string') {
46 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
47 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
48 | }
49 |
50 | return activeElement.value;
51 | }
52 |
53 | /* Get the normal selection. */
54 | return document.getSelection() + '';
55 | }
56 |
57 | if (s === '') {
58 | s = getActiveSelection(document) || prompt('Please enter your Ecosia image search query:');
59 | } else {
60 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection(document) + '$2');
61 | }
62 |
63 | if (s) {
64 | location = 'https://www.ecosia.org/images?q=' + encodeURIComponent(s);
65 | }
66 | })(document);
67 |
--------------------------------------------------------------------------------
/search/g.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Search the international (English) Google for the given text, with a 100
3 | * results per SERP and without Instant Search.
4 | *
5 | * @title Google Search
6 | */
7 | (function g() {
8 | /* Try to get the parameter string from the bookmarklet/search query.
9 | Fall back to the current text selection, if any. If those options
10 | both fail, prompt the user.
11 | */
12 | var s = (function () { /*%s*/; }).toString()
13 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
14 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
15 | .replace(/\u0025s/, '');
16 |
17 | /**
18 | * Get the active text selection, diving into frames and
19 | * text controls when necessary and possible.
20 | */
21 | function getActiveSelection(doc) {
22 | if (arguments.length === 0) {
23 | doc = document;
24 | }
25 |
26 | if (!doc || typeof doc.getSelection !== 'function') {
27 | return '';
28 | }
29 |
30 | if (!doc.activeElement) {
31 | return doc.getSelection() + '';
32 | }
33 |
34 | var activeElement = doc.activeElement;
35 |
36 | /* Recurse for FRAMEs and IFRAMEs. */
37 | try {
38 | if (
39 | typeof activeElement.contentDocument === 'object'
40 | && activeElement.contentDocument !== null
41 | ) {
42 | return getActiveSelection(activeElement.contentDocument);
43 | }
44 | } catch (e) {
45 | return doc.getSelection() + '';
46 | }
47 |
48 | /* Get the selection from inside a text control. */
49 | if (typeof activeElement.value === 'string') {
50 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
51 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
52 | }
53 |
54 | return activeElement.value;
55 | }
56 |
57 | /* Get the normal selection. */
58 | return doc.getSelection() + '';
59 | }
60 |
61 | if (s === '') {
62 | s = getActiveSelection() || prompt('Please enter your Google search query:');
63 | } else {
64 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
65 | }
66 |
67 | if (s) {
68 | location = 'https://www.google.com/search?ie=utf-8&hl=en&num=100&q=' + encodeURIComponent(s);
69 | }
70 | })();
71 |
--------------------------------------------------------------------------------
/search/gc.js:
--------------------------------------------------------------------------------
1 | /**
2 | * View the Google cached text for the specified URL.
3 | * Specify "html" as the first parameter to view the cached HTML.
4 | *
5 | * @title Google cache
6 | */
7 | (function gc() {
8 | /* Try to get the parameter string from the bookmarklet/search query.
9 | Fall back to the current text selection, if any. If those options
10 | both fail, prompt the user.
11 | */
12 | var s = (function () { /*%s*/; }).toString()
13 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
14 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
15 | .replace(/\u0025s/, '');
16 |
17 | /**
18 | * Get the active text selection, diving into frames and
19 | * text controls when necessary and possible.
20 | */
21 | function getActiveSelection(doc) {
22 | if (arguments.length === 0) {
23 | doc = document;
24 | }
25 |
26 | if (!doc || typeof doc.getSelection !== 'function') {
27 | return '';
28 | }
29 |
30 | if (!doc.activeElement) {
31 | return doc.getSelection() + '';
32 | }
33 |
34 | var activeElement = doc.activeElement;
35 |
36 | /* Recurse for FRAMEs and IFRAMEs. */
37 | try {
38 | if (
39 | typeof activeElement.contentDocument === 'object'
40 | && activeElement.contentDocument !== null
41 | ) {
42 | return getActiveSelection(activeElement.contentDocument);
43 | }
44 | } catch (e) {
45 | return doc.getSelection() + '';
46 | }
47 |
48 | /* Get the selection from inside a text control. */
49 | if (typeof activeElement.value === 'string') {
50 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
51 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
52 | }
53 |
54 | return activeElement.value;
55 | }
56 |
57 | /* Get the normal selection. */
58 | return doc.getSelection() + '';
59 | }
60 |
61 | if (s === '') {
62 | s = getActiveSelection() || prompt('Please enter the URL whose Google cache to view:', location);
63 | } else {
64 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
65 | }
66 |
67 | if (s) {
68 | var url = 'https://webcache.googleusercontent.com/search?', words = s.split(' ');
69 |
70 | if (words[0] == 'html') {
71 | s = words.slice(1).join(' ');
72 | } else {
73 | url += 'strip=1&';
74 | }
75 |
76 | location = url + 'q=cache:' + encodeURIComponent(s);
77 | }
78 | })();
79 |
--------------------------------------------------------------------------------
/search/go.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Go to the first DuckDuckGo result ("I'm Feeling Ducky") for the given text.
3 | *
4 | * @title Go
5 | */
6 | (function go() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter your DuckDuckGo “I’m Feeling Ducky” search query:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | s += ' !';
68 | location = 'https://www.duckduckgo.com/?q=' + encodeURIComponent(s);
69 | }
70 | })();
71 |
--------------------------------------------------------------------------------
/search/gs.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Search the international (English) Google for the given text on the current
3 | * site's domain, with a 100 results per SERP and without Instant Search.
4 | *
5 | * @title Google Site Search
6 | */
7 | (function gs() {
8 | /* Try to get the parameter string from the bookmarklet/search query.
9 | Fall back to the current text selection, if any. If those options
10 | both fail, prompt the user.
11 | */
12 | var s = (function () { /*%s*/; }).toString()
13 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
14 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
15 | .replace(/\u0025s/, '');
16 |
17 | /**
18 | * Get the active text selection, diving into frames and
19 | * text controls when necessary and possible.
20 | */
21 | function getActiveSelection(doc) {
22 | if (arguments.length === 0) {
23 | doc = document;
24 | }
25 |
26 | if (!doc || typeof doc.getSelection !== 'function') {
27 | return '';
28 | }
29 |
30 | if (!doc.activeElement) {
31 | return doc.getSelection() + '';
32 | }
33 |
34 | var activeElement = doc.activeElement;
35 |
36 | /* Recurse for FRAMEs and IFRAMEs. */
37 | try {
38 | if (
39 | typeof activeElement.contentDocument === 'object'
40 | && activeElement.contentDocument !== null
41 | ) {
42 | return getActiveSelection(activeElement.contentDocument);
43 | }
44 | } catch (e) {
45 | return doc.getSelection() + '';
46 | }
47 |
48 | /* Get the selection from inside a text control. */
49 | if (typeof activeElement.value === 'string') {
50 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
51 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
52 | }
53 |
54 | return activeElement.value;
55 | }
56 |
57 | /* Get the normal selection. */
58 | return doc.getSelection() + '';
59 | }
60 |
61 | if (s === '') {
62 | s = getActiveSelection() || prompt('Please enter your Google search query for ' + location.host + 't:');
63 | } else {
64 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
65 | }
66 |
67 | if (s) {
68 | s = 'site:' + location.host + ' ' + s;
69 | location = 'https://www.google.com/search?ie=utf-8&hl=en&num=100&q=' + encodeURIComponent(s);
70 | }
71 | })();
72 |
--------------------------------------------------------------------------------
/search/img.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Defaults to Ecosia Images (see `eimg`).
3 | *
4 | * @title Image search
5 | * @keyword img
6 | * @transclude eimg.js
7 | */
8 |
--------------------------------------------------------------------------------
/search/maps/README:
--------------------------------------------------------------------------------
1 | Maps & transportation
2 |
--------------------------------------------------------------------------------
/search/maps/mapi.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Go to the specified (lat, lng) coordinates with Mapillary.
3 | *
4 | * @title Mapillary
5 | */
6 | (function mapi(document) {
7 | 'use strict';
8 |
9 | /* Try to get the parameter string from the bookmarklet/search query.
10 | * Fall back to the current text selection, if any. If those options
11 | * both fail, prompt the user. */
12 | let s = (function () { /*%s*/; }).toString()
13 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
14 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
15 | .replace(/\u0025s/, '');
16 |
17 | /**
18 | * Get the active text selection, diving into frames and
19 | * text controls when necessary and possible.
20 | */
21 | function getActiveSelection(document) {
22 | if (!document || typeof document.getSelection !== 'function') {
23 | return '';
24 | }
25 |
26 | if (!document.activeElement) {
27 | return document.getSelection() + '';
28 | }
29 |
30 | const activeElement = document.activeElement;
31 |
32 | /* Recurse for FRAMEs and IFRAMEs. */
33 | try {
34 | if (
35 | typeof activeElement.contentDocument === 'object'
36 | && activeElement.contentDocument !== null
37 | ) {
38 | return getActiveSelection(activeElement.contentDocument);
39 | }
40 | } catch (e) {
41 | return document.getSelection() + '';
42 | }
43 |
44 | /* Get the selection from inside a text control. */
45 | if (typeof activeElement.value === 'string') {
46 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
47 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
48 | }
49 |
50 | return activeElement.value;
51 | }
52 |
53 | /* Get the normal selection. */
54 | return document.getSelection() + '';
55 | }
56 |
57 | if (s === '') {
58 | s = getActiveSelection(document) || prompt('Specify the (lat, lng) coordinates:');
59 | } else {
60 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection(document) + '$2');
61 | }
62 |
63 | if (s) {
64 | const [lat, lng] = s
65 | .replace(/^\s*\(\s*/, '')
66 | .replace(/\s*\(\s*$/, '')
67 | .replace(/^https:\/\/www\.google\.com\/maps\/([^@]+\/)*@/, '')
68 | .split(/\s*[ ,]\s*/)
69 | .map(parseFloat);
70 |
71 | if (isNaN(lat) || isNaN(lng)) {
72 | alert(`Could not parse (lat, lng) coordinates from “${s}”`);
73 | return;
74 | }
75 |
76 | location = `https://www.mapillary.com/app/?lat=${encodeURIComponent(lat)}&lng=${encodeURIComponent(lng)}&z=15`;
77 | }
78 | })(document);
79 |
--------------------------------------------------------------------------------
/search/tineye.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Search images using the TinEye reverse image search.
3 | *
4 | * @title TinEye
5 | */
6 | (function tin() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the image URL for TinEye to reverse search:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | if (!s.match(/^(\w+:(\/\/)?)?[^\s]+(\.[^\s]+)+\//))
68 | {
69 | alert(`Are you sure that’s an image URL?\n\n${s}`);
70 | return;
71 | }
72 |
73 | location = 'https://tineye.com/search/?url=' + encodeURIComponent(s);
74 | }
75 | })();
76 |
--------------------------------------------------------------------------------
/search/tw.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Search Twitter for the specified text or URL.
3 | *
4 | * @title Twitter search
5 | */
6 | (function tw() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter your Twitter search query:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | location = 'https://twitter.com/search?f=live&q=' + encodeURIComponent(s);
68 | }
69 | })();
70 |
--------------------------------------------------------------------------------
/search/tweep.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Search Twitter for the specified user.
3 | *
4 | * @title Twitter user (Tweep) search
5 | */
6 | (function tweep() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the Twitter user to search for:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | location = 'https://twitter.com/search?f=user&q=' + encodeURIComponent(s);
68 | }
69 | })();
70 |
--------------------------------------------------------------------------------
/search/wb.js:
--------------------------------------------------------------------------------
1 | /**
2 | * View the Internet Archive Wayback Machine's latest cache for the specified URL.
3 | *
4 | * @title Wayback Machine
5 | */
6 | (function wb() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the URL to look up in the Wayback Machine:', location);
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | /* Typing “wb *\/example.com” (without the backslash) to search all
67 | * archived versions of “example.com” does not work because of the way
68 | * this bookmarklet wraps “percent s” in a multiline comment in a
69 | * function body (see above). As a workaround, use “wb * example.com”
70 | * or “wb 2010* example.com”.
71 | */
72 | s = s.replace(/^\s*([0-9]+\*?|\*)\s+/, '$1/');
73 |
74 | if (s) {
75 | location = 'https://web.archive.org/web/' + s;
76 | }
77 | })();
78 |
--------------------------------------------------------------------------------
/search/wikipedia/2comm.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Go to the corresponding Wikimedia Commons page for a Wikipedia article.
3 | *
4 | * @title Go to Wikimedia Commons
5 | * @keyword 2comm
6 | */
7 | (function() {
8 | 'use strict';
9 |
10 | /* Recursively execute the logic on the document and its sub-documents. */
11 | function execute(document) {
12 | const commonsLink = document.querySelector('.wb-otherproject-link.wb-otherproject-commons a[href], .sistersitebox a[href^="https://commons.wikimedia.org/wiki/"], .sistersitebox a[href^="https://commons.m.wikimedia.org/wiki/"]');
13 | if (commonsLink) {
14 | try {
15 | top.location = commonsLink.href;
16 | return;
17 | } catch (e) {
18 | location = commonsLink.href;
19 | }
20 | }
21 |
22 | /* Recurse for (i)frames. */
23 | try {
24 | Array.from(document.querySelectorAll('frame, iframe, object[type^="text/html"], object[type^="application/xhtml+xml"]')).forEach(
25 | elem => { try { execute(elem.contentDocument) } catch (e) { } }
26 | );
27 | } catch (e) {
28 | /* Catch and ignore exceptions for out-of-domain access. */
29 | }
30 | }
31 |
32 | execute(document);
33 | })();
34 |
--------------------------------------------------------------------------------
/search/wikipedia/README:
--------------------------------------------------------------------------------
1 | Wikipedia
2 |
--------------------------------------------------------------------------------
/search/wikipedia/anyw.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text in any Wikipedia.
3 | *
4 | * This does a Google "I'm feeling lucky" search for all wikipedia.org sites.
5 | *
6 | * @title Any Wikipedia
7 | */
8 | (function anyw() {
9 | /* Try to get the parameter string from the bookmarklet/search query.
10 | Fall back to the current text selection, if any. If those options
11 | both fail, prompt the user.
12 | */
13 | var s = (function () { /*%s*/; }).toString()
14 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
15 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
16 | .replace(/\u0025s/, '');
17 |
18 | /**
19 | * Get the active text selection, diving into frames and
20 | * text controls when necessary and possible.
21 | */
22 | function getActiveSelection(doc) {
23 | if (arguments.length === 0) {
24 | doc = document;
25 | }
26 |
27 | if (!doc || typeof doc.getSelection !== 'function') {
28 | return '';
29 | }
30 |
31 | if (!doc.activeElement) {
32 | return doc.getSelection() + '';
33 | }
34 |
35 | var activeElement = doc.activeElement;
36 |
37 | /* Recurse for FRAMEs and IFRAMEs. */
38 | try {
39 | if (
40 | typeof activeElement.contentDocument === 'object'
41 | && activeElement.contentDocument !== null
42 | ) {
43 | return getActiveSelection(activeElement.contentDocument);
44 | }
45 | } catch (e) {
46 | return doc.getSelection() + '';
47 | }
48 |
49 | /* Get the selection from inside a text control. */
50 | if (typeof activeElement.value === 'string') {
51 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
52 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
53 | }
54 |
55 | return activeElement.value;
56 | }
57 |
58 | /* Get the normal selection. */
59 | return doc.getSelection() + '';
60 | }
61 |
62 | if (s === '') {
63 | s = getActiveSelection() || prompt('Please enter the subject to look up on any Wikipedia:');
64 | } else {
65 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
66 | }
67 |
68 | if (s) {
69 | /* Pro-tip: use this as keyword.URL in Firefox (see about:config). It used to be the default, but then Google slightly tweaked it. */
70 | location = 'https://www.google.com/search?btnI=&ie=utf-8&sourceid=navclient&q=' + encodeURIComponent('site:wikipedia.org ' + s);
71 | }
72 | })();
73 |
--------------------------------------------------------------------------------
/search/wikipedia/dew.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text in the German Wikipedia.
3 | *
4 | * Use `--dis` as the first parameter to show the disambiguation page, if any.
5 | *
6 | * E.g. `enw --dis 1` would open `1 (disambiguation)`, which is a lot faster to
7 | * type then `enw 1 (disambiguation)`, and also works for the non-English
8 | * Wikipedia instances, which use other words for “disambiguation”.
9 | *
10 | * @title German Wikipedia
11 | * @keyword dew
12 | */
13 | (function (config) {
14 | const {languageCode, languageNamesInEnglish, disambigationPageSuffix} = config;
15 | /* Try to get the parameter string from the bookmarklet/search query.
16 | Fall back to the current text selection, if any. If those options
17 | both fail, prompt the user.
18 | */
19 | var s = (function () { /*%s*/; }).toString()
20 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
21 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
22 | .replace(/\u0025s/, '');
23 |
24 | /**
25 | * Get the active text selection, diving into frames and
26 | * text controls when necessary and possible.
27 | */
28 | function getActiveSelection(doc) {
29 | if (arguments.length === 0) {
30 | doc = document;
31 | }
32 |
33 | if (!doc || typeof doc.getSelection !== 'function') {
34 | return '';
35 | }
36 |
37 | if (!doc.activeElement) {
38 | return doc.getSelection() + '';
39 | }
40 |
41 | var activeElement = doc.activeElement;
42 |
43 | /* Recurse for FRAMEs and IFRAMEs. */
44 | try {
45 | if (
46 | typeof activeElement.contentDocument === 'object'
47 | && activeElement.contentDocument !== null
48 | ) {
49 | return getActiveSelection(activeElement.contentDocument);
50 | }
51 | } catch (e) {
52 | return doc.getSelection() + '';
53 | }
54 |
55 | /* Get the selection from inside a text control. */
56 | if (typeof activeElement.value === 'string') {
57 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
58 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
59 | }
60 |
61 | return activeElement.value;
62 | }
63 |
64 | /* Get the normal selection. */
65 | return doc.getSelection() + '';
66 | }
67 |
68 | if (s === '') {
69 | s = getActiveSelection() || prompt(`Please enter the subject to look up in the ${languageNamesInEnglish.join('/')} Wikipedia:`);
70 | } else {
71 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
72 | }
73 |
74 | if (s) {
75 | /* Open the disambigation page for queries like `enw --dis Foo`. */
76 | let matches = s.match(/^\s*--dis\s*(.+)/);
77 | if (matches) {
78 | s = matches[1] + disambigationPageSuffix;
79 | }
80 |
81 | /* The Wikipedia search works like "I'm feeling lucky" on most Wikipedia instances. If there is a complete match, it will redirect us there. */
82 | location = `https://${languageCode}.wikipedia.org/w/index.php?searchToken=.&title=Special%3ASearch&ns0=1&search=${encodeURIComponent(s)}`;
83 | }
84 | })({
85 |
86 | languageCode: 'de',
87 | languageNamesInEnglish: ['German'],
88 | disambigationPageSuffix: ' (Begriffsklärung)',
89 |
90 | });
91 |
--------------------------------------------------------------------------------
/search/wikipedia/enw.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text in the English Wikipedia.
3 | *
4 | * Use `--dis` as the first parameter to show the disambiguation page, if any.
5 | *
6 | * E.g. `enw --dis 1` would open `1 (disambiguation)`, which is a lot faster to
7 | * type then `enw 1 (disambiguation)`, and also works for the non-English
8 | * Wikipedia instances, which use other words for “disambiguation”.
9 | *
10 | * @title English Wikipedia
11 | * @keyword enw
12 | */
13 | (function (config) {
14 | const {languageCode, languageNamesInEnglish, disambigationPageSuffix} = config;
15 | /* Try to get the parameter string from the bookmarklet/search query.
16 | Fall back to the current text selection, if any. If those options
17 | both fail, prompt the user.
18 | */
19 | var s = (function () { /*%s*/; }).toString()
20 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
21 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
22 | .replace(/\u0025s/, '');
23 |
24 | /**
25 | * Get the active text selection, diving into frames and
26 | * text controls when necessary and possible.
27 | */
28 | function getActiveSelection(doc) {
29 | if (arguments.length === 0) {
30 | doc = document;
31 | }
32 |
33 | if (!doc || typeof doc.getSelection !== 'function') {
34 | return '';
35 | }
36 |
37 | if (!doc.activeElement) {
38 | return doc.getSelection() + '';
39 | }
40 |
41 | var activeElement = doc.activeElement;
42 |
43 | /* Recurse for FRAMEs and IFRAMEs. */
44 | try {
45 | if (
46 | typeof activeElement.contentDocument === 'object'
47 | && activeElement.contentDocument !== null
48 | ) {
49 | return getActiveSelection(activeElement.contentDocument);
50 | }
51 | } catch (e) {
52 | return doc.getSelection() + '';
53 | }
54 |
55 | /* Get the selection from inside a text control. */
56 | if (typeof activeElement.value === 'string') {
57 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
58 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
59 | }
60 |
61 | return activeElement.value;
62 | }
63 |
64 | /* Get the normal selection. */
65 | return doc.getSelection() + '';
66 | }
67 |
68 | if (s === '') {
69 | s = getActiveSelection() || prompt(`Please enter the subject to look up in the ${languageNamesInEnglish.join('/')} Wikipedia:`);
70 | } else {
71 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
72 | }
73 |
74 | if (s) {
75 | /* Open the disambigation page for queries like `enw --dis Foo`. */
76 | let matches = s.match(/^\s*--dis\s*(.+)/);
77 | if (matches) {
78 | s = matches[1] + disambigationPageSuffix;
79 | }
80 |
81 | /* The Wikipedia search works like "I'm feeling lucky" on most Wikipedia instances. If there is a complete match, it will redirect us there. */
82 | location = `https://${languageCode}.wikipedia.org/w/index.php?searchToken=.&title=Special%3ASearch&ns0=1&search=${encodeURIComponent(s)}`;
83 | }
84 | })({
85 | /* ↓ XXX Begin JS config object ↓ XXX */
86 | languageCode: 'en',
87 | languageNamesInEnglish: ['English'],
88 | disambigationPageSuffix: ' (disambiguation)',
89 | /* ↑ XXX End JS config object ↑ XXX */
90 | });
91 |
--------------------------------------------------------------------------------
/search/wikipedia/esw.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text in the Spanish Wikipedia.
3 | *
4 | * Use `--dis` as the first parameter to show the disambiguation page, if any.
5 | *
6 | * E.g. `enw --dis 1` would open `1 (disambiguation)`, which is a lot faster to
7 | * type then `enw 1 (disambiguation)`, and also works for the non-English
8 | * Wikipedia instances, which use other words for “disambiguation”.
9 | *
10 | * @title Spanish Wikipedia
11 | * @keyword esw
12 | */
13 | (function (config) {
14 | const {languageCode, languageNamesInEnglish, disambigationPageSuffix} = config;
15 | /* Try to get the parameter string from the bookmarklet/search query.
16 | Fall back to the current text selection, if any. If those options
17 | both fail, prompt the user.
18 | */
19 | var s = (function () { /*%s*/; }).toString()
20 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
21 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
22 | .replace(/\u0025s/, '');
23 |
24 | /**
25 | * Get the active text selection, diving into frames and
26 | * text controls when necessary and possible.
27 | */
28 | function getActiveSelection(doc) {
29 | if (arguments.length === 0) {
30 | doc = document;
31 | }
32 |
33 | if (!doc || typeof doc.getSelection !== 'function') {
34 | return '';
35 | }
36 |
37 | if (!doc.activeElement) {
38 | return doc.getSelection() + '';
39 | }
40 |
41 | var activeElement = doc.activeElement;
42 |
43 | /* Recurse for FRAMEs and IFRAMEs. */
44 | try {
45 | if (
46 | typeof activeElement.contentDocument === 'object'
47 | && activeElement.contentDocument !== null
48 | ) {
49 | return getActiveSelection(activeElement.contentDocument);
50 | }
51 | } catch (e) {
52 | return doc.getSelection() + '';
53 | }
54 |
55 | /* Get the selection from inside a text control. */
56 | if (typeof activeElement.value === 'string') {
57 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
58 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
59 | }
60 |
61 | return activeElement.value;
62 | }
63 |
64 | /* Get the normal selection. */
65 | return doc.getSelection() + '';
66 | }
67 |
68 | if (s === '') {
69 | s = getActiveSelection() || prompt(`Please enter the subject to look up in the ${languageNamesInEnglish.join('/')} Wikipedia:`);
70 | } else {
71 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
72 | }
73 |
74 | if (s) {
75 | /* Open the disambigation page for queries like `enw --dis Foo`. */
76 | let matches = s.match(/^\s*--dis\s*(.+)/);
77 | if (matches) {
78 | s = matches[1] + disambigationPageSuffix;
79 | }
80 |
81 | /* The Wikipedia search works like "I'm feeling lucky" on most Wikipedia instances. If there is a complete match, it will redirect us there. */
82 | location = `https://${languageCode}.wikipedia.org/w/index.php?searchToken=.&title=Special%3ASearch&ns0=1&search=${encodeURIComponent(s)}`;
83 | }
84 | })({
85 |
86 | languageCode: 'es',
87 | languageNamesInEnglish: ['Spanish'],
88 | disambigationPageSuffix: ' (desambiguación)',
89 |
90 | });
91 |
--------------------------------------------------------------------------------
/search/wikipedia/frw.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text in the French Wikipedia.
3 | *
4 | * Use `--dis` as the first parameter to show the disambiguation page, if any.
5 | *
6 | * E.g. `enw --dis 1` would open `1 (disambiguation)`, which is a lot faster to
7 | * type then `enw 1 (disambiguation)`, and also works for the non-English
8 | * Wikipedia instances, which use other words for “disambiguation”.
9 | *
10 | * @title French Wikipedia
11 | * @keyword frw
12 | */
13 | (function (config) {
14 | const {languageCode, languageNamesInEnglish, disambigationPageSuffix} = config;
15 | /* Try to get the parameter string from the bookmarklet/search query.
16 | Fall back to the current text selection, if any. If those options
17 | both fail, prompt the user.
18 | */
19 | var s = (function () { /*%s*/; }).toString()
20 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
21 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
22 | .replace(/\u0025s/, '');
23 |
24 | /**
25 | * Get the active text selection, diving into frames and
26 | * text controls when necessary and possible.
27 | */
28 | function getActiveSelection(doc) {
29 | if (arguments.length === 0) {
30 | doc = document;
31 | }
32 |
33 | if (!doc || typeof doc.getSelection !== 'function') {
34 | return '';
35 | }
36 |
37 | if (!doc.activeElement) {
38 | return doc.getSelection() + '';
39 | }
40 |
41 | var activeElement = doc.activeElement;
42 |
43 | /* Recurse for FRAMEs and IFRAMEs. */
44 | try {
45 | if (
46 | typeof activeElement.contentDocument === 'object'
47 | && activeElement.contentDocument !== null
48 | ) {
49 | return getActiveSelection(activeElement.contentDocument);
50 | }
51 | } catch (e) {
52 | return doc.getSelection() + '';
53 | }
54 |
55 | /* Get the selection from inside a text control. */
56 | if (typeof activeElement.value === 'string') {
57 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
58 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
59 | }
60 |
61 | return activeElement.value;
62 | }
63 |
64 | /* Get the normal selection. */
65 | return doc.getSelection() + '';
66 | }
67 |
68 | if (s === '') {
69 | s = getActiveSelection() || prompt(`Please enter the subject to look up in the ${languageNamesInEnglish.join('/')} Wikipedia:`);
70 | } else {
71 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
72 | }
73 |
74 | if (s) {
75 | /* Open the disambigation page for queries like `enw --dis Foo`. */
76 | let matches = s.match(/^\s*--dis\s*(.+)/);
77 | if (matches) {
78 | s = matches[1] + disambigationPageSuffix;
79 | }
80 |
81 | /* The Wikipedia search works like "I'm feeling lucky" on most Wikipedia instances. If there is a complete match, it will redirect us there. */
82 | location = `https://${languageCode}.wikipedia.org/w/index.php?searchToken=.&title=Special%3ASearch&ns0=1&search=${encodeURIComponent(s)}`;
83 | }
84 | })({
85 |
86 | languageCode: 'fr',
87 | languageNamesInEnglish: ['French'],
88 | disambigationPageSuffix: ' (homonymie)',
89 |
90 | });
91 |
--------------------------------------------------------------------------------
/search/wikipedia/itw.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text in the Italian Wikipedia.
3 | *
4 | * Use `--dis` as the first parameter to show the disambiguation page, if any.
5 | *
6 | * E.g. `enw --dis 1` would open `1 (disambiguation)`, which is a lot faster to
7 | * type then `enw 1 (disambiguation)`, and also works for the non-English
8 | * Wikipedia instances, which use other words for “disambiguation”.
9 | *
10 | * @title Italian Wikipedia
11 | * @keyword itw
12 | */
13 | (function (config) {
14 | const {languageCode, languageNamesInEnglish, disambigationPageSuffix} = config;
15 | /* Try to get the parameter string from the bookmarklet/search query.
16 | Fall back to the current text selection, if any. If those options
17 | both fail, prompt the user.
18 | */
19 | var s = (function () { /*%s*/; }).toString()
20 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
21 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
22 | .replace(/\u0025s/, '');
23 |
24 | /**
25 | * Get the active text selection, diving into frames and
26 | * text controls when necessary and possible.
27 | */
28 | function getActiveSelection(doc) {
29 | if (arguments.length === 0) {
30 | doc = document;
31 | }
32 |
33 | if (!doc || typeof doc.getSelection !== 'function') {
34 | return '';
35 | }
36 |
37 | if (!doc.activeElement) {
38 | return doc.getSelection() + '';
39 | }
40 |
41 | var activeElement = doc.activeElement;
42 |
43 | /* Recurse for FRAMEs and IFRAMEs. */
44 | try {
45 | if (
46 | typeof activeElement.contentDocument === 'object'
47 | && activeElement.contentDocument !== null
48 | ) {
49 | return getActiveSelection(activeElement.contentDocument);
50 | }
51 | } catch (e) {
52 | return doc.getSelection() + '';
53 | }
54 |
55 | /* Get the selection from inside a text control. */
56 | if (typeof activeElement.value === 'string') {
57 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
58 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
59 | }
60 |
61 | return activeElement.value;
62 | }
63 |
64 | /* Get the normal selection. */
65 | return doc.getSelection() + '';
66 | }
67 |
68 | if (s === '') {
69 | s = getActiveSelection() || prompt(`Please enter the subject to look up in the ${languageNamesInEnglish.join('/')} Wikipedia:`);
70 | } else {
71 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
72 | }
73 |
74 | if (s) {
75 | /* Open the disambigation page for queries like `enw --dis Foo`. */
76 | let matches = s.match(/^\s*--dis\s*(.+)/);
77 | if (matches) {
78 | s = matches[1] + disambigationPageSuffix;
79 | }
80 |
81 | /* The Wikipedia search works like "I'm feeling lucky" on most Wikipedia instances. If there is a complete match, it will redirect us there. */
82 | location = `https://${languageCode}.wikipedia.org/w/index.php?searchToken=.&title=Special%3ASearch&ns0=1&search=${encodeURIComponent(s)}`;
83 | }
84 | })({
85 |
86 | languageCode: 'it',
87 | languageNamesInEnglish: ['Italian'],
88 | disambigationPageSuffix: ' (disambigua)',
89 |
90 | });
91 |
--------------------------------------------------------------------------------
/search/wikipedia/nlw.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text in the Dutch Wikipedia.
3 | *
4 | * Use `--dis` as the first parameter to show the disambiguation page, if any.
5 | *
6 | * E.g. `enw --dis 1` would open `1 (disambiguation)`, which is a lot faster to
7 | * type then `enw 1 (disambiguation)`, and also works for the non-English
8 | * Wikipedia instances, which use other words for “disambiguation”.
9 | *
10 | * @title Dutch Wikipedia
11 | * @keyword nlw
12 | */
13 | (function (config) {
14 | const {languageCode, languageNamesInEnglish, disambigationPageSuffix} = config;
15 | /* Try to get the parameter string from the bookmarklet/search query.
16 | Fall back to the current text selection, if any. If those options
17 | both fail, prompt the user.
18 | */
19 | var s = (function () { /*%s*/; }).toString()
20 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
21 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
22 | .replace(/\u0025s/, '');
23 |
24 | /**
25 | * Get the active text selection, diving into frames and
26 | * text controls when necessary and possible.
27 | */
28 | function getActiveSelection(doc) {
29 | if (arguments.length === 0) {
30 | doc = document;
31 | }
32 |
33 | if (!doc || typeof doc.getSelection !== 'function') {
34 | return '';
35 | }
36 |
37 | if (!doc.activeElement) {
38 | return doc.getSelection() + '';
39 | }
40 |
41 | var activeElement = doc.activeElement;
42 |
43 | /* Recurse for FRAMEs and IFRAMEs. */
44 | try {
45 | if (
46 | typeof activeElement.contentDocument === 'object'
47 | && activeElement.contentDocument !== null
48 | ) {
49 | return getActiveSelection(activeElement.contentDocument);
50 | }
51 | } catch (e) {
52 | return doc.getSelection() + '';
53 | }
54 |
55 | /* Get the selection from inside a text control. */
56 | if (typeof activeElement.value === 'string') {
57 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
58 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
59 | }
60 |
61 | return activeElement.value;
62 | }
63 |
64 | /* Get the normal selection. */
65 | return doc.getSelection() + '';
66 | }
67 |
68 | if (s === '') {
69 | s = getActiveSelection() || prompt(`Please enter the subject to look up in the ${languageNamesInEnglish.join('/')} Wikipedia:`);
70 | } else {
71 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
72 | }
73 |
74 | if (s) {
75 | /* Open the disambigation page for queries like `enw --dis Foo`. */
76 | let matches = s.match(/^\s*--dis\s*(.+)/);
77 | if (matches) {
78 | s = matches[1] + disambigationPageSuffix;
79 | }
80 |
81 | /* The Wikipedia search works like "I'm feeling lucky" on most Wikipedia instances. If there is a complete match, it will redirect us there. */
82 | location = `https://${languageCode}.wikipedia.org/w/index.php?searchToken=.&title=Special%3ASearch&ns0=1&search=${encodeURIComponent(s)}`;
83 | }
84 | })({
85 |
86 | languageCode: 'nl',
87 | languageNamesInEnglish: ['Dutch'],
88 | disambigationPageSuffix: ' (doorverwijspagina)',
89 |
90 | });
91 |
--------------------------------------------------------------------------------
/search/wikipedia/now.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text in the Norwegian Wikipedia.
3 | *
4 | * Use `--dis` as the first parameter to show the disambiguation page, if any.
5 | *
6 | * E.g. `enw --dis 1` would open `1 (disambiguation)`, which is a lot faster to
7 | * type then `enw 1 (disambiguation)`, and also works for the non-English
8 | * Wikipedia instances, which use other words for “disambiguation”.
9 | *
10 | * @title Norwegian Wikipedia
11 | * @keyword now
12 | */
13 | (function (config) {
14 | const {languageCode, languageNamesInEnglish, disambigationPageSuffix} = config;
15 | /* Try to get the parameter string from the bookmarklet/search query.
16 | Fall back to the current text selection, if any. If those options
17 | both fail, prompt the user.
18 | */
19 | var s = (function () { /*%s*/; }).toString()
20 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
21 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
22 | .replace(/\u0025s/, '');
23 |
24 | /**
25 | * Get the active text selection, diving into frames and
26 | * text controls when necessary and possible.
27 | */
28 | function getActiveSelection(doc) {
29 | if (arguments.length === 0) {
30 | doc = document;
31 | }
32 |
33 | if (!doc || typeof doc.getSelection !== 'function') {
34 | return '';
35 | }
36 |
37 | if (!doc.activeElement) {
38 | return doc.getSelection() + '';
39 | }
40 |
41 | var activeElement = doc.activeElement;
42 |
43 | /* Recurse for FRAMEs and IFRAMEs. */
44 | try {
45 | if (
46 | typeof activeElement.contentDocument === 'object'
47 | && activeElement.contentDocument !== null
48 | ) {
49 | return getActiveSelection(activeElement.contentDocument);
50 | }
51 | } catch (e) {
52 | return doc.getSelection() + '';
53 | }
54 |
55 | /* Get the selection from inside a text control. */
56 | if (typeof activeElement.value === 'string') {
57 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
58 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
59 | }
60 |
61 | return activeElement.value;
62 | }
63 |
64 | /* Get the normal selection. */
65 | return doc.getSelection() + '';
66 | }
67 |
68 | if (s === '') {
69 | s = getActiveSelection() || prompt(`Please enter the subject to look up in the ${languageNamesInEnglish.join('/')} Wikipedia:`);
70 | } else {
71 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
72 | }
73 |
74 | if (s) {
75 | /* Open the disambigation page for queries like `enw --dis Foo`. */
76 | let matches = s.match(/^\s*--dis\s*(.+)/);
77 | if (matches) {
78 | s = matches[1] + disambigationPageSuffix;
79 | }
80 |
81 | /* The Wikipedia search works like "I'm feeling lucky" on most Wikipedia instances. If there is a complete match, it will redirect us there. */
82 | location = `https://${languageCode}.wikipedia.org/w/index.php?searchToken=.&title=Special%3ASearch&ns0=1&search=${encodeURIComponent(s)}`;
83 | }
84 | })({
85 |
86 | languageCode: 'no',
87 | languageNamesInEnglish: ['Norwegian'],
88 | disambigationPageSuffix: ' (andre betydninger)',
89 |
90 | });
91 |
--------------------------------------------------------------------------------
/search/wikipedia/ptw.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text in the Portuguese Wikipedia.
3 | *
4 | * Use `--dis` as the first parameter to show the disambiguation page, if any.
5 | *
6 | * E.g. `enw --dis 1` would open `1 (disambiguation)`, which is a lot faster to
7 | * type then `enw 1 (disambiguation)`, and also works for the non-English
8 | * Wikipedia instances, which use other words for “disambiguation”.
9 | *
10 | * @title Portuguese Wikipedia
11 | * @keyword ptw
12 | */
13 | (function (config) {
14 | const {languageCode, languageNamesInEnglish, disambigationPageSuffix} = config;
15 | /* Try to get the parameter string from the bookmarklet/search query.
16 | Fall back to the current text selection, if any. If those options
17 | both fail, prompt the user.
18 | */
19 | var s = (function () { /*%s*/; }).toString()
20 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
21 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
22 | .replace(/\u0025s/, '');
23 |
24 | /**
25 | * Get the active text selection, diving into frames and
26 | * text controls when necessary and possible.
27 | */
28 | function getActiveSelection(doc) {
29 | if (arguments.length === 0) {
30 | doc = document;
31 | }
32 |
33 | if (!doc || typeof doc.getSelection !== 'function') {
34 | return '';
35 | }
36 |
37 | if (!doc.activeElement) {
38 | return doc.getSelection() + '';
39 | }
40 |
41 | var activeElement = doc.activeElement;
42 |
43 | /* Recurse for FRAMEs and IFRAMEs. */
44 | try {
45 | if (
46 | typeof activeElement.contentDocument === 'object'
47 | && activeElement.contentDocument !== null
48 | ) {
49 | return getActiveSelection(activeElement.contentDocument);
50 | }
51 | } catch (e) {
52 | return doc.getSelection() + '';
53 | }
54 |
55 | /* Get the selection from inside a text control. */
56 | if (typeof activeElement.value === 'string') {
57 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
58 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
59 | }
60 |
61 | return activeElement.value;
62 | }
63 |
64 | /* Get the normal selection. */
65 | return doc.getSelection() + '';
66 | }
67 |
68 | if (s === '') {
69 | s = getActiveSelection() || prompt(`Please enter the subject to look up in the ${languageNamesInEnglish.join('/')} Wikipedia:`);
70 | } else {
71 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
72 | }
73 |
74 | if (s) {
75 | /* Open the disambigation page for queries like `enw --dis Foo`. */
76 | let matches = s.match(/^\s*--dis\s*(.+)/);
77 | if (matches) {
78 | s = matches[1] + disambigationPageSuffix;
79 | }
80 |
81 | /* The Wikipedia search works like "I'm feeling lucky" on most Wikipedia instances. If there is a complete match, it will redirect us there. */
82 | location = `https://${languageCode}.wikipedia.org/w/index.php?searchToken=.&title=Special%3ASearch&ns0=1&search=${encodeURIComponent(s)}`;
83 | }
84 | })({
85 |
86 | languageCode: 'pt',
87 | languageNamesInEnglish: ['Portuguese'],
88 | disambigationPageSuffix: ' (desambiguação)',
89 |
90 | });
91 |
--------------------------------------------------------------------------------
/search/wikipedia/ruw.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text in the Russian Wikipedia.
3 | *
4 | * Use `--dis` as the first parameter to show the disambiguation page, if any.
5 | *
6 | * E.g. `enw --dis 1` would open `1 (disambiguation)`, which is a lot faster to
7 | * type then `enw 1 (disambiguation)`, and also works for the non-English
8 | * Wikipedia instances, which use other words for “disambiguation”.
9 | *
10 | * @title Russian Wikipedia
11 | * @keyword ruw
12 | */
13 | (function (config) {
14 | const {languageCode, languageNamesInEnglish, disambigationPageSuffix} = config;
15 | /* Try to get the parameter string from the bookmarklet/search query.
16 | Fall back to the current text selection, if any. If those options
17 | both fail, prompt the user.
18 | */
19 | var s = (function () { /*%s*/; }).toString()
20 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
21 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
22 | .replace(/\u0025s/, '');
23 |
24 | /**
25 | * Get the active text selection, diving into frames and
26 | * text controls when necessary and possible.
27 | */
28 | function getActiveSelection(doc) {
29 | if (arguments.length === 0) {
30 | doc = document;
31 | }
32 |
33 | if (!doc || typeof doc.getSelection !== 'function') {
34 | return '';
35 | }
36 |
37 | if (!doc.activeElement) {
38 | return doc.getSelection() + '';
39 | }
40 |
41 | var activeElement = doc.activeElement;
42 |
43 | /* Recurse for FRAMEs and IFRAMEs. */
44 | try {
45 | if (
46 | typeof activeElement.contentDocument === 'object'
47 | && activeElement.contentDocument !== null
48 | ) {
49 | return getActiveSelection(activeElement.contentDocument);
50 | }
51 | } catch (e) {
52 | return doc.getSelection() + '';
53 | }
54 |
55 | /* Get the selection from inside a text control. */
56 | if (typeof activeElement.value === 'string') {
57 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
58 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
59 | }
60 |
61 | return activeElement.value;
62 | }
63 |
64 | /* Get the normal selection. */
65 | return doc.getSelection() + '';
66 | }
67 |
68 | if (s === '') {
69 | s = getActiveSelection() || prompt(`Please enter the subject to look up in the ${languageNamesInEnglish.join('/')} Wikipedia:`);
70 | } else {
71 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
72 | }
73 |
74 | if (s) {
75 | /* Open the disambigation page for queries like `enw --dis Foo`. */
76 | let matches = s.match(/^\s*--dis\s*(.+)/);
77 | if (matches) {
78 | s = matches[1] + disambigationPageSuffix;
79 | }
80 |
81 | /* The Wikipedia search works like "I'm feeling lucky" on most Wikipedia instances. If there is a complete match, it will redirect us there. */
82 | location = `https://${languageCode}.wikipedia.org/w/index.php?searchToken=.&title=Special%3ASearch&ns0=1&search=${encodeURIComponent(s)}`;
83 | }
84 | })({
85 |
86 | languageCode: 'ru',
87 | languageNamesInEnglish: ['Russian'],
88 | disambigationPageSuffix: ' (значения)',
89 |
90 | });
91 |
--------------------------------------------------------------------------------
/search/wikipedia/svw.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text in the Swedish Wikipedia.
3 | *
4 | * Use `--dis` as the first parameter to show the disambiguation page, if any.
5 | *
6 | * E.g. `enw --dis 1` would open `1 (disambiguation)`, which is a lot faster to
7 | * type then `enw 1 (disambiguation)`, and also works for the non-English
8 | * Wikipedia instances, which use other words for “disambiguation”.
9 | *
10 | * @title Swedish Wikipedia
11 | * @keyword svw
12 | */
13 | (function (config) {
14 | const {languageCode, languageNamesInEnglish, disambigationPageSuffix} = config;
15 | /* Try to get the parameter string from the bookmarklet/search query.
16 | Fall back to the current text selection, if any. If those options
17 | both fail, prompt the user.
18 | */
19 | var s = (function () { /*%s*/; }).toString()
20 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
21 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
22 | .replace(/\u0025s/, '');
23 |
24 | /**
25 | * Get the active text selection, diving into frames and
26 | * text controls when necessary and possible.
27 | */
28 | function getActiveSelection(doc) {
29 | if (arguments.length === 0) {
30 | doc = document;
31 | }
32 |
33 | if (!doc || typeof doc.getSelection !== 'function') {
34 | return '';
35 | }
36 |
37 | if (!doc.activeElement) {
38 | return doc.getSelection() + '';
39 | }
40 |
41 | var activeElement = doc.activeElement;
42 |
43 | /* Recurse for FRAMEs and IFRAMEs. */
44 | try {
45 | if (
46 | typeof activeElement.contentDocument === 'object'
47 | && activeElement.contentDocument !== null
48 | ) {
49 | return getActiveSelection(activeElement.contentDocument);
50 | }
51 | } catch (e) {
52 | return doc.getSelection() + '';
53 | }
54 |
55 | /* Get the selection from inside a text control. */
56 | if (typeof activeElement.value === 'string') {
57 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
58 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
59 | }
60 |
61 | return activeElement.value;
62 | }
63 |
64 | /* Get the normal selection. */
65 | return doc.getSelection() + '';
66 | }
67 |
68 | if (s === '') {
69 | s = getActiveSelection() || prompt(`Please enter the subject to look up in the ${languageNamesInEnglish.join('/')} Wikipedia:`);
70 | } else {
71 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
72 | }
73 |
74 | if (s) {
75 | /* Open the disambigation page for queries like `enw --dis Foo`. */
76 | let matches = s.match(/^\s*--dis\s*(.+)/);
77 | if (matches) {
78 | s = matches[1] + disambigationPageSuffix;
79 | }
80 |
81 | /* The Wikipedia search works like "I'm feeling lucky" on most Wikipedia instances. If there is a complete match, it will redirect us there. */
82 | location = `https://${languageCode}.wikipedia.org/w/index.php?searchToken=.&title=Special%3ASearch&ns0=1&search=${encodeURIComponent(s)}`;
83 | }
84 | })({
85 |
86 | languageCode: 'sv',
87 | languageNamesInEnglish: ['Swedish'],
88 | disambigationPageSuffix: ' (olika betydelser)',
89 |
90 | });
91 |
--------------------------------------------------------------------------------
/search/wikipedia/viw.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text in the Vietnamese Wikipedia.
3 | *
4 | * Use `--dis` as the first parameter to show the disambiguation page, if any.
5 | *
6 | * E.g. `enw --dis 1` would open `1 (disambiguation)`, which is a lot faster to
7 | * type then `enw 1 (disambiguation)`, and also works for the non-English
8 | * Wikipedia instances, which use other words for “disambiguation”.
9 | *
10 | * @title Vietnamese Wikipedia
11 | * @keyword viw
12 | */
13 | (function (config) {
14 | const {languageCode, languageNamesInEnglish, disambigationPageSuffix} = config;
15 | /* Try to get the parameter string from the bookmarklet/search query.
16 | Fall back to the current text selection, if any. If those options
17 | both fail, prompt the user.
18 | */
19 | var s = (function () { /*%s*/; }).toString()
20 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
21 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
22 | .replace(/\u0025s/, '');
23 |
24 | /**
25 | * Get the active text selection, diving into frames and
26 | * text controls when necessary and possible.
27 | */
28 | function getActiveSelection(doc) {
29 | if (arguments.length === 0) {
30 | doc = document;
31 | }
32 |
33 | if (!doc || typeof doc.getSelection !== 'function') {
34 | return '';
35 | }
36 |
37 | if (!doc.activeElement) {
38 | return doc.getSelection() + '';
39 | }
40 |
41 | var activeElement = doc.activeElement;
42 |
43 | /* Recurse for FRAMEs and IFRAMEs. */
44 | try {
45 | if (
46 | typeof activeElement.contentDocument === 'object'
47 | && activeElement.contentDocument !== null
48 | ) {
49 | return getActiveSelection(activeElement.contentDocument);
50 | }
51 | } catch (e) {
52 | return doc.getSelection() + '';
53 | }
54 |
55 | /* Get the selection from inside a text control. */
56 | if (typeof activeElement.value === 'string') {
57 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
58 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
59 | }
60 |
61 | return activeElement.value;
62 | }
63 |
64 | /* Get the normal selection. */
65 | return doc.getSelection() + '';
66 | }
67 |
68 | if (s === '') {
69 | s = getActiveSelection() || prompt(`Please enter the subject to look up in the ${languageNamesInEnglish.join('/')} Wikipedia:`);
70 | } else {
71 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
72 | }
73 |
74 | if (s) {
75 | /* Open the disambigation page for queries like `enw --dis Foo`. */
76 | let matches = s.match(/^\s*--dis\s*(.+)/);
77 | if (matches) {
78 | s = matches[1] + disambigationPageSuffix;
79 | }
80 |
81 | /* The Wikipedia search works like "I'm feeling lucky" on most Wikipedia instances. If there is a complete match, it will redirect us there. */
82 | location = `https://${languageCode}.wikipedia.org/w/index.php?searchToken=.&title=Special%3ASearch&ns0=1&search=${encodeURIComponent(s)}`;
83 | }
84 | })({
85 |
86 | languageCode: 'vi',
87 | languageNamesInEnglish: ['Vietnamese'],
88 | disambigationPageSuffix: ' (định hướng)',
89 |
90 | });
91 |
--------------------------------------------------------------------------------
/search/wikipedia/wikiv.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text in the English Wikivoyage.
3 | *
4 | * @title English Wikivoyage
5 | */
6 | (function wikiv() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the subject to look up in the English Wikivoyage:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | /* The Wikivoyage search works like "I'm feeling lucky" on most Wikivoyage instances. If there is a complete match, it will redirect us there. */
68 | location = 'https://en.wikivoyage.org/w/index.php?searchToken=&title=Special%3ASearch&search=' + encodeURIComponent(s);
69 | }
70 | })();
71 |
--------------------------------------------------------------------------------
/search/wikipedia/zhw.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Look up the specified or selected text in the Chinese Wikipedia.
3 | *
4 | * Use `--dis` as the first parameter to show the disambiguation page, if any.
5 | *
6 | * E.g. `enw --dis 1` would open `1 (disambiguation)`, which is a lot faster to
7 | * type then `enw 1 (disambiguation)`, and also works for the non-English
8 | * Wikipedia instances, which use other words for “disambiguation”.
9 | *
10 | * @title Chinese Wikipedia
11 | * @keyword zhw
12 | */
13 | (function (config) {
14 | const {languageCode, languageNamesInEnglish, disambigationPageSuffix} = config;
15 | /* Try to get the parameter string from the bookmarklet/search query.
16 | Fall back to the current text selection, if any. If those options
17 | both fail, prompt the user.
18 | */
19 | var s = (function () { /*%s*/; }).toString()
20 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
21 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
22 | .replace(/\u0025s/, '');
23 |
24 | /**
25 | * Get the active text selection, diving into frames and
26 | * text controls when necessary and possible.
27 | */
28 | function getActiveSelection(doc) {
29 | if (arguments.length === 0) {
30 | doc = document;
31 | }
32 |
33 | if (!doc || typeof doc.getSelection !== 'function') {
34 | return '';
35 | }
36 |
37 | if (!doc.activeElement) {
38 | return doc.getSelection() + '';
39 | }
40 |
41 | var activeElement = doc.activeElement;
42 |
43 | /* Recurse for FRAMEs and IFRAMEs. */
44 | try {
45 | if (
46 | typeof activeElement.contentDocument === 'object'
47 | && activeElement.contentDocument !== null
48 | ) {
49 | return getActiveSelection(activeElement.contentDocument);
50 | }
51 | } catch (e) {
52 | return doc.getSelection() + '';
53 | }
54 |
55 | /* Get the selection from inside a text control. */
56 | if (typeof activeElement.value === 'string') {
57 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
58 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
59 | }
60 |
61 | return activeElement.value;
62 | }
63 |
64 | /* Get the normal selection. */
65 | return doc.getSelection() + '';
66 | }
67 |
68 | if (s === '') {
69 | s = getActiveSelection() || prompt(`Please enter the subject to look up in the ${languageNamesInEnglish.join('/')} Wikipedia:`);
70 | } else {
71 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
72 | }
73 |
74 | if (s) {
75 | /* Open the disambigation page for queries like `enw --dis Foo`. */
76 | let matches = s.match(/^\s*--dis\s*(.+)/);
77 | if (matches) {
78 | s = matches[1] + disambigationPageSuffix;
79 | }
80 |
81 | /* The Wikipedia search works like "I'm feeling lucky" on most Wikipedia instances. If there is a complete match, it will redirect us there. */
82 | location = `https://${languageCode}.wikipedia.org/w/index.php?searchToken=.&title=Special%3ASearch&ns0=1&search=${encodeURIComponent(s)}`;
83 | }
84 | })({
85 |
86 | languageCode: 'zh',
87 | languageNamesInEnglish: ['Chinese'],
88 | disambigationPageSuffix: ' (消歧义)',
89 |
90 | });
91 |
--------------------------------------------------------------------------------
/search/yanimg.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Search Yandex with its reverse image search.
3 | *
4 | * @title Yandex.Images
5 | */
6 | (function yanimg() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter your Yandex.Images search query or image URL:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | var words = s.split(' '), matches;
68 |
69 | /* If the first parameter looks like a URL, use Yandex’s reverse image search. */
70 | if (words[0].match(/^(\w+:(\/\/)?)?[^\s]+(\.[^\s]+)+\//))
71 | {
72 | location = 'https://yandex.com/images/search?rpt=imageview&url=' + encodeURIComponent(words[0]) + '&text=' + encodeURIComponent(words.slice(1).join(' '));
73 | return;
74 | }
75 |
76 | location = 'https://yandex.com/images/search?text=' + encodeURIComponent(s);
77 | }
78 | })();
79 |
--------------------------------------------------------------------------------
/search/yttop.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Search YouTube for the specified or selected text inside “topic” videos,
3 | * using Invidious (“an alternative front-end to YouTube”).
4 | *
5 | * “Topic” videos are the official channels for artists/bands/musicians and can
6 | * be recognized by either “ - Topic” or “🎵” suffixed to the name. However, it
7 | * is easier to search for the text “Provided to YouTube by”, which is at the
8 | * start of the auto-generated description for music “videos”.
9 | *
10 | * @title YouTube topic search
11 | */
12 | (function yttop() {
13 | /* Try to get the parameter string from the bookmarklet/search query.
14 | Fall back to the current text selection, if any. If those options
15 | both fail, prompt the user.
16 | */
17 | var s = (function () { /*%s*/; }).toString()
18 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
19 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
20 | .replace(/\u0025s/, '');
21 |
22 | /**
23 | * Get the active text selection, diving into frames and
24 | * text controls when necessary and possible.
25 | */
26 | function getActiveSelection(doc) {
27 | if (arguments.length === 0) {
28 | doc = document;
29 | }
30 |
31 | if (!doc || typeof doc.getSelection !== 'function') {
32 | return '';
33 | }
34 |
35 | if (!doc.activeElement) {
36 | return doc.getSelection() + '';
37 | }
38 |
39 | var activeElement = doc.activeElement;
40 |
41 | /* Recurse for FRAMEs and IFRAMEs. */
42 | try {
43 | if (
44 | typeof activeElement.contentDocument === 'object'
45 | && activeElement.contentDocument !== null
46 | ) {
47 | return getActiveSelection(activeElement.contentDocument);
48 | }
49 | } catch (e) {
50 | return doc.getSelection() + '';
51 | }
52 |
53 | /* Get the selection from inside a text control. */
54 | if (typeof activeElement.value === 'string') {
55 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
56 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
57 | }
58 |
59 | return activeElement.value;
60 | }
61 |
62 | /* Get the normal selection. */
63 | return doc.getSelection() + '';
64 | }
65 |
66 | if (s === '') {
67 | s = getActiveSelection() || prompt('Please enter your YouTube topic search query:');
68 | } else {
69 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
70 | }
71 |
72 | if (s) {
73 | s = s.replace(/\uFEFF/g, '');
74 |
75 | location = 'https://yewtu.be/search?q=' + encodeURIComponent(s + ' "Provided to YouTube by"');
76 | }
77 | })();
78 |
--------------------------------------------------------------------------------
/site-specific/README:
--------------------------------------------------------------------------------
1 | Site-specific
2 |
3 | Might as well turn these into Greasemonkey scripts one day.
4 |
--------------------------------------------------------------------------------
/site-specific/discogs.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Search the Discogs master release for the given text.
3 | *
4 | * I prefer searching for the master record instead of a specific release, to
5 | * get more “general” info.
6 | *
7 | * @title Search Discogs
8 | */
9 | (function discogs(document) {
10 | 'use strict';
11 |
12 | /* Try to get the parameter string from the bookmarklet/search query.
13 | * Fall back to the current text selection, if any. If those options
14 | * both fail, prompt the user. */
15 | let s = (function () { /*%s*/; }).toString()
16 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
17 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
18 | .replace(/\u0025s/, '');
19 |
20 | /**
21 | * Get the active text selection, diving into frames and
22 | * text controls when necessary and possible.
23 | */
24 | function getActiveSelection(document) {
25 | if (!document || typeof document.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!document.activeElement) {
30 | return document.getSelection() + '';
31 | }
32 |
33 | const activeElement = document.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return document.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return document.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection(document) || prompt('Please enter the text to search in the Discogs release masters database:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection(document) + '$2');
64 | }
65 |
66 | if (s) {
67 | location = 'https://www.discogs.com/search/?type=master&limit=250&sort=year%2Casc&q=' + encodeURIComponent(s);
68 | }
69 | })(document);
70 |
--------------------------------------------------------------------------------
/site-specific/emo.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Search Emojipedia for the given text or emoji.
3 | *
4 | * @title Emojipedia
5 | */
6 | (function emo(document) {
7 | 'use strict';
8 |
9 | /* Try to get the parameter string from the bookmarklet/search query.
10 | * Fall back to the current text selection, if any. If those options
11 | * both fail, prompt the user. */
12 | let s = (function () { /*%s*/; }).toString()
13 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
14 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
15 | .replace(/\u0025s/, '');
16 |
17 | /**
18 | * Get the active text selection, diving into frames and
19 | * text controls when necessary and possible.
20 | */
21 | function getActiveSelection(document) {
22 | if (!document || typeof document.getSelection !== 'function') {
23 | return '';
24 | }
25 |
26 | if (!document.activeElement) {
27 | return document.getSelection() + '';
28 | }
29 |
30 | const activeElement = document.activeElement;
31 |
32 | /* Recurse for FRAMEs and IFRAMEs. */
33 | try {
34 | if (
35 | typeof activeElement.contentDocument === 'object'
36 | && activeElement.contentDocument !== null
37 | ) {
38 | return getActiveSelection(activeElement.contentDocument);
39 | }
40 | } catch (e) {
41 | return document.getSelection() + '';
42 | }
43 |
44 | /* Get the selection from inside a text control. */
45 | if (typeof activeElement.value === 'string') {
46 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
47 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
48 | }
49 |
50 | return activeElement.value;
51 | }
52 |
53 | /* Get the normal selection. */
54 | return document.getSelection() + '';
55 | }
56 |
57 | if (s === '') {
58 | s = getActiveSelection(document) || prompt('Please specify the text or emoji to search on Emojipedia.org:');
59 | } else {
60 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection(document) + '$2');
61 | }
62 |
63 | if (s) {
64 | location = 'https://emojipedia.org/search/?q=' + encodeURIComponent(s);
65 | }
66 | })(document);
67 |
--------------------------------------------------------------------------------
/site-specific/githublet.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Put a bookmarklet's code on GitHub in a TEXTAREA so it is easy to copy.
3 | *
4 | * I use this because selecting and copying bookmarklet code to put them in my
5 | * Safari on iOS is a pain.
6 | *
7 | * @title GitHublet
8 | */
9 | (function githublet() {
10 | var codeContainer = document.querySelector('.file .lines .highlight');
11 | if (!codeContainer) {
12 | alert('No file contents found on page.');
13 | return;
14 | }
15 |
16 | /* Extract the source code from the separately highlighted lines. */
17 | var lineContainers = Array.prototype.slice.call(codeContainer.querySelectorAll('.line'));
18 | if (!lineContainers.length) {
19 | alert('No lines found in file contents.');
20 | return;
21 | }
22 | var lines = [];
23 | lineContainers.forEach(function (line) {
24 | lines.push(line.textContent);
25 | });
26 |
27 | /* Replace the code with a TEXTAREA of more or less the same dimensions. */
28 | var textarea = document.createElementNS('http://www.w3.org/1999/xhtml', 'textarea');
29 | textarea.value = 'javascript:' + lines.join('\n');
30 | var codeContainerStyle = window.getComputedStyle(codeContainer);
31 | ['width', 'height', 'margin', 'padding'].forEach(function (property) {
32 | if (property === 'width' || property === 'height') {
33 | textarea.style[property] = codeContainerStyle[property];
34 | } else {
35 | ['Top', 'Right', 'Bottom', 'Left'].forEach(function (edge) {
36 | textarea.style[property + edge] = codeContainerStyle[property + edge];
37 | });
38 | }
39 | });
40 | textarea.style.border = 0;
41 | textarea.style.lineHeight = lineContainers[0].offsetHeight + 'px';
42 | var lineContainerStyle = window.getComputedStyle(lineContainers[0]);
43 | ['fontFamily', 'fontSize', 'paddingLeft'].forEach(function (property) {
44 | textarea.style[property] = lineContainerStyle[property];
45 | });
46 | codeContainer.parentNode.replaceChild(textarea, codeContainer);
47 | textarea.focus();
48 | textarea.select();
49 | })();
50 |
--------------------------------------------------------------------------------
/site-specific/printriodos.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Improve the Triodos account statement print-out.
3 | *
4 | * This bookmarklets adds the account balance after each operation, which
5 | * makes it easier to keep track of the balance throughout the year/month.
6 | *
7 | * It also darkens the odd row background so it stands out more when printing
8 | * in black and white. (Remember to check the "Print background colours and
9 | * images" box.)
10 | *
11 | * @title Triodos pretty-printer
12 | */
13 | (function printriodos() {
14 | var table = document.querySelector('table[id$=":searchResultTable"]');
15 |
16 | /* Add a column with the total after each movement. */
17 | var total = parseFloat(
18 | document.querySelector('.dataView table:first-child tr:first-child td:last-child')
19 | .textContent
20 | .replace('.', '')
21 | .replace(',', '.')
22 | );
23 |
24 | Array.prototype.slice.call(table.querySelectorAll('tbody[id$="searchResultTable:tb"] td:last-child')).reverse().forEach(function (td) {
25 | td.style.textAlign = 'right';
26 |
27 | var amount = td.textContent.replace('.', '').replace(',', '.');
28 | total = (parseFloat(total) + parseFloat(amount)).toFixed(2);
29 | var newTd = td.cloneNode();
30 | newTd.textContent = total.replace('.', ',').replace(/([0-9])([0-9]{3}),/, '$1.$2,');
31 | td.classList.remove('lastItem');
32 | td.parentNode.appendChild(newTd);
33 | });
34 |
35 | /* Add a header cell for the column we just added. */
36 | var th = table.querySelector('thead th:last-child');
37 | var newTh = th.cloneNode();
38 | newTh.textContent = 'Saldo (EUR)';
39 | th.parentNode.appendChild(newTh);
40 |
41 | /* Keep the pretty background colours when printing. (This needs to be enabled in the printer options dialog, too.) */
42 | Array.prototype.slice.call(document.querySelectorAll('link[rel="StyleSheet"][media="screen"]')).forEach(function (link) {
43 | link.media = 'all';
44 | });
45 |
46 | /* Avoid double borders on the last cell. */
47 | document.head.appendChild(document.createElementNS('http://www.w3.org/1999/xhtml', 'style')).textContent = '.dataView th:last-child, .dataView td:last-child { border-right: 0; }';
48 |
49 | /* Make the difference between rows more pronounced. */
50 | document.head.appendChild(document.createElementNS('http://www.w3.org/1999/xhtml', 'style')).textContent = '.dataView tr.evenRow th, .dataView tr.evenRow td { background-color: #cee; }';
51 | })();
52 |
--------------------------------------------------------------------------------
/site-specific/redtop.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Show the top posts for the current/selected subreddit.
3 | *
4 | * I hardly ever use Reddit, but when I do, I’m most likely looking at a
5 | * humour-related subreddit to have a laugh, so “just play the hits, dammit!”.
6 | *
7 | * @title Subreddit’s top posts
8 | */
9 | (function redtop() {
10 | 'use strict';
11 |
12 | /* Try to get the parameter string from the bookmarklet/search query.
13 | * Fall back to the current text selection, if any. If those options
14 | * both fail, prompt the user. */
15 | let s = (function () { /*%s*/; }).toString()
16 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
17 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
18 | .replace(/\u0025s/, '');
19 |
20 | /**
21 | * Get the active text selection, diving into frames and
22 | * text controls when necessary and possible.
23 | */
24 | function getActiveSelection(document) {
25 | if (!document || typeof document.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!document.activeElement) {
30 | return document.getSelection() + '';
31 | }
32 |
33 | const activeElement = document.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return document.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return document.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection(document);
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection(document) + '$2');
64 | }
65 |
66 | const subredditRegexp = /\b(?https?:\/\/([^\/]+\.)?reddit\.com\/)?(?r\/[a-zA-Z0-9_-]+)/;
67 |
68 | /* Check the bookmarklet parameter or the selected text. */
69 | let subredditMatches = s.match(subredditRegexp);
70 |
71 | /* Check the current URL. */
72 | if (!subredditMatches) {
73 | subredditMatches = location.href.match(subredditRegexp);
74 | }
75 |
76 | /* Prompt for the subreddit name or URL. */
77 | if (!subredditMatches) {
78 | s = prompt('Please enter the `r/SubredditNameHere` or the full `https://www.reddit.com/r/SubredditNameHere` URL to view its top posts.', location);
79 | subredditMatches = s.match(subredditRegexp);
80 | }
81 |
82 | if (!subredditMatches) {
83 | alert(`“${s}” does not look like a valid subreddit.`);
84 | return;
85 | }
86 |
87 | location = (subredditMatches.groups.redditUrlPrefix || 'https://www.reddit.com/')
88 | + subredditMatches?.groups.subredditName
89 | + '/top/?sort=top&t=all';
90 | })();
91 |
--------------------------------------------------------------------------------
/site-specific/somanp.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Show the currently playing track in the window/tab title on SomaFM Player
3 | * pages like https://somafm.com/player/#/now-playing/cliqhop
4 | *
5 | * @title SomaFM np
6 | */
7 | (function somanp() {
8 | var playlistContainer = document.querySelector('.now-playing .list-body');
9 | if (!playlistContainer) {
10 | return;
11 | }
12 |
13 | var originalTitle = document.title;
14 |
15 | function updateTitle() {
16 | var artistNode = playlistContainer.querySelector('.row > :nth-child(2)');
17 | var titleNode = playlistContainer.querySelector('.row > :nth-child(3)');
18 |
19 | if (!artistNode || !titleNode) {
20 | return;
21 | }
22 |
23 | document.title = artistNode.textContent
24 | + ' - ' + titleNode.textContent.toLowerCase()
25 | + ' | ' + originalTitle;
26 | }
27 |
28 | var observer = new MutationObserver(updateTitle);
29 |
30 | observer.observe(playlistContainer, {
31 | childList: true,
32 | subtree: true
33 | });
34 |
35 | updateTitle();
36 | })();
37 |
--------------------------------------------------------------------------------
/site-specific/strava/README:
--------------------------------------------------------------------------------
1 | Strava
2 |
3 | Utilities for “the social network for athletes”.
4 |
--------------------------------------------------------------------------------
/site-specific/strava/pace2speed.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Convert pace (e.g. “4:38/km”) to speed (e.g. “12.95 km/h”) on a web page.
3 | *
4 | * @title Pace2Speed
5 | */
6 | (function pace2speed() {
7 | 'use strict';
8 |
9 | /* Recursively execute the logic on the document and its sub-documents. */
10 | function execute(document) {
11 | const possiblePaceLeafNodes = [];
12 |
13 | Array.from(document.querySelectorAll('body *')).forEach(node => {
14 | const matches = node.textContent.match(/^\s*(?\d+)\s*(:|'|′|min(ute)?s?)\s*(?\d+)\s*(''|"|″|sec(ond)?s?)?\s*\/\s*(?km|mi)/)
15 | ?? node.textContent.match(/^\s*(?\d+)\s*:\s*(?\d+)\s*(?:min(?:utes?)?)\s*\/\s*(?km|mi)/);
16 |
17 | if (!matches) {
18 | return;
19 | }
20 |
21 | const durationInSeconds = parseInt(matches.groups.minutes, 10) * 60 + parseInt(matches.groups.seconds, 10);
22 | let speedInKilometersPerHour = 3600 / durationInSeconds;
23 | if (matches.groups.unit === 'mi') {
24 | speedInKilometersPerHour *= 1.60934;
25 | }
26 | speedInKilometersPerHour = speedInKilometersPerHour.toFixed(1);
27 |
28 | node.setAttribute('xxxJanPace2Speed', speedInKilometersPerHour);
29 | possiblePaceLeafNodes.push(node);
30 | });
31 |
32 | /* Replace the text content of the deepest nodes. */
33 | possiblePaceLeafNodes.forEach(node => {
34 | if (node.querySelector('[xxxJanPace2Speed]')) {
35 | return;
36 | }
37 |
38 | node.textContent = `${node.getAttribute('xxxJanPace2Speed')} km/h`;
39 | });
40 |
41 | /* Recurse for frames and IFRAMEs. */
42 | try {
43 | Array.from(
44 | document.querySelectorAll('frame, iframe, object[type^="text/html"], object[type^="application/xhtml+xml"]')
45 | ).forEach(
46 | elem => execute(elem.contentDocument)
47 | );
48 | } catch (e) {
49 | /* Catch and ignore exceptions for out-of-domain access. */
50 | }
51 | }
52 |
53 | execute(document);
54 | })();
55 |
--------------------------------------------------------------------------------
/site-specific/strava/sact.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Search for a Strava activity.
3 | *
4 | * @title Strava activity
5 | */
6 | (function sact() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the Strava activity name to look for:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | location = 'https://www.strava.com/athlete/training?keywords=' + encodeURIComponent(s);
68 | }
69 | })();
70 |
--------------------------------------------------------------------------------
/site-specific/strava/sath.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Search for a Strava member (athlete).
3 | *
4 | * @title Strava athlete
5 | */
6 | (function sath() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the Strava athlete/member name to look for:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | location = 'https://www.strava.com/athletes/search?utf8=%E2%9C%93&text=' + encodeURIComponent(s);
68 | }
69 | })();
70 |
--------------------------------------------------------------------------------
/site-specific/strava/sclub.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Search for a Strava club.
3 | *
4 | * @title Strava club
5 | */
6 | (function sclub() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the Strava club name to look for:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | location = 'https://www.strava.com/clubs/search?utf8=%E2%9C%93&text=' + encodeURIComponent(s);
68 | }
69 | })();
70 |
--------------------------------------------------------------------------------
/site-specific/strava/sseg.js:
--------------------------------------------------------------------------------
1 | /**
2 | * Search for a Strava segment.
3 | *
4 | * @title Strava segment
5 | */
6 | (function sseg() {
7 | /* Try to get the parameter string from the bookmarklet/search query.
8 | Fall back to the current text selection, if any. If those options
9 | both fail, prompt the user.
10 | */
11 | var s = (function () { /*%s*/; }).toString()
12 | .replace(/^function\s*\(\s*\)\s*\{\s*\/\*/, '')
13 | .replace(/\*\/\s*\;?\s*\}\s*$/, '')
14 | .replace(/\u0025s/, '');
15 |
16 | /**
17 | * Get the active text selection, diving into frames and
18 | * text controls when necessary and possible.
19 | */
20 | function getActiveSelection(doc) {
21 | if (arguments.length === 0) {
22 | doc = document;
23 | }
24 |
25 | if (!doc || typeof doc.getSelection !== 'function') {
26 | return '';
27 | }
28 |
29 | if (!doc.activeElement) {
30 | return doc.getSelection() + '';
31 | }
32 |
33 | var activeElement = doc.activeElement;
34 |
35 | /* Recurse for FRAMEs and IFRAMEs. */
36 | try {
37 | if (
38 | typeof activeElement.contentDocument === 'object'
39 | && activeElement.contentDocument !== null
40 | ) {
41 | return getActiveSelection(activeElement.contentDocument);
42 | }
43 | } catch (e) {
44 | return doc.getSelection() + '';
45 | }
46 |
47 | /* Get the selection from inside a text control. */
48 | if (typeof activeElement.value === 'string') {
49 | if (activeElement.selectionStart !== activeElement.selectionEnd) {
50 | return activeElement.value.substring(activeElement.selectionStart, activeElement.selectionEnd);
51 | }
52 |
53 | return activeElement.value;
54 | }
55 |
56 | /* Get the normal selection. */
57 | return doc.getSelection() + '';
58 | }
59 |
60 | if (s === '') {
61 | s = getActiveSelection() || prompt('Please enter the Strava segment title to look for:');
62 | } else {
63 | s = s.replace(/(^|\s|")~("|\s|$)/g, '$1' + getActiveSelection() + '$2');
64 | }
65 |
66 | if (s) {
67 | location = 'https://www.strava.com/segments/search?utf8=%E2%9C%93&filter_type=cycling&min-cat=0&max-cat=5&terrain=all&keywords=' + encodeURIComponent(s);
68 | }
69 | })();
70 |
--------------------------------------------------------------------------------
/tests/README:
--------------------------------------------------------------------------------
1 | A collection of saved web pages to test my bookmarklets.
2 |
--------------------------------------------------------------------------------