You can use the script by importing it from Tampermonkey or other Uaserscript extensions.
This is the screenshot
I’m sick of adjusting the size and location of my YouTube popup whenever I open a new lesson. So, I automate these steps with a Usersctipt. You can change the parameters (width, height, right, bottom) by your own preference. It also adjust the size of left/right page buttons for wider screen.
Another feature is that automatically changes the sorting option in a course page. I don’t like the default ‘All lessons’. So, it automatically changes it to the ‘Newest to Oldest’ Option. You can change what would be defaulted by changing the number in this part of the code a.dropdown-item:nth-child(3)
.
1: All lessons
2: Oldest to Newest
3: Newest to Oldest
4: Last Opened
5: New Words %
6: A-Z
Feel free to modify it!
// ==UserScript==
// @name LingQ Addons
// @match https://www.lingq.com/*/learn/*/web/reader/*
// @match https://www.lingq.com/*/learn/*/web/library
// @grant none
// ==/UserScript==
(function () {
"use strict";
// Resize youtube video
var height = 370;
var width = 540;
var right = 0.1;
var bottom = 13;
var style = document.createElement("style");
style.textContent = `
div.video-wrapper {
height: ${height}px !important;
width: ${width}px !important;
}
div.modal-content.is-medium {
max-width: ${width}px !important;
}
div.modal {
right: ${right}% !important;
bottom: ${bottom}% !important;
}
div.sentence--video-player > div > div {
height: ${height}px !important;
width: ${width}px !important;
}
div.reader-container {
margin: 0 !important;
justify-self: stretch !important;
}
div.reader-component {
grid-template-columns: 1.5rem 1fr 1.5rem !important;
}
div.reader-component a.button span {
width: 1.5rem !important;
}
`;
document.querySelector("head").appendChild(style);
// Sort courses
function addClickListener() {
document.querySelectorAll('div.library-item-wrap').forEach(item => {
if (!item.dataset.listenerAdded) {
item.addEventListener('click', function () {
setTimeout(() => {
document.querySelector('div.collection-section--controllers > div.dropdown > div.dropdown-menu > div.dropdown-content > a.dropdown-item:nth-child(3)').click();
}, 500);
});
item.dataset.listenerAdded = true;
}
});
}
const observer = new MutationObserver(addClickListener);
observer.observe(document.body, { childList: true, subtree: true });
addClickListener();
})();
6 Likes
vet8t6z79pc4:
Tampermonkey
Visit this website and search about it
2 Likes
Hi, could you share the link? I couldn’t find it on Greasy Fork. Thanks!
1 Like
Just copy & paste the script I attached above to your Tampermonkey or others.
You can use the script by importing it from Tampermonkey or other Uaserscript extensions.
This is the screenshot
[image]
I’m sick of adjusting the size and location of my YouTube popup whenever I open a new lesson. So, I automate these steps with a Usersctipt. You can change the parameters (width, height, right, bottom) by your own preference. It also adjust the size of left/right page buttons for wider screen.
Another feature is that automatically changes the sorting option in a course pag…
1 Like
I just added another modification. The embedded YouTube video will be automatically played with subtitles on.
// ==UserScript==
// @name LingQ Addon
// @match https://www.lingq.com/*/learn/*/web/reader/*
// @match https://www.lingq.com/*/learn/*/web/library
// @description Custom embedded player, and sort course automatically.
// ==/UserScript==
(function () {
"use strict";
// Restyle embedded player
var height = 370;
var width = 540;
var right = 0.1;
var bottom = 13;
var style = document.createElement("style");
style.textContent = `
div.video-wrapper {
height: ${height}px !important;
width: ${width}px !important;
}
div.modal-content.is-medium {
max-width: ${width}px !important;
}
div.modal {
right: ${right}% !important;
bottom: ${bottom}% !important;
}
div.sentence--video-player > div > div {
height: ${height}px !important;
width: ${width}px !important;
}
div.reader-container {
margin: 0 !important;
justify-self: stretch !important;
}
div.reader-component {
grid-template-columns: 1.5rem 1fr 1.5rem !important;
}
div.reader-component a.button span {
width: 1.5rem !important;
}
`;
document.querySelector("head").appendChild(style);
// 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');
src = src + '&cc_load_policy=1'
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(() => {
document
.querySelector(
"div.collection-section--controllers > div.dropdown > div.dropdown-menu > div.dropdown-content > a.dropdown-item:nth-child(3)",
)
.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();
}
})();
Before
After
Also, consider this script that automatically collapses the irritating “More videos popup” in the player occurring when the video is paused. It helps me to read subtitles more easily.
// ==UserScript==
// @name Collapse More-videos
// @description Automatically collapse More videos popup in YouTube.
// @match https://www.youtube-nocookie.com/*
// ==/UserScript==
(function () {
"use strict";
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;
}
`;
document.querySelector("head").appendChild(style);
})();
2 Likes
Nice!!!
BTW, if you delete this bit, the video can be dragged again:
div.modal {
right: ${right}% !important;
bottom: ${bottom}% !important;
}
Also, replacing the size vars with this bit makes it easy to keep the correct 16:9 aspect ratio, or any other you choose:
// Resize youtube video
var base_size = 60;
var height = 9*base_size;
var width = 16*base_size;
var right = 0.1;
var bottom = 13;
1 Like
I adjusted some code.
Now, it only sets the default position and users can drag the video window to a new position.
And it does not fix video size in full-screen view.
// ==UserScript==
// @name LingQ Addon
// @match https://www.lingq.com/*/learn/*/web/reader/*
// @match https://www.lingq.com/*/learn/*/web/library
// @description Custom embedded player, and sort course automatically.
// ==/UserScript==
(function () {
"use strict";
// Restyle embedded player
var height = 370;
var width = 540;
var height_big = 650;
var width_big = 1100;
var right = 0.1;
var bottom = 13;
var style = document.createElement("style");
style.textContent = `
.video-player .video-wrapper,.sent-video-player .video-wrapper {
height: ${height_big}px;
overflow: hidden;
}
.modal.video-player .modal-content {
max-width: ${width_big}px;
margin-bottom: 0;
}
.video-player.is-minimized .video-wrapper,.sent-video-player.is-minimized .video-wrapper {
height: ${height}px;
width: ${width}px;
}
.video-player.is-minimized .modal-content,.sent-video-player.is-minimized .modal-content {
max-width: ${width}px;
margin-bottom: 0;
}
.video-player.is-minimized,.sent-video-player.is-minimized {
left: auto;
top: auto;
right: ${right}%;
bottom: ${bottom}%;
z-index: 99999999;
overflow: visible
}
.reader-container {
margin: 0 !important;
justify-self: stretch !important;
}
.reader-component {
grid-template-columns: 1.5rem 1fr 1.5rem !important;
}
.reader-component a.button span {
width: 1.5rem !important;
}
body .reader-container .sentence-item {
color: #e0e0e0 !important;
}
.reader-component .reader-container {
line-height: 1.6 !important;
}
.reader-component article{
font-size: 1.05rem !important;
}
.reader-container p+p {
margin-top: 0.5rem;
}
`;
document.querySelector("head").appendChild(style);
// 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');
src = src + '&cc_load_policy=1'
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(() => {
document
.querySelector(
"div.collection-section--controllers > div.dropdown > div.dropdown-menu > div.dropdown-content > a.dropdown-item:nth-child(3)",
)
.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();
}
})();
@BassmasterJJ FYI
3 Likes
Well done!
Like the compressed line spacing but not a big fan of fixing the font size. Easy enough to comment out.
Add a new full-screen shortcut (F key) for YouTube player.
Now we don’t need to use a mouse to change full-screen mode.
// ==UserScript==
// @name LingQ Addon
// @match https://www.lingq.com/*/learn/*/web/reader/*
// @match https://www.lingq.com/*/learn/*/web/library
// @description Custom embedded player, and sort course automatically.
// ==/UserScript==
(function () {
"use strict";
// Restyle embedded player
var height = 370;
var width = 540;
var height_big = 650;
var width_big = 1100;
var right = 0.1;
var bottom = 13;
var style = document.createElement("style");
style.textContent = `
.video-player .video-wrapper,.sent-video-player .video-wrapper {
height: ${height_big}px;
overflow: hidden;
}
.modal.video-player .modal-content {
max-width: ${width_big}px;
margin-bottom: 0;
}
.video-player.is-minimized .video-wrapper,.sent-video-player.is-minimized .video-wrapper {
height: ${height}px;
width: ${width}px;
}
.video-player.is-minimized .modal-content,.sent-video-player.is-minimized .modal-content {
max-width: ${width}px;
margin-bottom: 0;
}
.video-player.is-minimized,.sent-video-player.is-minimized {
left: auto;
top: auto;
right: ${right}%;
bottom: ${bottom}%;
z-index: 99999999;
overflow: visible
}
.reader-container {
margin: 0 !important;
justify-self: stretch !important;
}
.reader-component {
grid-template-columns: 1.5rem 1fr 1.5rem !important;
}
.reader-component a.button span {
width: 1.5rem !important;
}
body .reader-container .sentence-item {
color: #e0e0e0 !important;
}
.reader-component .reader-container {
line-height: 1.6 !important;
}
.reader-component article{
font-size: 1.05rem !important;
}
.reader-container p+p {
margin-top: 0.5rem;
}
`;
document.querySelector("head").appendChild(style);
// Add video full creen shortcut (f key)
document.addEventListener('keydown', function(event) {
if (event.key === 'f' || event.key === 'F') {
const button = document.querySelector('.modal-section > div > button:nth-child(2)');
if (button) {
button.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');
src = src + '&cc_load_policy=1'
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(() => {
document
.querySelector(
"div.collection-section--controllers > div.dropdown > div.dropdown-menu > div.dropdown-content > a.dropdown-item:nth-child(3)",
)
.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();
}
})();
1 Like
Changed the full-screen shortcut to ‘x’ to avoid crashing with the built-in shortcut. And disabled the shortcut when typing.
// ==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.0
// ==/UserScript==
(function () {
"use strict";
// Restyle embedded player
var height = 370;
var width = 540;
var height_big = 650;
var width_big = 1100;
var right = 0.1;
var bottom = 13;
// video player size/location settings
var style = document.createElement("style");
style.textContent = `
.video-player .video-wrapper,.sent-video-player .video-wrapper {
height: ${height_big}px;
overflow: hidden;
}
.modal.video-player .modal-content {
max-width: ${width_big}px;
margin-bottom: 0;
}
.video-player.is-minimized .video-wrapper,.sent-video-player.is-minimized .video-wrapper {
height: ${height}px;
width: ${width}px;
}
.video-player.is-minimized .modal-content,.sent-video-player.is-minimized .modal-content {
max-width: ${width}px;
margin-bottom: 0;
}
.video-player.is-minimized,.sent-video-player.is-minimized {
left: auto;
top: auto;
right: ${right}%;
bottom: ${bottom}%;
z-index: 99999999;
overflow: visible
}
// make prev/next page buttons compact
.reader-container {
margin: 0 !important;
justify-self: stretch !important;
}
.reader-component {
grid-template-columns: 1.5rem 1fr 1.5rem !important;
}
.reader-component a.button span {
width: 1.5rem !important;
}
// font settings
body .reader-container .sentence-item {
color: #e0e0e0 !important;
}
.reader-component .reader-container {
line-height: 1.6 !important;
}
.reader-component article{
font-size: 1.05rem !important;
}
.reader-container p+p {
margin-top: 0.5rem;
}
`;
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(3)"
).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();
}
})();
1 Like
Without and with this addon
Fix some bugs on css selector
Modify some additional font-related options.
// ==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.2
// ==/UserScript==
(function () {
"use strict";
// Restyle embedded player
var height = 370;
var width = 540;
var height_big = 650;
var width_big = 1100;
var right = 0.5;
var bottom = 5.5;
// video player size/location settings
var style = document.createElement("style");
style.textContent = `
.video-player .video-wrapper,.sent-video-player .video-wrapper {
height: ${height_big}px;
overflow: hidden;
}
.modal.video-player .modal-content {
max-width: ${width_big}px;
margin-bottom: 0;
}
.video-player.is-minimized .video-wrapper,.sent-video-player.is-minimized .video-wrapper {
height: ${height}px;
width: ${width}px;
}
.video-player.is-minimized .modal-content,.sent-video-player.is-minimized .modal-content {
max-width: ${width}px;
margin-bottom: 0;
}
.video-player.is-minimized,.sent-video-player.is-minimized {
left: auto;
top: auto;
right: ${right}%;
bottom: ${bottom}%;
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: 1.6 !important;
padding 0 !important;
font-size: 1.1rem !important;
}
.reader-container p {
margin-top: 0 !important;
}
.reader-container p span.sentence-item {
color: #e0e0e0 !important;
}
.sentence.is-playing, .sentence.is-playing span {
text-underline-offset: .2em !important;
}
.phrase-item {
padding: 0 !important;
}
.reader-container .sentence .lingq-word:not(.is-learned) {
border: 1px solid hsl(41 43% 50% / 1) !important;
}
.reader-container .sentence .lingq-word.is-learned {
border: 1px solid hsl(41 43% 50% / 0.5) !important;
}
.phrase-cluster:not(:has(.phrase-item-status--4)) {
border: 1px solid hsl(41 43% 50% / 1) !important;
border-radius: .25rem;
}
.phrase-cluster:has(.phrase-item-status--4) {
border: 1px solid hsl(41 43% 50% / 0.5) !important;
border-radius: .25rem;
}
.phrase-cluster:hover,.phrase-created:hover {
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();
}
})();
3 Likes