[UPDATED] Extension for Better LingQ Reader Layout (For Video/Audio Lessons)

Before & After

Reader

Video Player (default size / location)

Features

Theme settings

  • Change the default size/location of video player.
  • Make prev/next page buttons compact
  • Custom font settings (clolor, paddings, space between lines, …)
  • Custom highlightings (color, border, paddings) on words (lingqed, leared, new)

Addons

  • Modified embedded player settings (caption on, auto play, disable controls)
  • Add a video full screen toggle shortcut (x key)
  • Change course sorting: Automatically changes the sorting option in a course page from ‘All lessons’ to other Option. You can change what would be defaulted by changing the number in .dropdown-item:nth-child(3).

How to use?

It is a userscript can be used in Tampermonkey or other apps.
Install the extension and copy & paste my code.

Homepage:

Random tutorial I found on google:

Code

// ==UserScript==
// @name         LingQ Addon
// @description  Custom embedded player, and sort course automatically.
// @match        https://www.lingq.com/*/learn/*/web/reader/*
// @match        https://www.lingq.com/*/learn/*/web/library
// @version      1.3
// ==/UserScript==

(function () {
  "use strict";
  
  // Style settings
  var style = document.createElement("style");
  style.textContent = `
  :root {
    --width_small: 540px;
    --height_small: 370px;
    --height_big: 650px;
    --width_big: 1100px;
    --right_pos: 0.5%;
    --bottom_pos: 5.5%;
    
    --font_size: 1.1rem;
    --font_color: #e0e0e0;
    --line_height: 1.7;
    
    --lingq_background: hsl(41 43% 30% / 0.7);
    --lingq_border: hsl(43 99% 64% / 0.3);
    --lingq_border_learned: hsl(43 99% 64% / 0.5);
    --blue_border: hsl(213 99% 64% / 0.5);
  }

  .video-player .video-wrapper,
  .sent-video-player .video-wrapper {
    height: var(--height_big);
    overflow: hidden;
  }

  .modal.video-player .modal-content {
    max-width: var(--width_big);
    margin-bottom: 0;
  }

  .video-player.is-minimized .video-wrapper,
  .sent-video-player.is-minimized .video-wrapper {
    height: var(--height_small);
    width: var(--width_small);
  }

  .video-player.is-minimized .modal-content,
  .sent-video-player.is-minimized .modal-content {
    max-width: var(--width_small);
    margin-bottom: 0;
  }

  .video-player.is-minimized,
  .sent-video-player.is-minimized {
    left: auto;
    top: auto;
    right: var(--right_pos);
    bottom: var(--bottom_pos);
    z-index: 99999999;
    overflow: visible
  }

  // make prev/next page buttons compact
  main {}

  .reader-component {
    grid-template-columns: 1.5rem 1fr 1.5rem !important;
  }

  .reader-component>div>a.button>span {
    width: 1.5rem !important;
  }


  // font settings
  article {}

  .reader-container {
    margin: 0 !important;
    float: left !important;
    line-height: var(--line_height) !important;
    padding: 0 !important;
    font-size: var(--font_size) !important;
  }

  .reader-container p {
    margin-top: 0 !important;
  }

  .reader-container p span.sentence-item {
    color: var(--font_color) !important;
  }

  .sentence.is-playing,
  .sentence.is-playing span {
    text-underline-offset: .2em !important;
  }
  
  // LingQ highlightings
  .phrase-cluster {}
  
  .phrase-item {
    padding: 0 !important;
  }

  .phrase-item:not(.phrase-item-status--4, .phrase-item-status--4x2) {
    background-color: var(--lingq_background) !important;
  }

  .phrase-item.phrase-item-status--4, 
  .phrase-item.phrase-item-status--4x2 {
    background-color: rgba(0, 0, 0, 0) !important;
  }

  .phrase-cluster:not(:has(.phrase-item-status--4, .phrase-item-status--4x2)) {
    border: 1px solid var(--lingq_border) !important;
    border-radius: .25rem;
  }

  .phrase-cluster:has(.phrase-item-status--4, .phrase-item-status--4x2) {
    border: 1px solid var(--lingq_border_learned) !important;
    border-radius: .25rem;
  }

  .reader-container .sentence .lingq-word:not(.is-learned) {
    border: 1px solid var(--lingq_border) !important;
    background-color: var(--lingq_background) !important;
  }

  .reader-container .sentence .lingq-word.is-learned {
    border: 1px solid var(--lingq_border_learned) !important;
  }
  
  .reader-container .sentence .blue-word {
    border: 1px solid var(--blue_border) !important;
  }
  
  .phrase-cluster:hover,
  .phrase-created:hover {
    padding: 0 !important;
  }
  
  .phrase-cluster:hover .phrase-item,
  .phrase-created .phrase-item {
    padding: 0 !important;
  }
  

  .reader-container .sentence .selected-text {
    padding: 0 !important;
  }
  `;
  document.querySelector("head").appendChild(style);
  
  
  
  // Add new shortcuts
  document.addEventListener('keydown', function(event) {
    const targetElement = event.target;
    const isTextInput = (targetElement.type === 'text' || targetElement.type === 'textarea');
    if (isTextInput) {
      return;
    }
    
    // video full screen toggle (x key)
    if (event.key === 'x' || event.key === 'X') {
      const full_screen_btn = document.querySelector('.modal-section > div > button:nth-child(2)');
      if (full_screen_btn) {
        full_screen_btn.click();
      }
    }
  });
  

  // Custom embedded player
  function replaceNoCookie() {
    document.querySelectorAll('iframe').forEach(function(iframe) {
        let src = iframe.getAttribute('src');

        if (src && src.includes('autoplay=0')) {
            src = src.replace('autoplay=0', 'autoplay=1'); // video will automatically start to play.
            src = src.replace('disablekb=1', 'disablekb=0'); // keyboard controls are enabled.
            src = src + '&cc_load_policy=1' // caption is shown by default.
            src = src + '&controls=0' // player controls do not display in the player.
            iframe.setAttribute('src', src);
            console.log(src);
        }
    });
  }

  const iframeObserver = new MutationObserver(function(mutationsList, observer) {
      for (const mutation of mutationsList) {
          if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
              mutation.addedNodes.forEach(node => {
                  if (node.nodeName === 'IFRAME') {
                      replaceNoCookie();
                  } else if (node.querySelectorAll) {
                      node.querySelectorAll('iframe').forEach(replaceNoCookie);
                  }
              });
          } else if (mutation.type === 'attributes' && mutation.attributeName === 'src' && mutation.target.nodeName === 'IFRAME') {
              replaceNoCookie();
          }
      }
  });

  if (document.URL.includes("/reader/")) {
    iframeObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['src'] });
  }


  // Sort courses
  function addClickListener() {
    document.querySelectorAll("div.library-item-wrap").forEach((item) => {
      if (!item.dataset.listenerAdded) {
        item.addEventListener("click", function () {
          setTimeout(() => {
            /* Change the number in .dropdown-item:nth-child(3) by your preference
               1: All lessons
               2: Oldest to Newest
               3: Newest to Oldest
               4: Last Opened
               5: New Words %
               6: A-Z */
            document.querySelector(
              ".library-item--menu-box .collection-section--controllers .dropdown-item:nth-child(5)"
            ).click();
          }, 500);
        });
        item.dataset.listenerAdded = true;
      }
    });
  }

  const libraryObserver = new MutationObserver(addClickListener);
  if (document.URL.includes("/library")) {
    libraryObserver.observe(document.body, { childList: true, subtree: true });
    addClickListener();
  }
})();

You can customize settings by adjusting these values in the code:

   :root {
    --width_small: 540px;
    --height_small: 370px;
    --height_big: 650px;
    --width_big: 1100px;
    --right_pos: 0.5%;
    --bottom_pos: 5.5%;
    
    --font_size: 1.1rem;
    --font_color: #e0e0e0;
    --line_height: 1.7;
    
    --lingq_background: hsl(41 43% 30% / 0.7);
    --lingq_border: hsl(43 99% 64% / 0.3);
    --lingq_border_learned: hsl(43 99% 64% / 0.5);
    --blue_border: hsl(213 99% 64% / 0.5);
  }

If it was helpful to you, you can
Buy Me A Coffee

8 Likes

I made some adjustments to see a large-sized video with its script without clicking the page flip button.

Adjust the value of variables to fit your resolution or env.

// ==UserScript==
// @name         LingQ Addon
// @description  Custom embedded player, and sort course automatically.
// @match        https://www.lingq.com/*/learn/*/web/reader/*
// @match        https://www.lingq.com/*/learn/*/web/library
// @version      1.3
// ==/UserScript==

(function () {
  "use strict";
  
  // Style settings
  var style = document.createElement("style");
  style.textContent = `
  :root {
    --width_small: 440px;
    --height_small: 260px;
    --right_pos: 0.5%;
    --bottom_pos: 5.5%;
    
    --width_big: calc(100vw - 424px - 40px);
    --height_big: 460px; /*video height*/
    
    --font_size: 1.1rem; /*reader font size*/
    --font_color: #e0e0e0; /*font color*/
    --line_height: 1.7;
    
    --lingq_background: hsl(41 43% 30% / 0.7);
    --lingq_border: hsl(43 99% 64% / 0.3);
    --lingq_border_learned: hsl(43 99% 64% / 0.5);
    --blue_border: hsl(213 99% 64% / 0.5);
    
    --is_playing_underline: #ffffff;
    
    --grid-layout: 1fr var(--height_big) 80px;
    --video_margin: 0 0 90px 10px !important;
    --article_height: calc(var(--app-height) - 165px - var(--height_big));
  }
  
  .main-wrapper {
    padding-top: calc(var(--spacing)* 12) !important;
  }
  
  #main-nav .navbar, #main-nav .navbar-brand {
    min-height: 2.75rem !important;
  }
  
  .main-header svg {
    width: 20px !important;
    height: 20px !important;
  }
  
  #lesson-reader {
    grid-template-rows: var(--grid-layout);
    overflow-y: hidden;
  }
  
  .sentence-text {
  height: var(--article_height) !important;
  }
  
  .reader-container-wrapper {
    height: 100% !important;
  }
  
  /*video viewer*/
  
  .main-footer.has-video {
    grid-area: 3 / 1 / 3 / 1 !important;
    align-self: end;
  }
  
  .widget-area {
    grid-area: 2 / 2 / -1 / 2 !important;
  }
  
  .main-content {
    grid-template-rows: 25px 1fr !important;
    overflow: hidden; 
    grid-area: 1 / 1 / 1 / -1 !important;
    align-items: anchor-center;
  }
  
  .modal-container .modls {
    pointer-events: none;
    justify-content: end !important;
    align-items: flex-start;
  }
  
  .modal-background {
    background-color: rgb(26 28 30 / 0%) !important;
  }
  
  .modal-section.modal-section--head {
    display: none !important;
  }
  
  .video-player .video-wrapper,
  .sent-video-player .video-wrapper {
    height: var(--height_big);
    overflow: hidden;
    pointer-events: auto;
  }

  .modal.video-player .modal-content {
    max-width: var(--width_big);
    margin: var(--video_margin);
  }

  .video-player.is-minimized .video-wrapper,
  .sent-video-player.is-minimized .video-wrapper {
    height: var(--height_small);
    width: var(--width_small);
  }

  .video-player.is-minimized .modal-content,
  .sent-video-player.is-minimized .modal-content {
    max-width: var(--width_small);
    margin-bottom: 0;
  }

  .video-player.is-minimized,
  .sent-video-player.is-minimized {
    left: auto;
    top: auto;
    right: var(--right_pos);
    bottom: var(--bottom_pos);
    z-index: 99999999;
    overflow: visible
  }

  /*make prev/next page buttons compact*/

  .reader-component {
    grid-template-columns: 0.5rem 1fr 0rem !important;
  }

  .reader-component>div>a.button>span {
    width: 0.5rem !important;
  }

  .reader-component>div>a.button>span>svg {
    width: 15px !important;
    height: 15px !important;
  }

  /*font settings*/
  
  .reader-container {
    margin: 0 !important;
    float: left !important;
    line-height: var(--line_height) !important;
    padding: 0 !important;
    font-size: var(--font_size) !important;
    columns: unset !important;
    overflow-y: scroll !important;
    max-width: unset !important;
  }

  .reader-container p {
    margin-top: 0 !important;
  }

  .reader-container p span.sentence-item {
    color: var(--font_color) !important;
  }

  .sentence.is-playing,
  .sentence.is-playing span {
    text-underline-offset: .2em !important;
    text-decoration-color: var(--is_playing_underline) !important;
  }
  
  /*LingQ highlightings*/

  .phrase-item {
    padding: 0 !important;
  }

  .phrase-item:not(.phrase-item-status--4, .phrase-item-status--4x2) {
    background-color: var(--lingq_background) !important;
  }

  .phrase-item.phrase-item-status--4, 
  .phrase-item.phrase-item-status--4x2 {
    background-color: rgba(0, 0, 0, 0) !important;
  }

  .phrase-cluster:not(:has(.phrase-item-status--4, .phrase-item-status--4x2)) {
    border: 1px solid var(--lingq_border) !important;
    border-radius: .25rem;
  }

  .phrase-cluster:has(.phrase-item-status--4, .phrase-item-status--4x2) {
    border: 1px solid var(--lingq_border_learned) !important;
    border-radius: .25rem;
  }

  .reader-container .sentence .lingq-word:not(.is-learned) {
    border: 1px solid var(--lingq_border) !important;
    background-color: var(--lingq_background) !important;
  }

  .reader-container .sentence .lingq-word.is-learned {
    border: 1px solid var(--lingq_border_learned) !important;
  }
  
  .reader-container .sentence .blue-word {
    border: 1px solid var(--blue_border) !important;
  }
  
  .phrase-cluster:hover,
  .phrase-created:hover {
    padding: 0 !important;
  }
  
  .phrase-cluster:hover .phrase-item,
  .phrase-created .phrase-item {
    padding: 0 !important;
  }
  
  .reader-container .sentence .selected-text {
    padding: 0 !important;
  }
  `;
  document.querySelector("head").appendChild(style);
  
  
  
  // Add new shortcuts
  document.addEventListener('keydown', function(event) {
    const targetElement = event.target;
    const isTextInput = (targetElement.type === 'text' || targetElement.type === 'textarea');
    if (isTextInput) {
      return;
    }
    
    // video full screen toggle (q key)
    if (event.key === 'q' || event.key === 'Q') {
      const full_screen_btn = document.querySelector('.modal-section > div > button:nth-child(2)');
      if (full_screen_btn) {
        full_screen_btn.click();
      }
    }
    
    // 5 sec Backward (w key)
    if (event.key === 'w' || event.key === 'W') {
      const full_screen_btn = document.querySelector('.audio-player--controllers > div:nth-child(1) > a');
      if (full_screen_btn) {
        full_screen_btn.click();
      }
      event.stopPropagation();
    }
    
    // 5 sec Forward (e key)
    if (event.key === 'e' || event.key === 'E') {
      const full_screen_btn = document.querySelector('.audio-player--controllers > div:nth-child(2) > a');
      if (full_screen_btn) {
        full_screen_btn.click();
      }
      event.stopPropagation();
    }
  });
  

  // Custom embedded player
  function replaceNoCookie() {
    document.querySelectorAll('iframe').forEach(function(iframe) {
        let src = iframe.getAttribute('src');

        if (src && src.includes('autoplay=0')) {
            src = src.replace('autoplay=0', 'autoplay=1'); // video will automatically start to play.
            src = src.replace('disablekb=1', 'disablekb=0'); // keyboard controls are enabled.
            src = src + '&cc_load_policy=1' // caption is shown by default.
            src = src + '&controls=0' // player controls do not display in the player.
            iframe.setAttribute('src', src);
            console.log(src);
        }
    });
  }

  const iframeObserver = new MutationObserver(function(mutationsList, observer) {
      for (const mutation of mutationsList) {
          if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
              mutation.addedNodes.forEach(node => {
                  if (node.nodeName === 'IFRAME') {
                      replaceNoCookie();
                  } else if (node.querySelectorAll) {
                      node.querySelectorAll('iframe').forEach(replaceNoCookie);
                  }
              });
          } else if (mutation.type === 'attributes' && mutation.attributeName === 'src' && mutation.target.nodeName === 'IFRAME') {
              replaceNoCookie();
          }
      }
  });

  if (document.URL.includes("/reader/")) {
    iframeObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['src'] });
  }


  // Change the amount of a scroll
  setTimeout(() => {
    console.log('scroll event!');
    const myDiv = document.querySelector('.reader-container');
    myDiv.addEventListener('wheel', (event) => {
      event.preventDefault();
      const delta = event.deltaY;
      const scrollAmount = 0.3;
      myDiv.scrollTop += delta * scrollAmount;
    });
  }, 3000);


  // Sort courses
  function addClickListener() {
    document.querySelectorAll("div.library-item-wrap").forEach((item) => {
      if (!item.dataset.listenerAdded) {
        item.addEventListener("click", function () {
          setTimeout(() => {
            /* Change the number in .dropdown-item:nth-child(3) by your preference
               1: All lessons
               2: Oldest to Newest
               3: Newest to Oldest
               4: Last Opened
               5: New Words %
               6: A-Z */
            document.querySelector(
              ".library-item--menu-box .collection-section--controllers .dropdown-item:nth-child(5)"
            ).click();
          }, 500);
        });
        item.dataset.listenerAdded = true;
      }
    });
  }

  const libraryObserver = new MutationObserver(addClickListener);
  if (document.URL.includes("/library")) {
    libraryObserver.observe(document.body, { childList: true, subtree: true });
    addClickListener();
  }
})();

You can adjust video size and layout by changing “–height_big” variable’s value only, others are automatically adjusted.

If it’s useful, plz hit the like button below.


  • You need to change the background color to dark manually or change the color settings.
  • If the video size is small, you need to expand the video window by pressing Q key.
6 Likes

Any way to change the punctuation color as well? The white really stands out if the font color is set to gray.

Change

  .reader-container p span.sentence-item {
    color: var(--font_color) !important;
  }

to

  .reader-container p .sentence-item, .reader-container p .sentence {
    color: var(--font_color) !important;
  }

Now it works.


Before


After

1 Like

Yes, that works, thank you.

1 Like

New Feature:

  • Now the sentence playing is located at the center of the screen. You don’t need to scrol acording to the playing video.

If you don’t want the sentence is fixed on the exact center use nearest instead of center in this part of the code playingSentence.scrollIntoView({behavior: 'smooth', block: 'center'});
It always locates the sentence inside a screen but not center.

// ==UserScript==
// @name         LingQ Addon
// @description  Custom embedded player, and sort course automatically.
// @match        https://www.lingq.com/*/learn/*/web/reader/*
// @match        https://www.lingq.com/*/learn/*/web/library
// @match        https://www.lingq.com/*/learn/*/web/library/course/*
// @version      1.4
// ==/UserScript==

(function () {
  "use strict";
  
  // Style settings
  var style = document.createElement("style");
  style.textContent = `
  :root {
    --width_small: 440px;
    --height_small: 260px;
    --right_pos: 0.5%;
    --bottom_pos: 5.5%;
    
    --width_big: calc(100vw - 424px - 40px);
    --height_big: 470px;
    
    --font_size: 1.1rem;
    --font_color: #e0e0e0;
    --line_height: 1.7;
    
    --lingq_background: hsl(41 43% 30% / 0.7);
    --lingq_border: hsl(43 99% 64% / 0.3);
    --lingq_border_learned: hsl(43 99% 64% / 0.5);
    --blue_border: hsl(213 99% 64% / 0.5);
    
    --is_playing_underline: #ffffff;
    
    --grid-layout: 1fr var(--height_big) 80px;
    --video_margin: 0 0 90px 10px !important;
    --article_height: calc(var(--app-height) - 165px - var(--height_big));
  }
  
  .main-wrapper {
    padding-top: calc(var(--spacing)* 12) !important;
  }
  
  #main-nav .navbar, #main-nav .navbar-brand {
    min-height: 2.75rem !important;
  }
  
  .main-header svg {
    width: 20px !important;
    height: 20px !important;
  }
  
  #lesson-reader {
    grid-template-rows: var(--grid-layout);
    overflow-y: hidden;
  }
  
  .sentence-text {
  height: var(--article_height) !important;
  }
  
  .reader-container-wrapper {
    height: 100% !important;
  }
  
  /*video viewer*/
  
  .main-footer.has-video {
    grid-area: 3 / 1 / 3 / 1 !important;
    align-self: end;
  }
  
  .widget-area {
    grid-area: 2 / 2 / -1 / 2 !important;
  }
  
  .main-content {
    grid-template-rows: 25px 1fr !important;
    overflow: hidden; 
    grid-area: 1 / 1 / 1 / -1 !important;
    align-items: anchor-center;
  }
  
  .modal-container .modls {
    pointer-events: none;
    justify-content: end !important;
    align-items: flex-start;
  }
  
  .modal-background {
    background-color: rgb(26 28 30 / 0%) !important;
  }
  
  .modal-section.modal-section--head {
    display: none !important;
  }
  
  .video-player .video-wrapper,
  .sent-video-player .video-wrapper {
    height: var(--height_big);
    overflow: hidden;
    pointer-events: auto;
  }

  .modal.video-player .modal-content {
    max-width: var(--width_big);
    margin: var(--video_margin);
  }

  .video-player.is-minimized .video-wrapper,
  .sent-video-player.is-minimized .video-wrapper {
    height: var(--height_small);
    width: var(--width_small);
  }

  .video-player.is-minimized .modal-content,
  .sent-video-player.is-minimized .modal-content {
    max-width: var(--width_small);
    margin-bottom: 0;
  }

  .video-player.is-minimized,
  .sent-video-player.is-minimized {
    left: auto;
    top: auto;
    right: var(--right_pos);
    bottom: var(--bottom_pos);
    z-index: 99999999;
    overflow: visible
  }

  /*make prev/next page buttons compact*/

  .reader-component {
    grid-template-columns: 0.5rem 1fr 0rem !important;
  }

  .reader-component>div>a.button>span {
    width: 0.5rem !important;
  }

  .reader-component>div>a.button>span>svg {
    width: 15px !important;
    height: 15px !important;
  }

  /*font settings*/
  
  .reader-container {
    margin: 0 !important;
    float: left !important;
    line-height: var(--line_height) !important;
    padding: 0 !important;
    font-size: var(--font_size) !important;
    columns: unset !important;
    overflow-y: scroll !important;
    max-width: unset !important;
  }

  .reader-container p {
    margin-top: 0 !important;
  }

  .reader-container p span.sentence-item {
    color: var(--font_color) !important;
  }

  .sentence.is-playing,
  .sentence.is-playing span {
    text-underline-offset: .2em !important;
    text-decoration-color: var(--is_playing_underline) !important;
  }
  
  /*LingQ highlightings*/

  .phrase-item {
    padding: 0 !important;
  }

  .phrase-item:not(.phrase-item-status--4, .phrase-item-status--4x2) {
    background-color: var(--lingq_background) !important;
  }

  .phrase-item.phrase-item-status--4, 
  .phrase-item.phrase-item-status--4x2 {
    background-color: rgba(0, 0, 0, 0) !important;
  }

  .phrase-cluster:not(:has(.phrase-item-status--4, .phrase-item-status--4x2)) {
    border: 1px solid var(--lingq_border) !important;
    border-radius: .25rem;
  }

  .phrase-cluster:has(.phrase-item-status--4, .phrase-item-status--4x2) {
    border: 1px solid var(--lingq_border_learned) !important;
    border-radius: .25rem;
  }

  .reader-container .sentence .lingq-word:not(.is-learned) {
    border: 1px solid var(--lingq_border) !important;
    background-color: var(--lingq_background) !important;
  }

  .reader-container .sentence .lingq-word.is-learned {
    border: 1px solid var(--lingq_border_learned) !important;
  }
  
  .reader-container .sentence .blue-word {
    border: 1px solid var(--blue_border) !important;
  }
  
  .phrase-cluster:hover,
  .phrase-created:hover {
    padding: 0 !important;
  }
  
  .phrase-cluster:hover .phrase-item,
  .phrase-created .phrase-item {
    padding: 0 !important;
  }
  
  .reader-container .sentence .selected-text {
    padding: 0 !important;
  }
  `;
  document.querySelector("head").appendChild(style);
  
  
  // Add new shortcuts
  document.addEventListener('keydown', function(event) {
    const targetElement = event.target;
    const isTextInput = (targetElement.type === 'text' || targetElement.type === 'textarea');
    if (isTextInput) {
      return;
    }
    
    // video full screen toggle
    if (event.key === 'q' || event.key === 'Q') {
      const full_screen_btn = document.querySelector('.modal-section > div > button:nth-child(2)');
      if (full_screen_btn) {
        full_screen_btn.click();
      }
    }
    
    // 5 sec Backward (Same as the 'Ctrl + ,')
    if (event.key === 'w' || event.key === 'W') {
      const full_screen_btn = document.querySelector('.audio-player--controllers > div:nth-child(1) > a');
      if (full_screen_btn) {
        full_screen_btn.click();
      }
      event.stopPropagation();
    }
    
    // 5 sec Forward (Same as the 'Ctrl + .')
    if (event.key === 'e' || event.key === 'E') {
      const full_screen_btn = document.querySelector('.audio-player--controllers > div:nth-child(2) > a');
      if (full_screen_btn) {
        full_screen_btn.click();
      }
      event.stopPropagation();
    }
    
    // Make the selected word Known (Same as the 'k')
    if (event.key === 'r' || event.key === 'R') {
      document.dispatchEvent(new KeyboardEvent('keydown', {key: 'k'}));
    }
  });
  

  // Custom embedded player
  function replaceNoCookie() {
    document.querySelectorAll('iframe').forEach(function(iframe) {
        let src = iframe.getAttribute('src');

        if (src && src.includes('autoplay=0')) {
            src = src.replace('autoplay=0', 'autoplay=1'); // video will automatically start to play.
            src = src.replace('disablekb=1', 'disablekb=0'); // keyboard controls are enabled.
            src = src + '&cc_load_policy=1' // caption is shown by default.
            src = src + '&controls=0' // player controls do not display in the player.
            iframe.setAttribute('src', src);
            console.log(src);
        }
    });
  }

  const iframeObserver = new MutationObserver(function(mutationsList, observer) {
      for (const mutation of mutationsList) {
          if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
              mutation.addedNodes.forEach(node => {
                  if (node.nodeName === 'IFRAME') {
                      replaceNoCookie();
                  } else if (node.querySelectorAll) {
                      node.querySelectorAll('iframe').forEach(replaceNoCookie);
                  }
              });
          } else if (mutation.type === 'attributes' && mutation.attributeName === 'src' && mutation.target.nodeName === 'IFRAME') {
              replaceNoCookie();
          }
      }
  });

  if (document.URL.includes("/reader/")) {
    iframeObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['src'] });
  }


  // Change the amount of a scroll
  setTimeout(() => {
    console.log('scroll event!');
    const myDiv = document.querySelector('.reader-container');
    myDiv.addEventListener('wheel', (event) => {
      event.preventDefault();
      const delta = event.deltaY;
      const scrollAmount = 0.3;
      myDiv.scrollTop += delta * scrollAmount;
    });
  }, 3000);


  // Focus on playing sentence
  function focusPlayingSentence() {
    const playingSentence = document.querySelector('.sentence.is-playing');

    if (playingSentence) {
    playingSentence.scrollIntoView({behavior: 'smooth', block: 'center'});
    }
  }

  const observer = new MutationObserver(mutations => {
    mutations.forEach(mutation => {
    if (mutation.type === 'attributes' && mutation.attributeName === 'class' && mutation.target.classList.contains('sentence')) {
      focusPlayingSentence();
    }
    });
  });

  const container = document.querySelector('.sentence-text'); 
  if (container) {
  	console.log('observer setted!')
    observer.observe(container, { attributes: true, subtree: true }); 
  }

  
  // Sort courses
  function addClickListener() {
    document.querySelectorAll("div.library-item-wrap").forEach((item) => {
      if (!item.dataset.listenerAdded) {
        item.addEventListener("click", function () {
          setTimeout(() => {
            /* Change the number in .dropdown-item:nth-child(3) by your preference
               1: All lessons
               2: Oldest to Newest
               3: Newest to Oldest
               4: Last Opened
               5: New Words %
               6: A-Z */
            document.querySelector(
              ".library-item--menu-box .collection-section--controllers .dropdown-item:nth-child(5)"
            ).click();
          }, 1000);
        });
        item.dataset.listenerAdded = true;
      }
    });
  }

  const libraryObserver = new MutationObserver(addClickListener);
  if (document.URL.includes("/library")) {
    libraryObserver.observe(document.body, { childList: true, subtree: true });
    addClickListener();
  }
  
  if (document.URL.includes("/library/course/")) {
    setTimeout(() => {
      document.querySelector(
        ".library-sections--item .dropdown-content .dropdown-item:nth-child(5)"
      ).click();
    }, 2000);
  }
})();

New hotkeys

  • Move the cursor to the reference input (`): it directly moves the keyboard cursor to the text field in the widget.
  • Open Dictionary (d or f): it works when multiple words are selected
  • Open Translator (t): it works when multiple words are selected
  • Copy selected text (c): copy selected text in a clipboard (I use it when using LLM)

Of course, you can change the hotkeys in your favor.


The Open Dictionary key clicks the first dictionary and the Open Translator selects the last. So you need to set them properly

image


You can change the order of the dicts here.


// ==UserScript==
// @name         LingQ Addon
// @description  Custom embedded player, and sort course automatically.
// @match        https://www.lingq.com/*/learn/*/web/reader/*
// @match        https://www.lingq.com/*/learn/*/web/library
// @match        https://www.lingq.com/*/learn/*/web/library/course/*
// @version      1.5
// ==/UserScript==

(function () {
  "use strict";
  
  // Style settings
  var style = document.createElement("style");
  style.textContent = `
  :root {
    --width_small: 440px;
    --height_small: 260px;
    --right_pos: 0.5%;
    --bottom_pos: 5.5%;
    
    --width_big: calc(100vw - 424px - 40px);
    --height_big: 470px;
    
    --font_size: 1.1rem;
    --font_color: #e0e0e0;
    --line_height: 1.7;
    
    --lingq_background: hsl(41 43% 30% / 0.7);
    --lingq_border: hsl(43 99% 64% / 0.3);
    --lingq_border_learned: hsl(43 99% 64% / 0.5);
    --blue_border: hsl(213 99% 64% / 0.5);
    
    --is_playing_underline: #ffffff;
    
    --grid-layout: 1fr var(--height_big) 80px;
    --video_margin: 0 0 90px 10px !important;
    --article_height: calc(var(--app-height) - 165px - var(--height_big));
  }
  
  .main-wrapper {
    padding-top: calc(var(--spacing)* 12) !important;
  }
  
  #main-nav .navbar, #main-nav .navbar-brand {
    min-height: 2.75rem !important;
  }
  
  .main-header svg {
    width: 20px !important;
    height: 20px !important;
  }
  
  #lesson-reader {
    grid-template-rows: var(--grid-layout);
    overflow-y: hidden;
  }
  
  .sentence-text {
  height: var(--article_height) !important;
  }
  
  .reader-container-wrapper {
    height: 100% !important;
  }
  
  /*video viewer*/
  
  .main-footer.has-video {
    grid-area: 3 / 1 / 3 / 1 !important;
    align-self: end;
  }
  
  .widget-area {
    grid-area: 2 / 2 / -1 / 2 !important;
  }
  
  .main-content {
    grid-template-rows: 25px 1fr !important;
    overflow: hidden; 
    grid-area: 1 / 1 / 1 / -1 !important;
    align-items: anchor-center;
  }
  
  .modal-container .modls {
    pointer-events: none;
    justify-content: end !important;
    align-items: flex-start;
  }
  
  .modal-background {
    background-color: rgb(26 28 30 / 0%) !important;
  }
  
  .modal-section.modal-section--head {
    display: none !important;
  }
  
  .video-player .video-wrapper,
  .sent-video-player .video-wrapper {
    height: var(--height_big);
    overflow: hidden;
    pointer-events: auto;
  }

  .modal.video-player .modal-content {
    max-width: var(--width_big);
    margin: var(--video_margin);
  }

  .video-player.is-minimized .video-wrapper,
  .sent-video-player.is-minimized .video-wrapper {
    height: var(--height_small);
    width: var(--width_small);
  }

  .video-player.is-minimized .modal-content,
  .sent-video-player.is-minimized .modal-content {
    max-width: var(--width_small);
    margin-bottom: 0;
  }

  .video-player.is-minimized,
  .sent-video-player.is-minimized {
    left: auto;
    top: auto;
    right: var(--right_pos);
    bottom: var(--bottom_pos);
    z-index: 99999999;
    overflow: visible
  }

  /*make prev/next page buttons compact*/

  .reader-component {
    grid-template-columns: 0.5rem 1fr 0rem !important;
  }

  .reader-component>div>a.button>span {
    width: 0.5rem !important;
  }

  .reader-component>div>a.button>span>svg {
    width: 15px !important;
    height: 15px !important;
  }

  /*font settings*/
  
  .reader-container {
    margin: 0 !important;
    float: left !important;
    line-height: var(--line_height) !important;
    padding: 0 !important;
    font-size: var(--font_size) !important;
    columns: unset !important;
    overflow-y: scroll !important;
    max-width: unset !important;
  }

  .reader-container p {
    margin-top: 0 !important;
  }

  .reader-container p span.sentence-item {
    color: var(--font_color) !important;
  }

  .sentence.is-playing,
  .sentence.is-playing span {
    text-underline-offset: .2em !important;
    text-decoration-color: var(--is_playing_underline) !important;
  }
  
  /*LingQ highlightings*/

  .phrase-item {
    padding: 0 !important;
  }

  .phrase-item:not(.phrase-item-status--4, .phrase-item-status--4x2) {
    background-color: var(--lingq_background) !important;
  }

  .phrase-item.phrase-item-status--4, 
  .phrase-item.phrase-item-status--4x2 {
    background-color: rgba(0, 0, 0, 0) !important;
  }

  .phrase-cluster:not(:has(.phrase-item-status--4, .phrase-item-status--4x2)) {
    border: 1px solid var(--lingq_border) !important;
    border-radius: .25rem;
  }

  .phrase-cluster:has(.phrase-item-status--4, .phrase-item-status--4x2) {
    border: 1px solid var(--lingq_border_learned) !important;
    border-radius: .25rem;
  }

  .reader-container .sentence .lingq-word:not(.is-learned) {
    border: 1px solid var(--lingq_border) !important;
    background-color: var(--lingq_background) !important;
  }

  .reader-container .sentence .lingq-word.is-learned {
    border: 1px solid var(--lingq_border_learned) !important;
  }
  
  .reader-container .sentence .blue-word {
    border: 1px solid var(--blue_border) !important;
  }
  
  .phrase-cluster:hover,
  .phrase-created:hover {
    padding: 0 !important;
  }
  
  .phrase-cluster:hover .phrase-item,
  .phrase-created .phrase-item {
    padding: 0 !important;
  }
  
  .reader-container .sentence .selected-text {
    padding: 0 !important;
  }
  `;
  document.querySelector("head").appendChild(style);
  
  
  // Add new shortcuts
  document.addEventListener('keydown', function(event) {
    const targetElement = event.target;
    const isTextInput = (targetElement.type === 'text' || targetElement.type === 'textarea');
    if (isTextInput) {
      return;
    }
    
    // video full screen toggle
    if (event.key === 'q' || event.key === 'Q') {
      const full_screen_btn = document.querySelector('.modal-section > div > button:nth-child(2)');
      if (full_screen_btn) {
        full_screen_btn.click();
      }
    }
    
    // 5 sec Backward (Same as the 'Ctrl + ,')
    if (event.key === 'w') {
      const backward_btn = document.querySelector('.audio-player--controllers > div:nth-child(1) > a');
      if (backward_btn) {
        backward_btn.click();
      }
      event.stopPropagation();
    }
    
    // 5 sec Forward (Same as the 'Ctrl + .')
    if (event.key === 'e') {
      const forkward_btn = document.querySelector('.audio-player--controllers > div:nth-child(2) > a');
      if (forkward_btn) {
        forkward_btn.click();
      }
      event.stopPropagation();
    }
    
    // Make the selected word Known (Same as the 'k')
    if (event.key === 'r') {
      document.dispatchEvent(new KeyboardEvent('keydown', {key: 'k'}));
      event.stopPropagation();
    }
    
    // Move cursor to the reference input
    if (event.key === '`') {
      const reference_input = document.querySelector('.reference-input-text');

      if (reference_input) {
          reference_input.focus();
          reference_input.setSelectionRange(reference_input.value.length, reference_input.value.length);
      }
      event.preventDefault();
      event.stopPropagation();  
    }
    
    // Open Dictionary
    if (event.key === 'd' || event.key === 'f') {
      const dict_btn = document.querySelector('.dictionary-resources > a:nth-child(1)');
      if (dict_btn) {
        dict_btn.click();
      }
      event.stopPropagation();
    }
    
    // Open Translator
    if (event.key === 't') {
      const translator_btn = document.querySelector('.dictionary-resources > a:nth-last-child(1)');
      if (translator_btn) {
        translator_btn.click();
      }
      event.stopPropagation();
    }
    
    // Copy selected text
    if (event.key === 'c') {
      const selected_text = document.querySelector('.reference-word');
      if (selected_text) {
        navigator.clipboard.writeText(selected_text.textContent);
      }
      event.stopPropagation();
    }
    
  });
  

  // Custom embedded player
  function replaceNoCookie() {
    document.querySelectorAll('iframe').forEach(function(iframe) {
        let src = iframe.getAttribute('src');

        if (src && src.includes('autoplay=0')) {
            src = src.replace('autoplay=0', 'autoplay=1'); // video will automatically start to play.
            src = src.replace('disablekb=1', 'disablekb=0'); // keyboard controls are enabled.
            src = src + '&cc_load_policy=1' // caption is shown by default.
            src = src + '&controls=0' // player controls do not display in the player.
            iframe.setAttribute('src', src);
            console.log(src);
        }
    });
  }

  const iframeObserver = new MutationObserver(function(mutationsList, observer) {
      for (const mutation of mutationsList) {
          if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
              mutation.addedNodes.forEach(node => {
                  if (node.nodeName === 'IFRAME') {
                      replaceNoCookie();
                  } else if (node.querySelectorAll) {
                      node.querySelectorAll('iframe').forEach(replaceNoCookie);
                  }
              });
          } else if (mutation.type === 'attributes' && mutation.attributeName === 'src' && mutation.target.nodeName === 'IFRAME') {
              replaceNoCookie();
          }
      }
  });

  if (document.URL.includes("/reader/")) {
    iframeObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['src'] });
  }


  // Change the amount of a scroll
  setTimeout(() => {
    console.log('scroll event!');
    const myDiv = document.querySelector('.reader-container');
    myDiv.addEventListener('wheel', (event) => {
      event.preventDefault();
      const delta = event.deltaY;
      const scrollAmount = 0.3;
      myDiv.scrollTop += delta * scrollAmount;
    });
  }, 3000);


  // Focus on playing sentence
  function focusPlayingSentence() {
    const playingSentence = document.querySelector('.sentence.is-playing');

    if (playingSentence) {
    playingSentence.scrollIntoView({behavior: 'smooth', block: 'center'});
    }
  }

  const observer = new MutationObserver(mutations => {
    mutations.forEach(mutation => {
    if (mutation.type === 'attributes' && mutation.attributeName === 'class' && mutation.target.classList.contains('sentence')) {
      focusPlayingSentence();
    }
    });
  });

  const container = document.querySelector('.sentence-text'); 
  if (container) {
  	console.log('observer setted!')
    observer.observe(container, { attributes: true, subtree: true }); 
  }

  
  // Sort courses
  function addClickListener() {
    document.querySelectorAll("div.library-item-wrap").forEach((item) => {
      if (!item.dataset.listenerAdded) {
        item.addEventListener("click", function () {
          setTimeout(() => {
            /* Change the number in .dropdown-item:nth-child(3) by your preference
               1: All lessons
               2: Oldest to Newest
               3: Newest to Oldest
               4: Last Opened
               5: New Words %
               6: A-Z */
            document.querySelector(
              ".library-item--menu-box .collection-section--controllers .dropdown-item:nth-child(5)"
            ).click();
          }, 1000);
        });
        item.dataset.listenerAdded = true;
      }
    });
  }

  const libraryObserver = new MutationObserver(addClickListener);
  if (document.URL.includes("/library")) {
    libraryObserver.observe(document.body, { childList: true, subtree: true });
    addClickListener();
  }
  
  if (document.URL.includes("/library/course/")) {
    setTimeout(() => {
      document.querySelector(
        ".library-sections--item .dropdown-content .dropdown-item:nth-child(5)"
      ).click();
    }, 2000);
  }
})();

I’ve yet to figure out how to enable this script via tampermonkey. Tampermonkey us enabled, I pasted in the script provided and saved it, that’s now in the extension an turned on, I’ve reloaded, nothing works. I’ve enabled developer mode for TM too. I watched a couple videos, nothing is showing the missing step unfortunatly.

1 Like

I’m not sure what the problem is with it.
This is the process i had and works. Uninstall the extension and follow the procedure.

  1. install Tampermonkey from chrome store
  2. open Extension from the upper navbar and click ‘Create a new script’ button.
  3. Copy and paste the script I provide.
  4. refresh LingQ reader page.

image

It could be the issue with the URL format. Let me know the URL of your reader page. Browser also.

Ok I followed those instructions. This time something change a little but nowhere close to what it shoud look like, and I tried it on a clean account with no other extensions which could possibly interfere. I tried it within firefox too and the same weird / incomplete effect happens.

Here is the url I’m on for reader mode:
image

What it looks like for me:

What I pasted in (beginning and end):


Enabled:


image

image

This is the layout I intended. It seems to work on your PC.
Hit the ‘Q’ key after loading the video to expand the video and fill its area.

If the video size is too large, adjust –height_big variable

If your monitor’s resolution is too low, you might need to change the fontsize and video size to reserve enough space for text.

This is 1920x1080 setup

1 Like

Q Key! Ok that resolved it and then I feel like I dope, I was expecting darkmode to be turned on via the script and I realized I needed to enable that seperatly in LingQ settings. Anyway, all good now, thanks for the help!

Yup. Have a good night or day!

1 Like

How can I change this situation??

Click the Aa button in the upper right corner and select the black background color. If you prefer light mode, change color values in the source code.

This css is for audio lesson users.

  :root {
    --width_small: 440px;
    --height_small: 260px;
    --right_pos: 0.5%;
    --bottom_pos: 5.5%;
    
    --width_big: calc(100vw - 424px - 5px);
    --height_big: 10px;
    
    --font_size: 1.1rem;
    --font_color: #e0e0e0;
    --line_height: 2.7;
    
    --lingq_background: hsl(41 43% 30% / 0.7);
    --lingq_border: hsl(43 99% 64% / 0.3);
    --lingq_border_learned: hsl(43 99% 64% / 0.5);
    --blue_border: hsl(213 99% 64% / 0.5);
    
    --is_playing_underline: #ffffff;
    
    --grid-layout: 1fr var(--height_big) 80px;
    --video_margin: 0 0 90px 10px !important;
    --article_height: calc(var(--app-height) - 175px - var(--height_big));
  }
  
  .main-wrapper {
    padding-top: calc(var(--spacing)* 12) !important;
  }
  
  #main-nav .navbar, #main-nav .navbar-brand {
    min-height: 2.75rem !important;
  }
  
  .main-header svg {
    width: 20px !important;
    height: 20px !important;
  }
  
  #lesson-reader {
    grid-template-rows: var(--grid-layout);
    overflow-y: hidden;
  }
  
  .sentence-text {
  height: var(--article_height) !important;
  }
  
  .reader-container-wrapper {
    height: 100% !important;
  }
  
  /*video viewer*/
  
  .main-footer {
    grid-area: 3 / 1 / 3 / 1 !important;
    align-self: end;
  }
  
  .widget-area {
    grid-area: 1 / 2 / -1 / 2 !important;
}
  
  .main-content {
    grid-template-rows: 45px 1fr !important;
    overflow: hidden;
    grid-area: 1 / 1 / 2 / 1 !important;
    align-items: anchor-center;
}
  
  .modal-container .modls {
    pointer-events: none;
    justify-content: end !important;
    align-items: flex-start;
  }
  
  .modal-background {
    background-color: rgb(26 28 30 / 0%) !important;
  }
  
  .modal-section.modal-section--head {
    display: none !important;
  }
  
  .video-player .video-wrapper,
  .sent-video-player .video-wrapper {
    height: var(--height_big);
    overflow: hidden;
    pointer-events: auto;
  }

  .modal.video-player .modal-content {
    max-width: var(--width_big);
    margin: var(--video_margin);
  }

  .video-player.is-minimized .video-wrapper,
  .sent-video-player.is-minimized .video-wrapper {
    height: var(--height_small);
    width: var(--width_small);
  }

  .video-player.is-minimized .modal-content,
  .sent-video-player.is-minimized .modal-content {
    max-width: var(--width_small);
    margin-bottom: 0;
  }

  .video-player.is-minimized,
  .sent-video-player.is-minimized {
    left: auto;
    top: auto;
    right: var(--right_pos);
    bottom: var(--bottom_pos);
    z-index: 99999999;
    overflow: visible
  }

  /*make prev/next page buttons compact*/

  .reader-component {
    grid-template-columns: 0.5rem 1fr 0rem !important;
  }

  .reader-component>div>a.button>span {
    width: 0.5rem !important;
  }

  .reader-component>div>a.button>span>svg {
    width: 15px !important;
    height: 15px !important;
  }

  /*font settings*/
  
  .reader-container {
    margin: 0 !important;
    float: left !important;
    line-height: var(--line_height) !important;
    padding: 0 !important;
    font-size: var(--font_size) !important;
    columns: unset !important;
    overflow-y: scroll !important;
    max-width: unset !important;
  }

  .reader-container p {
    margin-top: 0 !important;
  }

  .reader-container p span.sentence-item {
    color: var(--font_color) !important;
  }

  .sentence.is-playing,
  .sentence.is-playing span {
    text-underline-offset: .2em !important;
    text-decoration-color: var(--is_playing_underline) !important;
  }
  
  /*LingQ highlightings*/

  .phrase-item {
    padding: 0 !important;
  }

  .phrase-item:not(.phrase-item-status--4, .phrase-item-status--4x2) {
    background-color: var(--lingq_background) !important;
  }

  .phrase-item.phrase-item-status--4, 
  .phrase-item.phrase-item-status--4x2 {
    background-color: rgba(0, 0, 0, 0) !important;
  }

  .phrase-cluster:not(:has(.phrase-item-status--4, .phrase-item-status--4x2)) {
    border: 1px solid var(--lingq_border) !important;
    border-radius: .25rem;
  }

  .phrase-cluster:has(.phrase-item-status--4, .phrase-item-status--4x2) {
    border: 1px solid var(--lingq_border_learned) !important;
    border-radius: .25rem;
  }

  .reader-container .sentence .lingq-word:not(.is-learned) {
    border: 1px solid var(--lingq_border) !important;
    background-color: var(--lingq_background) !important;
  }

  .reader-container .sentence .lingq-word.is-learned {
    border: 1px solid var(--lingq_border_learned) !important;
  }
  
  .reader-container .sentence .blue-word {
    border: 1px solid var(--blue_border) !important;
  }
  
  .phrase-cluster:hover,
  .phrase-created:hover {
    padding: 0 !important;
  }
  
  .phrase-cluster:hover .phrase-item,
  .phrase-created .phrase-item {
    padding: 0 !important;
  }
  
  .reader-container .sentence .selected-text {
    padding: 0 !important;
  }

It hides the annoying “more videos” popup and the YT logo from the mini video player.
You can read subtitles when a video is paused.
Use it together with my LingQ Add-on script.

Before

After

// ==UserScript==
// @name         Collapse More-videos
// @description  Automatically collapse More videos popup in YouTube.
// @match        https://www.youtube-nocookie.com/*
// @version      1.5
// ==/UserScript==

(function () {
  "use strict";
  
  document.addEventListener('keydown', function(event) {
    const targetElement = event.target;

    // dismiss subtitle background opacity setting key (w)
    if (event.key === 'w') {
    console.log('w');
    event.preventDefault(); 
    event.stopPropagation();
    }
  }, true); 
  
  function clickPlayButton() {
    document.querySelector(".ytp-button.ytp-large-play-button").click();
  }

  function clickCollapseButton() {
    document.querySelector(".ytp-button.ytp-collapse").click();
  }

  function clickSubtitleButton() {
    document.querySelector(".ytp-button.ytp-subtitles-button").click();
  }

  window.addEventListener("load", function () {
    setTimeout(() => {
      clickPlayButton();
      clickCollapseButton();
      clickPlayButton();
    }, 100);
  });

  var style = document.createElement("style");
  style.textContent = `
  div.ytp-pause-overlay{
    visibility: hidden !important;
  }
  a.ytp-watermark{
    visibility: hidden !important;
  }
`;

  document.querySelector("head").appendChild(style);
})();


In the default lingQ interface, the state 4 of the word will hide the yellow prompt, but the yellow prompt will still be displayed under the script, how can I change the target, and the yellow prompt will be hidden when the state 4 is hidden?

I intentionally maintained the border of the known words. If you don’t like it, change the code.

--lingq_border_learned: hsl(43 99% 64% / 0.5);
to
--lingq_border_learned: hsl(43 99% 64% / 0);


Additional Tip

You can open DevTools with F12 key. There, you can change the variables interatively. Use it when you test UI elements.
(The change made here is not saved, so make sure that you change the corresponding script’s values.)

Change Log

v1.6: Now, LingQ uses “youtube.com” player, not “youtube-nocookie.com”. Some code is updated for that change.

Also, now the videos you watch in LingQ show up in YouTube watch history (previously not). In other words, YT algorithm will consider the video played in LingQ.

LingQ automatically play the video, and auto-played video doesn’t counted as a view. So, not appear in YT history page.

Script for YouTube Player

// ==UserScript==
// @name         Collapse More-videos
// @description  Automatically collapse More videos popup in YouTube.
// @match        https://www.youtube-nocookie.com/*
// @match        https://www.youtube.com/embed/*
// @version      1.6
// ==/UserScript==

(function () {
  "use strict";
  
  document.addEventListener('keydown', function(event) {
    const targetElement = event.target;

    // dismiss subtitle background opacity setting key (w)
    if (event.key === 'w') {
    console.log('w');
    event.preventDefault(); 
    event.stopPropagation();
    }
  }, true); 
  
  function clickPlayButton() {
    document.querySelector(".ytp-button.ytp-large-play-button").click();
  }

  function clickCollapseButton() {
    document.querySelector(".ytp-button.ytp-collapse").click();
  }

  function clickSubtitleButton() {
    document.querySelector(".ytp-button.ytp-subtitles-button").click();
  }

  window.addEventListener("load", function () {
    setTimeout(() => {
      clickPlayButton();
      clickCollapseButton();
      clickPlayButton();
    }, 100);
  });

  var style = document.createElement("style");
  style.textContent = `
  div.ytp-pause-overlay{
    visibility: hidden !important;
  }
  a.ytp-watermark{
    visibility: hidden !important;
  }
`;

  document.querySelector("head").appendChild(style);
})();

Script for LingQ website

// ==UserScript==
// @name         LingQ Addon
// @description  Custom embedded player, and sort course automatically.
// @match        https://www.lingq.com/*/learn/*/web/reader/*
// @match        https://www.lingq.com/*/learn/*/web/library
// @match        https://www.lingq.com/*/learn/*/web/library/course/*
// @version      1.6
// ==/UserScript==

(function () {
  "use strict";

  // Style settings
  var style = document.createElement("style");
  style.textContent = `
  //PASTE THE CSS HERE
  `;
  document.querySelector("head").appendChild(style);
  
  // Add new shortcuts
  document.addEventListener('keydown', function(event) {
    const targetElement = event.target;
    const isTextInput = (targetElement.type === 'text' || targetElement.type === 'textarea');
    if (isTextInput) {
      return;
    }
    
    // video full screen toggle
    if (event.key === 'q' || event.key === 'Q') {
      const full_screen_btn = document.querySelector('.modal-section > div > button:nth-child(2)');
      if (full_screen_btn) {
        full_screen_btn.click();
      }
      event.preventDefault();
      event.stopPropagation();
    }
    
    // 5 sec Backward (Same as the 'Ctrl + ,')
    if (event.key === 'w') {
      const backward_btn = document.querySelector('.audio-player--controllers > div:nth-child(1) > a');
      if (backward_btn) {
        backward_btn.click();
      }
      event.preventDefault();
      event.stopPropagation();
    }
    
    // 5 sec Forward (Same as the 'Ctrl + .')
    if (event.key === 'e') {
      const forkward_btn = document.querySelector('.audio-player--controllers > div:nth-child(2) > a');
      if (forkward_btn) {
        forkward_btn.click();
      }
      event.preventDefault();
      event.stopPropagation();
    }
    
    // Make the selected word Known (Same as the 'k')
    if (event.key === 'r') {
      document.dispatchEvent(new KeyboardEvent('keydown', {key: 'k'}));
      event.preventDefault();
      event.stopPropagation();
    }
    
    // Move cursor to the reference input
    if (event.key === '`') {
      const reference_input = document.querySelector('.reference-input-text');

      if (reference_input) {
          reference_input.focus();
          reference_input.setSelectionRange(reference_input.value.length, reference_input.value.length);
      }
      event.preventDefault();
      event.stopPropagation();  
    }
    
    // Open Dictionary
    if (event.key === 'd' || event.key === 'f') {
      const dict_btn = document.querySelector('.dictionary-resources > a:nth-child(1)');
      if (dict_btn) {
        dict_btn.click();
      }
      event.preventDefault();
      event.stopPropagation();
    }
    
    // Open Translator
    if (event.key === 't') {
      const translator_btn = document.querySelector('.dictionary-resources > a:nth-last-child(1)');
      if (translator_btn) {
        translator_btn.click();
      }
      event.preventDefault();
      event.stopPropagation();
    }
    
    // Copy selected text
    if (event.key === 'c') {
      const selected_text = document.querySelector('.reference-word');
      if (selected_text) {
        navigator.clipboard.writeText(selected_text.textContent);
      }
      event.preventDefault();
      event.stopPropagation();
    }
    
  });
  

  // Custom embedded player
  function replaceNoCookie() {
    document.querySelectorAll('iframe').forEach(function(iframe) {
        let src = iframe.getAttribute('src');

        if (src && src.includes('disablekb=1')) {
            // src = src.replace('autoplay=0', 'autoplay=1'); // video will automatically start to play.
            src = src.replace('disablekb=1', 'disablekb=0'); // keyboard controls are enabled.
            src = src + '&cc_load_policy=1' // caption is shown by default.
            src = src + '&controls=0' // player controls do not display in the player.
            iframe.setAttribute('src', src);
            console.log(src);
        }
    });
  }

  const iframeObserver = new MutationObserver(function(mutationsList, observer) {
      for (const mutation of mutationsList) {
          if (mutation.type === 'childList' && mutation.addedNodes.length > 0) {
              mutation.addedNodes.forEach(node => {
                  if (node.nodeName === 'IFRAME') {
                      replaceNoCookie();
                  } else if (node.querySelectorAll) {
                      node.querySelectorAll('iframe').forEach(replaceNoCookie);
                  }
              });
          } else if (mutation.type === 'attributes' && mutation.attributeName === 'src' && mutation.target.nodeName === 'IFRAME') {
              replaceNoCookie();
          }
      }
  });

  if (document.URL.includes("/reader/")) {
    iframeObserver.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['src'] });
  }


  // Change the amount of a scroll
  setTimeout(() => {
    console.log('scroll event!');
    const myDiv = document.querySelector('.reader-container');
    myDiv.addEventListener('wheel', (event) => {
      event.preventDefault();
      const delta = event.deltaY;
      const scrollAmount = 0.3;
      myDiv.scrollTop += delta * scrollAmount;
    });
  }, 3000);


  // Focus on playing sentence
  function focusPlayingSentence() {
    const playingSentence = document.querySelector('.sentence.is-playing');

    if (playingSentence) {
    playingSentence.scrollIntoView({behavior: 'smooth', block: 'center'});
    }
  }

  const observer = new MutationObserver(mutations => {
    mutations.forEach(mutation => {
    if (mutation.type === 'attributes' && mutation.attributeName === 'class' && mutation.target.classList.contains('sentence')) {
      focusPlayingSentence();
    }
    });
  });

  const container = document.querySelector('.sentence-text'); 
  if (container) {
  	console.log('observer setted!')
    observer.observe(container, { attributes: true, subtree: true }); 
  }

  
  // Sort courses
  function addClickListener() {
    document.querySelectorAll("div.library-item-wrap").forEach((item) => {
      if (!item.dataset.listenerAdded) {
        item.addEventListener("click", function () {
          setTimeout(() => {
            /* Change the number in .dropdown-item:nth-child(3) by your preference
               1: All lessons
               2: Oldest to Newest
               3: Newest to Oldest
               4: Last Opened
               5: New Words %
               6: A-Z */
            document.querySelector(
              ".library-item--menu-box .collection-section--controllers .dropdown-item:nth-child(5)"
            ).click();
          }, 1000);
        });
        item.dataset.listenerAdded = true;
      }
    });
  }

  const libraryObserver = new MutationObserver(addClickListener);
  if (document.URL.includes("/library")) {
    libraryObserver.observe(document.body, { childList: true, subtree: true });
    addClickListener();
  }
  
  if (document.URL.includes("/library/course/")) {
    setTimeout(() => {
      document.querySelector(
        ".library-sections--item .dropdown-content .dropdown-item:nth-child(5)"
      ).click();
    }, 2000);
  }
})();