Skip to content

Instantly share code, notes, and snippets.

@evandrocoan
Last active April 14, 2024 16:07
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 3 You must be signed in to fork a gist
  • Save evandrocoan/0e25dd233f3f99352a8147041809ba8d to your computer and use it in GitHub Desktop.
Save evandrocoan/0e25dd233f3f99352a8147041809ba8d to your computer and use it in GitHub Desktop.
# My Google Chrome Extensions.md
# Copyright (c) 2022-2024 Evandro Coan
#
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documentation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all
# copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
# SOFTWARE.

Disable chrome tab unloading

  1. chrome://discards/

  2. chrome://settings/?search=memory+saver

  3. chrome://flags/#modal-memory-saver

  4. chrome://flags/#probabilistic-memory-saver

  5. chrome://flags/#memory-saver-multi-state-mode

  6. https://superuser.com/questions/1353931/how-can-i-get-chrome-to-stop-killing-my-tabs-in-the-background/1774148#1774148

  7. Disable automatic tab discarding

    • Stops Chrome from suspending tabs, and reloading them when you switch to them.

Extentions

  1. To disable Chrome’s media control key extension to the Windows 10 volume OSD, follow these steps:

    1. https://www.chanhvuong.com/3954/disable-annoying-chrome-media-control-key-extension-to-windows-10-volume-osd/
    2. Using Chrome, browse to “chrome://flags/” to access the experimental hidden settings.
    3. Search for the “Hardware Media Key Handling” function.
    4. Disable it by changing the dropdown selection from Default to Disabled.
    5. Click the “Relaunch Now” button on the popup at the bottom.
  2. Read Aloud: A Text to Speech Voice Reader

    • lsdsoftware.com: Read aloud the current web-page article with one click, using text to speech (TTS). Supports 40+ languages.
  3. Lazy Tabs

    • Discard all inactive tabs (except pinned) at startup or by clicking an icon
  4. NordVPN - VPN proxy for privacy and security

    • Connect to the fastest VPN out there — NordVPN. Hide your IP, block ads, and be safe online with our VPN proxy extension for Chrome.
  5. Enhancer for Netflix, Crunchyroll

    • Show trailers, IMDb/Simkl ratings, secret categories and much more, on the Netflix page. Sync Netflix or Crunchyroll to Simkl.
  6. Postman

    • Postman is an American application that allows the testing of web APIs.
  7. YouTube Auto HD + FPS

    • Automatically set the video quality on YouTube according to its FPS!
  8. Web Scrobbler

    • Scrobble music all around the web!
  9. W Zoom, 1.0.17

    • A Chrome extension which can perform per-tab/per-origin/per-path zooming
  10. Discourse Forum Notifications

  11. Application Launcher for Drive (by Google)

    • Open Drive files directly from your browser in compatible applications installed on your computer.
  12. Full Page Screen Capture

    • Capture a screenshot of your current page in entirety and reliably—without requesting any extra permissions!
  13. GitHub Repository Size

    • Automatically adds repository size to GitHub's repository summary
  14. BackStop

  • Stop Backspace returning to previous page
  1. Google Docs Offline

  • Get things done offline with the Google Docs family of products.
  1. Isometric Contributions

  • Renders an isometric pixel view of GitHub contribution graphs.
  1. Notifier for GitHub

  • Displays your GitHub notifications unread count
  1. Open in new tab

  • Open links in new tab for a list of specified domains. Useful for sites such as hackernews
  1. Mute Tab 1.4

  • Restores the 'Mute Tab' functionality of versions prior to Chrome 71.
  1. Save to Pocket

  • Pocket Extension for Chrome - The best way to save articles, videos and more
  1. Shortkeys (Custom Keyboard Shortcuts)

  • Custom keyboard shortcuts for your browser
  1. Simple Speed Dial

  • A speed dial functionally similar to the one used in Opera.
  1. Ultra light newtab page with bookmarks on it

  • Ultra light new tab with bookmark navigator
  1. Web Scrobbler

  • Scrobble music all around the web!
  1. Session Buddy

  • Manage Browser Tabs and Bookmarks with Ease
  1. Selection Highlighter

  • Passively highlights occurrences of selected text. Maintains current text selection.
  1. Disable HTML5 Autoplay (Reloaded)

  • Disable autoplay and preloading of HTML5 video and audio players.
  1. Notifier for Gmail™

  • Multiple label and account notifier for Google Mail (Gmail)
  1. Change Timezone (Time Shift)

  • Easily change your timezone to a desired value and protect your privacy.
  1. Chromium Wheel Smooth Scroller

  • Make scroll behavior smooth, ease-in-out manner, customizable with dynamically plotted curve. With bouncy edge feature.
  1. Calculadora de jornada - Ahgora

  • Adiciona uma tabela com informações adicionais e a hora estimada de saída do trabalho na pagina de batidas de ponto do ahgora.
  1. Checker Plus for Google Calendar

  • See your next events, get meeting notifications and snooze events without opening the Google Calendar page!
  1. jQuery Injector

  • Inject jQuery into all frames on any page. jQuery Injector allows you to inject jQuery into every frame on a page so that you can use jQuery in the dev console.
  1. Chrome extension source viewer

  • View source code of Chrome extensions, Firefox addons or Opera extensions (crx/nex/xpi) from the Chrome web store and elsewhere.
  1. OpenList

  • Utilities to create and open lists of tabs.
  1. TabCopy

  • Quickly copy tabs to the clipboard
  1. Refined GitHub

  • Simplifies the GitHub interface and adds useful features
  • Features to disable, by filename: shorten-links add- move-marketplace-link-to-profile-dropdown set-default-repositories-type-to-sources infinite-scroll hide-useless-comments hide-watch-and-fork-count fit-textareas
  • Custom CSS ```css / fix GitHub Actions console output last line being half-cut */ body { line-height: 150%; }
/* Stop adding scroll bar on quoted blocks/images */
/* https://github.com/sindresorhus/refined-github/issues/2491 */
.comment-body blockquote,
.comment-body pre {
  max-height: none !important;
  overflow-y: visible !important;
}

/* How to remove the sticky issues top bar? */
/* https://github.com/sindresorhus/refined-github/issues/3086 */
.Box-header#js-issues-toolbar,
.Box#js-issues-toolbar > .Box-header {
  position: relative;
}
```
  1. Tampermonkey

    1. Auto scroll gitlab ci log

      // ==UserScript==
      // @name         Auto scroll gitlab ci log
      // @namespace    *
      // @version      0.1
      // @description  ...
      // @author       Evandro Coan
      //
      // @include http*://gitlab*
      //
      // @require http://code.jquery.com/jquery-3.4.1.min.js
      // ==/UserScript==
      //
      // https://gitlab.com/gitlab-org/gitlab/-/issues/37313 - Job Log Page is no longer auto scrolling to the bottom
      // https://stackoverflow.com/questions/3898130/check-if-a-user-has-scrolled-to-the-bottom/3898152
      //
      (function() {
          'use strict';
              function getDocHeight() {
              var D = document;
              return Math.max(
                  D.body.scrollHeight, D.documentElement.scrollHeight,
                  D.body.offsetHeight, D.documentElement.offsetHeight,
                  D.body.clientHeight, D.documentElement.clientHeight
              );
          }
          setInterval(function(){
                  if($(window).scrollTop() + $(window).height() > getDocHeight() - 300) {
                      $('button[data-testid="job-controller-scroll-bottom"]').click();
                  }
              },
              1000);
      })();
    2. Fix chatgpt auto-scrooling by always adding 500px at the bottom

      // ==UserScript==
      // @name         Fix chatgpt auto-scrolling by always adding 500px at the bottom
      // @namespace    http://tampermonkey.net/
      // @version      0.1
      // @description  Modify the height of the last HTML element with a data-testid attribute
      // @author       You
      // @match        https://chat.openai.com/*
      // @grant        none
      // ==/UserScript==
      
      (function() {
          'use strict';
          function setElementHeight() {
              //let elements = document.querySelectorAll('[data-role="assistant"]');  // use for superpower chatgpt chrome extension
              let elements = document.querySelectorAll('[data-testid^="conversation-turn"]');  // use for chatgpt vanilla
      
              let heightJump = 500;
              let jumpTimeoutInSeconds = 30;
              let lastElement = elements[elements.length - 1];
      
              if (lastElement)
              {
                  let height = lastElement.scrollHeight || -1;
                  let setMinHeight = parseInt(lastElement.style.minHeight, 10) || -1;
      
                  let lastHeight = parseInt(lastElement.getAttribute("data-last-scrool"), 10) || height;
                  let lastHeightCount = parseInt(lastElement.getAttribute("data-last-scrool-count"), 10) || 0;
      
                  // console.log(`height ${height}, lastHeight ${lastHeight}, setMinHeight ${setMinHeight}, lastHeightCount ${lastHeightCount}.`)
                  if (height > lastHeight) {
                      height += heightJump;
                      lastElement.style.minHeight = `${height}px`;
                  }
      
                  if( height == lastHeight )
                  {
                      if(lastHeightCount > jumpTimeoutInSeconds) {
                          // console.log(`Reseting height ${height} ${lastHeightCount}.`)
                          lastElement.style.minHeight = `auto`;
                      }
                      lastHeightCount += 1;
                  }
                  else {
                      lastHeightCount = 0;
                  }
      
                  lastElement.setAttribute("data-last-scrool", height);
                  lastElement.setAttribute("data-last-scrool-count", lastHeightCount);
              }
      
              let penultiLastElement = elements[elements.length - 2];
              let penultiLastElement2 = elements[elements.length - 3];
      
              if (penultiLastElement) {
                  penultiLastElement.style.minHeight = `auto`;
              }
              if (penultiLastElement2) {
                  penultiLastElement2.style.minHeight = `auto`;
              }
      
              let chatTypeHeaders = document.querySelectorAll('header.sticky.top-0');
              if(chatTypeHeaders) {
                  chatTypeHeaders.forEach((chatTypeHeader) => {
                      chatTypeHeader.className = "";
                  });
              }
          }
      
          setInterval(setElementHeight, 1000);
      })();
    3. Fix GitHub snippet edit small size

      // ==UserScript==
      // @name         Fix GitHub snippet edit small size
      // @namespace    http://tampermonkey.net/
      // @version      0.1
      // @description  try to take over the world!
      // @author       You
      // @match        https://gist.github.com/evandrocoan/*
      // @require http://code.jquery.com/jquery-3.4.1.min.js
      // ==/UserScript==
      
      (function() {
          'use strict';
          let keepclosing = async () => {
              let viewedbar = $('div[class="CodeMirror cm-s-github-light CodeMirror-wrap"]').not('span[data-donot-process-this-again]');
      
              // console.log('running');
              // console.log(viewedbar);
              if(viewedbar.length)
              {
                  viewedbar.css("height", "700px");
                  viewedbar.attr('data-donot-process-this-again', true);
              }
              setTimeout(keepclosing, 500);
          }
          setTimeout(keepclosing, 500);
      })();
    4. Force GMail Archive button to go to back after clicking on it

      // ==UserScript==
      // @name         Force GMail Archive button to go to back after clicking on it
      // @namespace    *
      // @version      0.1
      // @description  Force GMail Archive button to go to back after clicking on it
      // @author       Evandro Coan
      //
      // @include https://mail.google.com/*
      // @require http://code.jquery.com/jquery-3.4.1.min.js
      // ==/UserScript==
      (function() {
          'use strict';
          let keepclosing = async () => {
              let viewedbar = $('div[data-tooltip="Archive"][tabindex="0"]').not('span[data-donot-process-this-again]');
              // console.log('running');
              // console.log(viewedbar);
              if(viewedbar.length)
              {
                  let previousItem = function() {
                      // let viewedbar = $('div[data-tooltip][tabindex="0"][role="button"]').filter(function() {
                      //     return $(this).attr('data-tooltip').match(/.*Back.*/);
                      // });
                      let viewedbar = $('div[data-tooltip="All Mail"]');
                      if(viewedbar.length) {
                          viewedbar.click();
                      }
                      return false;
                  };
                  viewedbar.on('click', previousItem);
                  viewedbar.attr('data-donot-process-this-again', true);
              }
              setTimeout(keepclosing, 500);
          }
          setTimeout(keepclosing, 500);
      
          let keepopening = async () => {
              let expandbutton = $('div[data-tooltip="Show trimmed content"][aria-expanded="false"]');
      
              setTimeout(keepopening, 500);
              if( expandbutton.length ) {
                  expandbutton.click();
              }
          }
          setTimeout(keepopening, 500);
      
          let keepremovingsearchbar = async () => {
              let expandbutton = $('div[aria-label="search refinement"]');
              let divsizetofix = $('div[gh="tm"]');
      
              setTimeout(keepremovingsearchbar, 500);
              divsizetofix.css("height", "30px");
              expandbutton.remove();
          }
          setTimeout(keepremovingsearchbar, 500);
      })();
    5. Force GMail Archive refresh page every 5 seconds

      // ==UserScript==
      // @name         Force GMail Archive refresh page every 5 seconds
      // @namespace    *
      // @version      0.1
      // @description  This is because on Linux the page some times takes long time to refresh
      // @author       Evandro Coan
      //
      // @include https://mail.google.com/*
      // @require http://code.jquery.com/jquery-3.4.1.min.js
      // ==/UserScript==
      
      (function() {
          'use strict';
          let keepclosing = async () => {
              let viewedbar = $('div[aria-label="Refresh"]');
      
              if(viewedbar.length)
              {
                  console.log('Clicking refresh');
                  viewedbar.click();
              }
              else {
                  console.log(viewedbar);
              }
          }
          setInterval(keepclosing, 5000);
      })();
    6. Remove youtube channels main image

      // ==UserScript==
      // @name         Remove youtube channels main image
      // @namespace    *
      // @version      0.1
      // @description  https://stackoverflow.com/questions/60480918/how-to-simulate-click-in-react-app-using-tampermonkey
      // @author       You
      //
      // @include https://*youtube.com/*
      // @require http://code.jquery.com/jquery-3.4.1.min.js
      // ==/UserScript==
      
      (function() {
          'use strict';
      
          let keepclosing = async () => {
              let menubuttons = $('tp-yt-paper-tab');
      
              if( menubuttons.length ) {
                  let background_div = $('div[id=background]');
      
                  if(background_div.length)
                  {
                       background_div.remove();
                  }
      
                  let topbardiv = $('div[class="style-scope tp-yt-app-header"]');
      
                  if(topbardiv.length)
                  {
                      topbardiv.css("padding-top", "0px");
                  }
      
                  let topbardiv2 = $('div[id="contents"]div[class="style-scope ytd-section-list-renderer"]');
      
                  if(topbardiv2.length)
                  {
                      topbardiv2.css("padding-top", "50px");
                      // topbardiv2.css("padding-top", "0px");
                  }
      
                  let topbardivbanner = $('div[class="banner-visible-area style-scope ytd-c4-tabbed-header-renderer"]');
      
                  if(topbardivbanner.length)
                  {
                      topbardivbanner.remove();
                  }
      
                  let topbardivsize = $('div[id=header][class="style-scope ytd-browse"]');
      
                  if(topbardivsize.length)
                  {
                      topbardivsize.css("height", "150px");
                      // topbardivsize.css("height", "0px");
                  }
      
                  let topbardivjoinbar = $('ytd-recognition-shelf-renderer[class="style-scope ytd-item-section-renderer"]');
      
                  if(topbardivjoinbar.length)
                  {
                      topbardivjoinbar.hide();
                  }
      
                  let topghostdiv = $('div[id=contentContainer][class="style-scope tp-yt-app-header-layout"]');
      
                  if(topghostdiv.length)
                  {
                      topghostdiv.hide();
                  }
      
                  // Unpin the main big bar (by putting it inside the main body)
                  // use 5 seconds to avoid delay to avoid unfocusing the search button type field each second
                  //if( $('div[id="contents"]div[class="style-scope ytd-section-list-renderer"] > div[class="style-scope tp-yt-app-header"]').length < 0 ) {
                  //}
              }
      
              setTimeout(keepclosing, 5000);
          }
          setTimeout(keepclosing, 5000);
      })();
    7. Remove youtube channels logo and always show all videos

      // ==UserScript==
      // @name         Remove youtube channels logo and always show all videos
      // @namespace    *
      // @version      0.1
      // @description  https://stackoverflow.com/questions/60480918/how-to-simulate-click-in-react-app-using-tampermonkey
      // @author       You
      //
      // @include https://*youtube.com/*
      // @exclude https://*youtube.com/*/TucaLoretti/*
      // @exclude https://*youtube.com/*/UC1__NTyvkBZElGBK1qmtoMg/*
      // @require http://code.jquery.com/jquery-3.4.1.min.js
      // ==/UserScript==
      
      (function() {
          'use strict';
      
          let keepclosing = async () => {
              let menubuttons = $('tp-yt-paper-tab');
      
              if( menubuttons.length ) {
                  // console.log("removing running...");
                  let videosButton = menubuttons[1];
                  let ariaSelected = $(videosButton).attr('aria-selected');
      
                  // console.log(`ariaSelected ${ariaSelected}`);
                  if( ariaSelected == 'false' ) {
                      menubuttons[1].click();
                  }
      
                  // delete youtube useless top bar/logo
                  let topbar = $('.style-scope.ytd-c4-tabbed-header-renderer');
                  if(topbar.length) {
                       topbar.hide();
                  }
              }
      
              setTimeout(keepclosing, 1000);
          }
          setTimeout(keepclosing, 1000);
      })();
    8. Always click youtube show more (channels button)

      // ==UserScript==
      // @name         Always click youtube show more (channels button)
      // @namespace    *
      // @version      0.1
      // @description  https://stackoverflow.com/questions/60480918/how-to-simulate-click-in-react-app-using-tampermonkey
      // @author       You
      //
      // @include https://*youtube.com/*
      // @exclude https://*youtube.com/*/TucaLoretti/*
      // @exclude https://*youtube.com/*/UC1__NTyvkBZElGBK1qmtoMg/*
      // @require http://code.jquery.com/jquery-3.4.1.min.js
      // ==/UserScript==
      
      (function() {
          'use strict';
          let showmoreregex = new RegExp("Show \\d+ more"); // expression here
      
          let keepclosing = async () => {
      
              let showmorebutton = $('yt-formatted-string[class="title style-scope ytd-guide-entry-renderer"]').filter(function () {
                  return showmoreregex.test($(this).text());
              });
      
              // console.log(`showmorebutton ${showmorebutton.text()}`);
              if( showmorebutton.length ) {
                  showmorebutton[0].click();
                  showmorebutton.remove();
              }
      
              setTimeout(keepclosing, 1000);
          }
          setTimeout(keepclosing, 1000);
      })();
    9. Remove genius lyrics side bars (to copy lyrics without their text)

      // ==UserScript==
      // @name         Remove genius lyrics side bars (to copy lyrics without their text)
      // @namespace    *
      // @version      0.1
      // @description  https://webapps.stackexchange.com/questions/145612/how-to-stop-the
      // @author       You
      //
      // @include https://genius.com/*
      // @require http://code.jquery.com/jquery-3.4.1.min.js
      // ==/UserScript==
      
      (function() {
          'use strict';
          let keepclosing = async () => {
              let viewedbar = $('.RightSidebar__Container-pajcl2-0');
              if(viewedbar.length) {
                  // console.log("removing running...");
                  // use hide instead of remove to avoid mass flickering of the page
                  viewedbar.hide();
              }
              // console.log("running");
              setTimeout(keepclosing, 500);
          }
          setTimeout(keepclosing, 500);
      })();
    10. Remove youtube viewed videos

      // ==UserScript==
      // @name         Remove youtube viewed videos
      // @namespace    *
      // @version      0.1
      // @description  https://webapps.stackexchange.com/questions/145612/how-to-stop-the
      // @author       You
      //
      // @include https://*youtube.com/*
      // @require http://code.jquery.com/jquery-3.4.1.min.js
      // ==/UserScript==
      
      (function() {
          'use strict';
          let keepclosing = async () => {
              let viewedbar = $('.style-scope.ytd-thumbnail-overlay-resume-playback-renderer');
              if(viewedbar.length) {
                  // console.log("removing running...");
                  let parent = viewedbar.closest('.style-scope.ytd-rich-grid-renderer');
                  if(parent.length) {
                      // use hide instead of remove to avoid mass flickering of the page
                      parent.hide();
                  }
              }
              // console.log("running");
              setTimeout(keepclosing, 500);
          }
          setTimeout(keepclosing, 500);
      })();
    11. Remove crunchyroll simulcastcalendar dub videos

      // ==UserScript==
      // @name         Remove crunchyroll simulcastcalendar dub videos
      // @namespace    *
      // @version      0.1
      // @description  https://webapps.stackexchange.com/questions/145612/how-to-stop-the
      // @author       You
      //
      // @include https://*crunchyroll*/simulcastcalendar*
      // @require http://code.jquery.com/jquery-3.4.1.min.js
      // ==/UserScript==
      
      (function() {
          'use strict';
          let keepclosing = async () => {
              let viewedbar = $('cite:contains(" Dub)")');
              if(viewedbar.length) {
                  // console.log("removing running...");
                  let parent = viewedbar.closest('li');
                  if(parent.length) {
                      // use hide instead of remove to avoid mass flickering of the page
                      parent.hide();
                  }
              }
              // console.log("running");
              // setTimeout(keepclosing, 500);
          }
          setTimeout(keepclosing, 1500);
      })();
    12. Close GitHub Notifications bar

      // ==UserScript==
      // @name         Close GitHub Notifications bar
      // @namespace    *
      // @version      0.1
      // @description  https://github.com/sindresorhus/refined-github/issues/3061
      //               https://gist.github.com/evandrocoan/0e25dd233f3f99352a8147041809ba8d
      //
      // @author       You
      // @include http://*github.com/*
      // @include https://*github.com/*
      // @require http://code.jquery.com/jquery-3.4.1.min.js
      // ==/UserScript==
      
      (function() {
          'use strict';
          clickButton('button[aria-label="Close notification controls"].js-flash-close');
          deleteElement('.js-sticky.js-sticky-offset-scroll.top-0.gh-header-sticky.is-stuck');
      
          // http://en.enisozgen.com/hide-github-academic-discount-coupon-error/
          deleteElement('.flash.flash-full.js-notice.flash-error');
      
          function deleteElement(selector) {
              let delayed = () => {
                  let element = $(String(selector));
                  if(element.length) {
                      console.log(`Deleting '${element.text().replace(/\s+/g, ' ').trim()}' button`);
                      element.remove();
                  }
                  setTimeout(delayed, 2000);
              }
              setTimeout(delayed, 2000);
          }
          function clickButton(selector) {
              let delayed = () => {
                  let element = $(String(selector));
                  if(element.length) {
                      console.log(`Closing element '${element.html()}' button`);
                      element.click();
                  }
                  setTimeout(delayed, 2000);
              }
              setTimeout(delayed, 2000);
          }
      })();
    13. Close stackexchange up vote beg bar

      // ==UserScript==
      // @name         Close Stackexchange Up Vote Notifications bar
      // @namespace    *
      // @version      0.1
      // @description  https://github.com/sindresorhus/refined-github/issues/3061
      // @author       You
      // https://meta.stackexchange.com/questions/81379/can-we-have-a-list-of-all
      // @description  https://github.com/sindresorhus/refined-github/issues/3061
      // @include https://*askubuntu.com/*
      // @include https://*mathoverflow.net/*
      // @include https://*blogoverflow.com/*
      // @include https://*serverfault.com/*
      // @include https://*stackoverflow.com/*
      // @include https://*stackexchange.com/*
      // @include https://*stackapps.com/*
      // @include https://*stackmod.blog/*
      // @include https://*stackoverflow.blog/*
      // @include https://*stackoverflowbusiness.com/*
      // @include https://*superuser.com/*
      // @include https://*tex-talk.net/*
      // @include https://*thesffblog.com/*
      // @require http://code.jquery.com/jquery-3.4.1.min.js
      // ==/UserScript==
      
      (function() {
          'use strict';
          let keepclosing = async () => {
              let closebutton = $('#overlay-header');
              if(closebutton.length) {
                  console.log('Close Stackexchange Up Vote Notifications bar');
                  closebutton.remove();
                  setTimeout(keepclosing, 2000);
              }
              let begteampromotion = $('.teams-promo.overflow-hidden.z-active.bs-md.bg-black-750.fc-white.fs-body2.js-teams-promo');
              if(begteampromotion.length) {
                  console.log('Close Stackexchange Team Bag Notifications bar');
                  begteampromotion.remove();
              }
              let beg_banner_bookmark = $('aside[class="s-notice s-notice__success"]');
              if(beg_banner_bookmark.length) {
                  console.log('Close Stackexchange Bookmark Notifications bar');
                  beg_banner_bookmark.hide();
                  setTimeout(keepclosing, 2000);
              }
          }
          setTimeout(keepclosing, 2000);
      })();
    14. Close Lastfm top bar player

      // ==UserScript==
      // @name         Close Lastfm player bar
      // @namespace    *
      // @version      0.1
      // @description  https://github.com/sindresorhus/refined-github/issues/3061
      // @author       You
      // https://meta.stackexchange.com/questions/81379/can-we-have-a-list-of-all
      // @include https://*last.fm/*
      // @require http://code.jquery.com/jquery-3.4.1.min.js
      // ==/UserScript==
      
      let things = `
      // https://stackoverflow.com/questions/7474354/include-jquery-in-the-javascript-console
      var jq = document.createElement('script');
      jq.src = "https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js";
      document.getElementsByTagName('head')[0].appendChild(jq);
      // ... give time for script to load, then type (or see below for non wait option)
      jQuery.noConflict();
      `;
      
      (function() {
          'use strict';
          deleteElement('div[data-more-string="More…"].navlist.navlist--more.masthead-nav.hidden-xs');
          deleteElement('.masthead-logo');
          deleteElement('.top-bar');
          function deleteElement(selector) {
              let delayed = () => {
                  // Avoid reprocessing when on background/not focused
                  if (document.hasFocus()) {
                      // console.log('Tab is active');
                  }
                  else {
                      // console.log('Tab is not active');
                      setTimeout(delayed, 1000);
                      return;
                  }
      
                  let element = $(String(selector));
                  if(element.length) {
                      console.log(`Deleting element '${element.text().replace(/\s+/g, ' ').trim()}' button`);
                      element.remove();
                  }
                  setTimeout(delayed, 2000);
              }
              setTimeout(delayed, 200);
          }
      
          $('#content').css({'padding-top': '0px'});
          if( String(window.location.href).toLowerCase().includes('ironhead4life') ) {
              setTimeout(fixScrobleLink, 1000);
          }
          function fixScrobleLink() {
              // Avoid reprocessing when on background/not focused
              if (document.hasFocus()) {
                  // console.log('Tab is active');
              }
              else {
                  // console.log('Tab is not active');
                  setTimeout(fixScrobleLink, 1000);
                  return;
              }
      
              $('.chartlist-name>a').each(function(index, item) {
                  // console.log(index)
                  let newitem = $(item).attr('href');
      
                  if( ! String(newitem).includes('IronHead4Life') ) {
                      let newitemsrc = String(newitem).replace('/music/', '/user/IronHead4Life/library/music/');
      
                      // console.log(newitemsrc);
                      $(item).attr('href', newitemsrc);
                      $(item).attr ('target', '_blank');
                  }
              });
              setTimeout(fixScrobleLink, 1000);
          }
      })();
    15. Force all short videos to open as a normal video!

      // ==UserScript==
      // @name         Force all short videos to open as a normal video!
      // @namespace    *
      // @version      0.1
      // @description  https://stackoverflow.com/questions/60480918/how-to-simulate-click-in-react-app-using-tampermonkey
      // @author       You
      //
      // @include https://*youtube.com/*
      // @require http://code.jquery.com/jquery-3.4.1.min.js
      // ==/UserScript==
      
      (function() {
          'use strict';
          let keepclosing = async () => {
              let viewedbar = $('a[href*="/shorts"]');
      
              // console.log('running');
              // console.log(viewedbar);
              if(viewedbar.length)
              {
                  $(viewedbar).each(function(index, item)
                  {
                      // console.log(index)
                      let newitem = $(item).attr('href');
                      let newitemsrc = String(newitem).replace('/shorts/', '/watch?v=');
      
                      // console.log(newitemsrc);
                      $(item).attr('rel', `noopener noreferrer`);
                      //$(item).attr('target', `_blank`);
                      $(item).attr('onclick', `
                          if( '${newitemsrc}' !=  this.getAttribute('href')) return;
                          window.open('${newitemsrc}', '');
                          setTimeout(function(){ history.back(); }, 500);
                          return false;
                      `);
                      $(item).removeAttr('href');
                      $(item).attr('href', newitemsrc);
                      //$(item).attr('data-saferedirecturl', newitemsrc);
                  })
              }
              setTimeout(keepclosing, 500);
          }
          setTimeout(keepclosing, 500);
      })();
      
      
      
      
      
      
      
    16. jisho add copy button to meanings-wrapper elements

      // ==UserScript==
      // @name         jisho add copy button to meanings-wrapper elements
      // @namespace    your-namespace
      // @version      1
      // @description  Add a button to all elements with the class "meanings-wrapper"
      // @match        *://jisho.org/*
      // @grant        none
      // ==/UserScript==
      
      (function() {
          'use strict';
          function copyToClipboard(docCopy) {
              const meaningTags = docCopy.querySelectorAll('.meaning-tags');
      
              for (let i = 0; i < meaningTags.length; i++) {
                  const tagContent = meaningTags[i].textContent;
                  if (tagContent) {
                      const newTag = document.createElement('span');
                      newTag.style.color = 'rgb(0, 128, 0)';
                      newTag.innerHTML = tagContent + ') ';
                      newTag.classList = meaningTags[i].classList;
                      meaningTags[i].parentNode.insertBefore(newTag, meaningTags[i]);
                      meaningTags[i].parentNode.removeChild(meaningTags[i]);
                  }
              }
      
              const meaningDefinitions = docCopy.querySelectorAll('.meaning-definition');
              for (let i = 0; i < meaningDefinitions.length; i++) {
                  const meaningDefinition = meaningDefinitions[i];
      
                  // remove `class="meaning-definition-section_divider"` and its contents
                  const sectionDivider = meaningDefinition.querySelector('.meaning-definition-section_divider');
                  if (sectionDivider) {
                      sectionDivider.parentNode.removeChild(sectionDivider);
                  }
              }
      
              // before the `class="supplemental_info"` and after `class="meaning-meaning` span tag closes, add `: `
              const spanElements = docCopy.querySelectorAll('span');
              for (let i = 0; i < spanElements.length; i++) {
                  const spanElement = spanElements[i];
                  if( !spanElement.parentNode ) {
                      continue;
                  }
      
                  // remove <span class="hit">円</span> but keep the contents
                  const hitElement = spanElement.querySelector('.hit');
                  if(hitElement) {
                      const textNode = document.createTextNode(hitElement.textContent);
                      hitElement.parentNode.replaceChild(textNode, hitElement);
                  }
      
                  if (spanElement.textContent === '​') {
                      const textNode = document.createTextNode(': ');
                      spanElement.parentNode.replaceChild(textNode, spanElement);
                  }
              }
      
              // replace `ul class="japanese` and its contents with new formating using `<ruby><rb>kanji</rb><rt>furigana</rt></ruby>`
              const japaneseLists = docCopy.querySelectorAll('.japanese');
              for (let i = 0; i < japaneseLists.length; i++) {
                  const japaneseListItems = japaneseLists[i].querySelectorAll('li');
                  for (let j = 0; j < japaneseListItems.length; j++) {
                      const japaneseListItem = japaneseListItems[j];
                      const kanji = japaneseListItem.querySelector('.unlinked');
                      const furigana = japaneseListItem.querySelector('.furigana');
                      if (kanji && furigana) {
                          const ruby = document.createElement('ruby');
                          const rt = document.createElement('rt');
                          rt.innerHTML = furigana.innerHTML;
                          if(kanji.innerHTML != kanji.textContent) {
                              throw new Error(`${kanji.innerHTML} != ${kanji.textContent}`);
                          }
                          // fix jisho bug where kanji is not separated from kana
                          let kanaList = [];
                          let kanjiList = [];
                          for (let i = 0; i < kanji.textContent.length; i++) {
                              const character = kanji.textContent.charAt(i);
                              if (/[\u3040-\u309F\u30A0-\u30FF]/g.test(character)) {
                                  kanaList.push(character);
                              }
                              else {
                                  kanjiList.push(character);
                              }
                          }
                          ruby.insertAdjacentHTML('beforeend', kanjiList.join(''));
                          ruby.appendChild(rt);
                          ruby.insertAdjacentHTML('beforeend', kanaList.join(''));
                          japaneseListItem.innerHTML = '';
                          japaneseListItem.appendChild(ruby);
                      }
                      else if(kanji) {
                          const ruby = document.createElement('ruby');
                          const rt = document.createElement('rt');
                          ruby.insertAdjacentHTML('beforeend', kanji.innerHTML)
                          ruby.appendChild(rt);
                          japaneseListItem.innerHTML = '';
                          japaneseListItem.appendChild(ruby);
                      }
                  }
              }
      
              // add `<br/>` after `class="meaning-wrapper"` contents but not if it is the last one
              const meaningWrappers = docCopy.querySelectorAll('.meaning-wrapper');
              for (let i = 0; i < meaningWrappers.length; i++) {
                  const meaningWrapper = meaningWrappers[i];
                  const contents = meaningWrapper.innerHTML;
                  if (i < meaningWrappers.length - 1) {
                      meaningWrapper.insertAdjacentElement('afterEnd', document.createElement('br'));
                  }
      
                  // remove ul and li but keep its contents
                  const sentences = meaningWrapper.querySelector('.sentences');
                  if(!sentences) {
                      continue;
                  }
                  const japanese = sentences.querySelector('.japanese');
                  const japaneseListItems = japanese.childNodes;
                  const japaneseListItemContents = [];
      
                  for(let i = 0; i < japaneseListItems.length; i++) {
                      const japaneseListItem = japaneseListItems[i];
                      if(japaneseListItem.nodeType === Node.TEXT_NODE) {
                          japaneseListItemContents.push(japaneseListItem.textContent);
                      }
                      else {
                          japaneseListItemContents.push(japaneseListItem.innerHTML);
                      }
                  };
                  const newHtml = document.createElement('span');
                  newHtml.innerHTML = japaneseListItemContents.join('');
                  newHtml.classList = 'japanese-chars';
                  japanese.parentElement.replaceChild(newHtml, japanese);
              }
      
              // move `class="english"` contents from inside `class="sentence"` to after it
              const sentences = docCopy.querySelectorAll('.sentence');
              for (let i = 0; i < sentences.length; i++) {
                  const sentence = sentences[i];
                  const english = sentence.querySelector('.english');
                  if (english) {
                      const englishText = english.textContent;
                      sentence.removeChild(english);
                      const newSpan = document.createElement('span');
                      newSpan.classList.add('japanese-english');
                      newSpan.textContent = englishText;
                      sentence.parentNode.appendChild(newSpan);
                  }
              }
      
              // replace all `div` tags by `span`, except the class="meaning-tags" div
              let divs = docCopy.querySelectorAll('div');
              while (divs.length > 0) {
                  for (let i = 0; i < divs.length; i++) {
                      const div = divs[i];
                      const span = document.createElement('span');
                      span.innerHTML = div.innerHTML;
                      div.parentNode.replaceChild(span, div);
                  }
                  divs = docCopy.querySelectorAll('div');
              }
      
              // prefix href=/search with 'https://jisho.org/'
              const links = docCopy.querySelectorAll('[href^="/"]');
              links.forEach(function(link) {
                  const href = link.getAttribute('href');
                  link.setAttribute('href', 'https://jisho.org' + href);
              });
      
              const removeButtons = docCopy.querySelectorAll('.remove-this-button');
              removeButtons.forEach(button => {
                  button.remove();
              });
      
              const html = docCopy.innerHTML;
              navigator.clipboard.writeText(html)
              .then(() => {
                  if (Notification.permission === 'granted') {
                      const notification = new Notification('HTML copied to clipboard', {
                          body: 'The HTML has been copied to the clipboard.',
                      });
                      setTimeout(() => {
                          notification.close();
                      }, 3000);
                  } else if (Notification.permission !== 'denied') {
                      Notification.requestPermission().then(permission => {
                          if (permission === 'granted') {
                              const notification = new Notification('HTML copied to clipboard', {
                                  body: 'The HTML has been copied to the clipboard.',
                              });
                              setTimeout(() => {
                                  notification.close();
                              }, 3000);
                          }
                          else {
                              alert('Clipboard copy notification show denied');
                          }
                      });
                  }
              })
              .catch(err => {
                  alert('Failed to copy HTML: ', err);
              });
          }
      
          let keepclosing = async () => {
              const meaningsWrappers = document.querySelectorAll('.meanings-wrapper:not(.remove-this-button)');
              meaningsWrappers.forEach(meaningsWrapper => {
                  meaningsWrapper.classList.add('remove-this-button');
                  const button = document.createElement('button');
                  button.innerText = 'Copy';
                  button.classList = 'remove-this-button';
                  button.addEventListener('click', ()=> copyToClipboard(meaningsWrapper.cloneNode(true)));
                  meaningsWrapper.appendChild(button);
              });
              setTimeout(keepclosing, 500);
          }
          setTimeout(keepclosing, 500);
      })();
    17. Move weather.com real feel temperature side-by-side with temperature

      // ==UserScript==
      // @name         Move weather.com real feel temperature side-by-side with temperature
      // @namespace    http://tampermonkey.net/
      // @version      2024-01-10
      // @description  try to take over the world!
      // @author       You
      // @match        https://weather.com/weather/hourbyhour/*
      // @icon         https://www.google.com/s2/favicons?sz=64&domain=weather.com
      // @require http://code.jquery.com/jquery-3.4.1.min.js
      // @grant        none
      // ==/UserScript==
      
      (function() {
          'use strict';
          setInterval(function(){
              let temperatures = $('span[data-testid="TemperatureValue"]');
              if( temperatures.length && temperatures[0].textContent.includes('/') ) {
                  temperatures = temperatures.not('span[data-donot-process-this-again]');
              }
      
              for (let index = 0; index < temperatures.length; index+=2) {
                  let main_temperature = $(temperatures[index]);
                  let real_feel = $(temperatures[index+1]);
                  main_temperature.append(` / ${real_feel.text()}`)
      
                  real_feel.attr('data-donot-process-this-again', true);
                  main_temperature.attr('data-donot-process-this-again', true);
              }
      
              let percentages = $('span[data-testid="PercentageValue"]').not('span[data-donot-process-this-again]');
      
              for (let index = 0; index < percentages.length; index+=3) {
                  let rain_probability = $(percentages[index]);
                  let humidity_percentage = $(percentages[index+1]);
                  let cloud_clover = $(percentages[index+2]);
                  rain_probability.append(`&nbsp;${humidity_percentage.text()}&nbsp;${cloud_clover.text()}`)
      
                  rain_probability.attr('data-donot-process-this-again', true);
                  humidity_percentage.attr('data-donot-process-this-again', true);
                  cloud_clover.attr('data-donot-process-this-again', true);
              }
          },
          1000);
      })();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment