Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

User Script suggestions #66

Open
ZitaNemeckova opened this issue Mar 17, 2020 · 6 comments
Open

User Script suggestions #66

ZitaNemeckova opened this issue Mar 17, 2020 · 6 comments

Comments

@ZitaNemeckova
Copy link
Contributor

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 😺

@ZitaNemeckova ZitaNemeckova changed the title User Script User Script suggestions Mar 17, 2020
@himdel
Copy link
Contributor

himdel commented Mar 23, 2020

// ==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();

@himdel
Copy link
Contributor

himdel commented Mar 23, 2020

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;
  }
`);

@himdel
Copy link
Contributor

himdel commented Mar 23, 2020

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');

@himdel
Copy link
Contributor

himdel commented Mar 23, 2020

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)

@himdel
Copy link
Contributor

himdel commented Mar 23, 2020

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..

)

@himdel
Copy link
Contributor

himdel commented Mar 23, 2020

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants