Open ZitaNemeckova opened 4 years ago
// ==UserScript==
// @name wiki test
// @match https://en.wikipedia.org/wiki/Userscript
// ==/UserScript==
// change document title
document.title = '!@#$%^&*()';
// change element text (article name)
document.querySelector('#firstHeading').innerText = 'Magic';
// change element style (wikipedia logo)
document.querySelector('.mw-wiki-logo').style.backgroundImage = 'url(https://placekitten.com/160/160)';
// remove element (table of contents)
document.querySelector('#toc').remove();
Add CSS (mdn docs):
// ==UserScript==
// @name wiki test2
// @match https://en.wikipedia.org/wiki/Userscript
// ==/UserScript==
var sheet = document.styleSheets[0];
sheet.insertRule('#firstHeading { color: blue; }', sheet.cssRules.length);
Or using greasemonkey extensions (note that @grant
- tampermonkey docs)..
// ==UserScript==
// @name wiki test3
// @match https://en.wikipedia.org/wiki/Userscript
// @grant GM_addStyle
// ==/UserScript==
// change document style
GM_addStyle(`
body {
background-color: red;
}
`);
More extensions - copy first paragraph of any wikipedia article to clipboard and pop up a notification..
also see @match
.
// ==UserScript==
// @name wiki test4
// @match https://*.wikipedia.org/wiki/*
// @grant GM_notification
// @grant GM_setClipboard
// ==/UserScript==
const text = document.querySelector('.mw-parser-output p').innerText;
GM_setClipboard(text, 'text');
GM_notification(text, 'Copied to clipboard');
Browser APIs - mutation observer - perform action on infiniscroll
// ==UserScript==
// @name youtube opacity by length
// @match https://www.youtube.com/watch?v=*
// ==/UserScript==
const playlistSelector = 'ytd-watch-next-secondary-results-renderer';
const itemSelector = 'ytd-compact-video-renderer';
// wait for an element to appear
const waitFor = (selector, callback) => {
let present = !! document.querySelector(selector);
if (present) {
callback();
} else {
setTimeout(() => waitFor(selector, callback), 1000);
}
};
const updateElement = (element) => {
console.log('video', element.data.videoId, element.data.lengthText.simpleText);
let short = element.data.lengthText.simpleText.match(/^(\d+):(\d+)$/);
let long = element.data.lengthText.simpleText.match(/^(\d+):(\d+):(\d+)$/);
let opacity = 0.1;
if (short && short[1] == '0') { // under a minute
opacity = 1;
} else if (! long) { // less than an hour
opacity = 1 / Math.sqrt(Number(short[1])); // 1 / sqrt(minutes)
}
element.style.opacity = opacity;
};
// wait for inital load
waitFor(playlistSelector, () => {
// run on load..
document.querySelectorAll(itemSelector).forEach(updateElement);
// set up lazy load watching
const targetNode = document.querySelector(playlistSelector);
const observerOptions = {
childList: true,
subtree: true,
};
const callback = function(mutationList, observer) {
mutationList.forEach((mutation) => {
const matchingElements = Array.from(mutation.addedNodes || []).filter((e) => e.matches && e.matches(itemSelector));
matchingElements.forEach(updateElement);
});
};
const observer = new MutationObserver(callback);
observer.observe(targetNode, observerOptions);
});
(mention console.dir
, native web components)
Add own elements, actions..
// ==UserScript==
// @name youtube seen
// @match https://www.youtube.com/watch?v=*
// ==/UserScript==
const playlistSelector = 'ytd-watch-next-secondary-results-renderer';
const itemSelector = 'ytd-compact-video-renderer';
// wait for an element to appear
const waitFor = (selector, callback) => {
let present = !! document.querySelector(selector);
if (present) {
callback();
} else {
setTimeout(() => waitFor(selector, callback), 1000);
}
};
const updateElement = (element) => {
const seen = new Set(JSON.parse(window.localStorage.seen || '[]'));
if (seen.has(element.data.videoId)) {
// element.remove();
element.style.opacity = 0.5;
}
};
const markSeen = (video) => {
const seen = JSON.parse(window.localStorage.seen || '[]');
seen.push(video);
window.localStorage.seen = JSON.stringify(seen);
};
const addButton = () => {
const params = window.location.search.substring(1).split('&').map((str) => str.split('=').map((s) => decodeURIComponent(s))).map(([a, b]) => ({[a]: b})).reduce((o,r) => ({...r, ...o}), {});
const title = document.querySelector('.title.ytd-video-primary-info-renderer');
const button = document.createElement('button');
button.textContent = "Mark as seen";
button.onclick = () => {
markSeen(params.v);
button.disabled = true;
};
// already seen
if ((new Set(JSON.parse(window.localStorage.seen || '[]'))).has(params.v)) {
button.textContent = "(seen)";
button.disabled = true;
}
title.append(button);
};
waitFor('ytd-video-primary-info-renderer', addButton);
// wait for inital load
waitFor(playlistSelector, () => {
// run on load..
document.querySelectorAll(itemSelector).forEach(updateElement);
// set up lazy load watching
const targetNode = document.querySelector(playlistSelector);
const observerOptions = {
childList: true,
subtree: true,
};
const callback = function(mutationList, observer) {
mutationList.forEach((mutation) => {
const matchingElements = Array.from(mutation.addedNodes || []).filter((e) => e.matches && e.matches(itemSelector));
matchingElements.forEach(updateElement);
});
};
const observer = new MutationObserver(callback);
observer.observe(targetNode, observerOptions);
});
(diff:
--- a 2020-03-23 23:11:04.031747349 +0000
+++ b 2020-03-23 23:11:17.167840372 +0000
@@ -1,5 +1,5 @@
// ==UserScript==
-// @name youtube opacity by length
+// @name youtube seen
// @match https://www.youtube.com/watch?v=*
// ==/UserScript==
@@ -17,21 +17,41 @@
};
const updateElement = (element) => {
- console.log('video', element.data.videoId, element.data.lengthText.simpleText);
-
- let short = element.data.lengthText.simpleText.match(/^(\d+):(\d+)$/);
- let long = element.data.lengthText.simpleText.match(/^(\d+):(\d+):(\d+)$/);
-
- let opacity = 0.1;
- if (short && short[1] == '0') { // under a minute
- opacity = 1;
- } else if (! long) { // less than an hour
- opacity = 1 / Math.sqrt(Number(short[1])); // 1 / sqrt(minutes)
- }
-
- element.style.opacity = opacity;
+ const seen = new Set(JSON.parse(window.localStorage.seen || '[]'));
+ if (seen.has(element.data.videoId)) {
+ // element.remove();
+ element.style.opacity = 0.5;
+ }
};
+const markSeen = (video) => {
+ const seen = JSON.parse(window.localStorage.seen || '[]');
+ seen.push(video);
+ window.localStorage.seen = JSON.stringify(seen);
+};
+
+const addButton = () => {
+ const params = window.location.search.substring(1).split('&').map((str) => str.split('=').map((s) => decodeURIComponent(s))).map(([a, b]) => ({[a]: b})).reduce((o,r) => ({...r, ...o}), {});
+
+ const title = document.querySelector('.title.ytd-video-primary-info-renderer');
+ const button = document.createElement('button');
+ button.textContent = "Mark as seen";
+ button.onclick = () => {
+ markSeen(params.v);
+ button.disabled = true;
+ };
+
+ // already seen
+ if ((new Set(JSON.parse(window.localStorage.seen || '[]'))).has(params.v)) {
+ button.textContent = "(seen)";
+ button.disabled = true;
+ }
+
+ title.append(button);
+};
+
+waitFor('ytd-video-primary-info-renderer', addButton);
+
// wait for inital load
waitFor(playlistSelector, () => {
// run on load..
)
More examples..
damejidlo - Resort restaurant by reddit order (more votes is more important than better votes): https://github.com/himdel/dotfiles/blob/master/userjs/damejidlo.sort.js
flickr - Download button: https://github.com/himdel/dotfiles/blob/master/userjs/flickr.user.js
chrome - skip Redirect Notice on google lucky: https://github.com/himdel/dotfiles/blob/master/userjs/google%20lucky%20fix.user.js
xkcd - use keys, show caption : https://github.com/himdel/dotfiles/blob/master/userjs/xkcd_next.user.js
A liitle info https://openuserjs.org/about/Userscript-Beginners-HOWTO
Any suggestion what you'd like to write as a User Script, please write in comments below. Thanks 😺