NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name LingQ // @namespace http://tampermonkey.net/ // @version 0.3.8 // @description same site better UX // @author ibn_rushd // @match https://www.lingq.com/* // @license GPL-3.0-or-later; https://www.gnu.org/licenses/gpl-3.0.txt // @grant GM_addStyle // ==/UserScript== /* jshint esversion: 8 */ var version = "0.3.8"; GM_addStyle(` .bg-dark { background: #091a2f !important; } .dashboard-wrap-section { width: 1440px; margin: 0 auto; } .dashboard-wrap-section p { font-family: 'Roboto',sans-serif; font-size: 1em; line-height: 1.5rem; letter-spacing: 0.00625rem; font-weight: 400; overflow-wrap: break-word; color: white; margin-bottom: 40px; } .dashboard-wrap-section h1 { color: white } .languages tr:nth-child(even) { background: rgba(255,255,255,0.03); } table.languages { width: 100%; font-family: monospace; text-align: left; color: white; font-size: 20px; margin-top: 85px; } table.languages th { color: white; } .hero-head .navbar { background: #091a2f; } table.languages tr th:hover { cursor: pointer; } table.languages tr th:hover span { border-bottom: 2px solid white; } table.languages .tr .number { width: 90px; } table.languages .tr .name { width: 150px; } table.languages .tr .known { width: 130px; } table.languages .tr .streak { width: 140px; } table.languages .tr .mastery { width: 140px; } table.languages tr th, table.languages tr td { vertical-align: bottom; font-size: 1em; padding: 1.1rem .75rem; } .popup.achievement-popup .modal-dialog{ position: absolute; top: 0; display: inline-block; min-width: 100%; } .popup.achievement-popup .modal-dialog .modal-content { height: 100vh; top: -30px; margin: 0; padding: 0; border-radius: 0; } .achievement-popup .close { display: none; } ul.languages > li > a { width: 110px; display: inline-block; } .autopage-button { background: transparent; width: 32px; height: 32px; display: inline-block; outline: 0; border-radius: 50%; padding: 0; border: 1px solid #3184de; color: #3184de; font-size: 50px; line-height: 60px; margin-top: -1px; margin-left: 5px; } .autopage-button:hover, .autopage-button:focus, .autopage-button:active { background: #3184de; color: white; } .total-pages { margin-right: 20px; width: 70px; text-align: center; background: #2b60a3; color: white; font-size: 16px; } .lesson-card .widget-area { box-shadow: none; } .rc-slider { height: 10px !important; border-radius: 0; background: #64a9ff!important; top: 80px !important; } .rc-slider .rc-slider-track{ height: 10px !important; background: #fac138 !important; } .rc-slider .rc-slider-handle { border-color: #fac138 !important; background: #fac138 !important; height: 20px !important; width: 20px !important; } .lingq-audio-player.activated .play-button { top: 14px !important; left: 34px !important; } .lesson-completed { background: white !important; } .lesson-completed .lesson-head { top: 80px; } .lesson-card { background: transparent; box-shadow: none !important; } section.lesson-topbar { min-height: 84px !important; box-shadow: 0 4px 8px 0 rgba(0,0,0,.15); margin-bottom: 25px !important;; border-radius: 4px !important; } .app-nav-wrapper .app-nav .navbar-collapse .navbar-nav.import-menu-item { background: transparent; } .lingq-audio-player .time { top: 55px !important; font-size: 14px !important; left: 87px!important; } .lesson-card .lesson-content { border-radius: 4px; !important; padding-top: 15px; box-shadow: 0 4px 8px 0 rgba(0,0,0,.15); background: white; } .body-progress { background: white; height: 4px; position: absolute; z-index: 1; transition-duration: 2000ms; } .version { text-align: center; background: #7eb9ff; } .app-nav-wrapper .app-nav .container { width: 1200px !important; } .streak-in-top-nav:after { content: "\\E013"; order: 1; font-family: Glyphicons Halflings; border-radius: 50%; width: 21px; height: 21px; display: block; float: right; margin-left: 9px; font-size: 10px; padding: 0px 5px; background: #444444; } body #app { overflow-y: hidden !important; } #app, .app-nav { background: linear-gradient(120deg, #2b60a3 550px, #3584de 550px) !important; } .dashboard-top-stats { height: 100px; margin-bottom: 20px; color: white; margin-left: -60px; margin-right: -30px } .dashboard-top-stats li { height: 100px; display: block; width: calc(33% - 40px); float: left; margin: 20px; padding: 20px; background: #1f1f30; } .status-bar .status-0 { background: white !important; color: #444 !important; font-size: 16px !important; height: 42px; } .btn:focus.status-0, .status-0.active, .status-0:hover{ background: #e2de40 !important; } .btn:focus.status-5, .btn.status-5.active, .btn.status-5:hover{ background: #e24040 !important; } .display-total-words .label-bullet { border: 1px solid black; } .display-percentage-unknown .label-bullet { background: #ff5959; } .lessons-wrap .current-lesson { background: #f6f6f6; padding: 30px 10px !important; box-shadow: 0 5px 5px 0 #c3bfbf; margin: 0 0px 5px 0px; } .today-counter span { color: white; position: relative; height: 55px; line-height: 55px; z-index: 1; } .today-counter .btn_update { color: black; padding: 0 10px 0 10px; cursor: pointer; font-size: 25px; color: white; transform: rotate(154deg); transition: transform 800ms ease; } .btn_update:hover { transform: rotate(0deg); padding: 0 10px 0 10px; top: -1px; } .lessons-wrap { padding: 0px !important; } .lessons-wrap .lesson-item k padding: 10px !important; }` ); //BEFORE LOAD HAPPENS //11b (beta) show loading bar for webpage showLoadingBar(10); var base_url = "https://lingq.com"; var data = []; var topbar = document.querySelector('.counters.nav'); var lang = window.location.pathname.split('/')[3]; var api_url = "https://www.lingq.com/api/v2/"; var span_lingq; var span_mastery; var current_lesson_link; var total_linq_of_lesson; var supported_languages = [ "ar", "da", "de", "en", "es", "fr", "id", "ru", "tr" ]; var mastery_lessons = { ar: 690829, da: 836059, de: 836064, en: 854377, es: 836067, fr: 689806, id: 835925, ru: 690605, tr: 836056 }; var unique_words = { ar: 5001, da: 4999, de: 4988, en: 5329, es: 4994, fr: 4998, id: 4919, ru: 4963, tr: 4950 }; function setTotalLingqOfLesson() { console.log("setTotalLingqOfLesson()"); if (window.location.href.indexOf("lesson/") != -1) { var l = document.querySelector(".words-index").innerText.split("(")[1].split(")")[0]; total_linq_of_lesson = Number(l); } } function setContinueButtonInCourse() { console.log("setContinueButtonInCourse"); if (window.location.href.indexOf("course") != -1) { waitForElement(".action-list", function() { var action_list = document.querySelector(".action-list"); var li = document.createElement("li"); var a = document.createElement("a"); li.setAttribute('class','action-item continue'); a.innerHTML = "Continue with Lesson;"; a.addEventListener('click', function() { goToCurrentLesson();}); li.appendChild(a); action_list.appendChild(li); }); } } function showLoadingBar(number) { if (window.location.pathname !== "/en/") { console.log("showLoadingBar()"); if (!number) { setTimeout(function () { let progress = document.querySelector(".body-progress"); progress.remove(); }, 2000); return; } if (number === 10) { waitForElement("header nav", function () { var nav = document.querySelector("header nav"); var progress_loading = document.createElement("div"); progress_loading.classList.add("body-progress"); var nav_container = document.querySelector("#main-nav"); nav_container.insertBefore(progress_loading, nav); }); } waitForElement(".body-progress", function () { document.querySelector(".body-progress").style.width = number + "%"; }); } } function goToCurrentLesson() { window.location = base_url + current_lesson_link; } function setLingqDailies() { if (window.location.href.indexOf("learn") != -1) { var today_counter = document.createElement("li"); today_counter.setAttribute('class','today-counter counter-item'); var lingq_text = document.createElement("span"); lingq_text.setAttribute('class','lingq_text'); var btn_update = document.createElement("span"); btn_update.setAttribute('class','btn_update'); btn_update.innerHTML = "↺"; today_counter.appendChild(lingq_text); today_counter.appendChild(btn_update); topbar.appendChild(today_counter); span_lingq = document.querySelector('.today-counter.counter-item .lingq_text'); span_mastery = document.querySelector('.navbar-nav.counters .coin-counter .count'); btn_update = document.querySelector('.today-counter.counter-item .btn_update'); btn_update.addEventListener('click', function() { updateDailyLingq(); }, false); span_lingq.innerText = "?? Lingq's"; } } async function updateDailyLingq() { if (window.location.href.indexOf("learn") != -1) { showStreakInTopNav(); console.log("updateDailyLingq"); span_lingq.innerText = "Loading..."; var response = await fetch(api_url + lang + "/milestones/").then(response => response.json()); span_lingq.innerText = response.stats.lingqs_daily + "/" + LINGQ_SETTINGS.dailyLingqsGoal + " Lingq's"; } } function continueWithLastLessonInCourse() { console.log("connectTriggersToBlueWords"); if (window.location.href.indexOf("course") != -1) { waitForElement(".lessons-wrap .lesson-list", function() { var lessons = document.querySelector('.lessons-wrap .lesson-list'); var lessons_items = document.querySelector('.lessons-wrap .lesson-list .lesson-item'); var total_completed = document.querySelectorAll('.completed').length; var current_lesson = lessons.childNodes[total_completed]; lessons.insertBefore(current_lesson, lessons.firstChild); lessons.firstChild.classList.add("current-lesson"); current_lesson_link = document.querySelector(".current-lesson a").getAttribute("href"); }); } } function logoLinksToDashboard() { if (window.location.href.indexOf("learn") != -1) { document.querySelector(".navbar-brand").setAttribute("href", "/en"); } } async function getLanguages(filter, lang) { response = await fetch(api_url + "languages/").then(response => response.json()); if (filter === "active") { var result = []; response.forEach(function (item) { if (item.knownWords > 0) { result.push([item.title, item.knownWords, item.code]); } }); return result.sort(); } if (filter === "last_week") { response = await fetch(api_url + lang + "/progress/?interval=last_week").then(response => response.json()); document.querySelector(".languages ." + lang + " .today").innerHTML= "(" + response.knownWords + ")"; } return response; } async function getRecentLesson(lang) { let response = await fetch(api_url + lang + "/lessons/recent/?page_size=1"); let result = await response.json(); result = result.results[0]; let id = result.contentId; let lesson_url = base_url + "/en/learn/" + lang + "/web/lesson/" + id; let title = result.collectionTitle; ret = [title, lesson_url]; return ret; } function sortTable(n) { var table, rows, switching, i, x, y, shouldSwitch, dir, switchcount = 0; table = document.getElementById("languages"); switching = true; // Set the sorting direction to ascending: dir = "asc"; /* Make a loop that will continue until no switching has been done: */ while (switching) { // Start by saying: no switching is done: switching = false; rows = table.rows; /* Loop through all table rows (except the first, which contains table headers): */ for (i = 1; i < (rows.length - 1); i++) { // Start by saying there should be no switching: shouldSwitch = false; /* Get the two elements you want to compare, one from current row and one from the next: */ x = rows[i].getElementsByTagName("TD")[n]; y = rows[i + 1].getElementsByTagName("TD")[n]; var x_value; var y_value; if(isNaN(parseFloat(x.innerHTML))){ x_value = x.innerHTML.toLowerCase(); } else { x_value = parseFloat(x.innerHTML); } if(isNaN(parseFloat(y.innerHTML))){ y_value = y.innerHTML.toLowerCase(); } else { y_value = parseFloat(y.innerHTML); } if (dir == "asc") { if (x_value > y_value) { // If so, mark as a switch and break the loop: shouldSwitch = true; break; } } else if (dir == "desc") { if (x_value < y_value) { // If so, mark as a switch and break the loop: shouldSwitch = true; break; } } } if (shouldSwitch) { /* If a switch has been marked, make the switch and mark that a switch has been done: */ rows[i].parentNode.insertBefore(rows[i + 1], rows[i]); switching = true; // Each time a switch is done, increase this count by 1: switchcount ++; } else { /* If no switching has been done AND the direction is "asc", set the direction to "desc" and run the while loop again. */ if (switchcount == 0 && dir == "asc") { dir = "desc"; switching = true; } } } } function setUpDashboard() { console.log("setUpDashboard"); if (window.location.pathname === "/en/") { document.querySelector(".hero-body").remove(); document.querySelector(".hero-foot").remove(); document.querySelector(".section-library").remove(); document.querySelector(".section-providers").remove(); document.querySelector(".section-features").remove(); document.querySelector(".section-cta").remove(); document.querySelector(".section-steve").remove(); document.querySelector(".section-community").remove(); document.querySelector(".section-testimonials").remove(); document.querySelector(".section-featured").remove(); document.querySelector(".section-devices").remove(); document.querySelector("section").classList.remove("hero"); document.querySelector("section").classList.remove("is-black"); document.querySelector("section").classList.add("dashboard-wrap-section"); document.querySelector("section").classList.add("bg-dark"); document.querySelector("body").classList.add("bg-dark"); document.querySelector("head title").innerText = "Dashboard - LingQ Learning Languages Simply"; //active languages getLanguages("active").then( languages => { var list = document.createElement("table"); list.classList.add("languages"); list.setAttribute("id", "languages"); var tr = document.createElement("tr"); var th = document.createElement("th"); th.innerHTML = "<span>#</span>" th.addEventListener("click", () => sortTable(0)); tr.appendChild(th); var th = document.createElement("th"); th.innerHTML = "<span>Language</span>" th.addEventListener("click", () => sortTable(1)); tr.appendChild(th); var th = document.createElement("th"); th.innerHTML = "<span>Known</span>" th.addEventListener("click", () => sortTable(2)); tr.appendChild(th); var th = document.createElement("th"); th.innerHTML = "<span>Streak</span>" th.addEventListener("click", () => sortTable(3)); tr.appendChild(th); var th = document.createElement("th"); th.innerHTML = "<span>Mastery</span>" th.addEventListener("click", () => sortTable(4)); tr.appendChild(th); var th = document.createElement("th"); th.innerHTML = "<span>Lesson</span>" th.addEventListener("click", () => sortTable(5)); tr.appendChild(th); list.appendChild(tr); console.log(languages); languages.forEach(function (item, index) { var tr = document.createElement("tr"); tr.classList.add(item[2]); var td = document.createElement("td"); td.classList.add("rank"); td.innerText = index + 1; tr.appendChild(td); var td = document.createElement("td"); td.innerHTML = "<a href='/en/learn/" + item[2] + "/web/'>" + item[0] + "</a>" ; td.classList.add("name"); tr.appendChild(td); td = document.createElement("td"); td.classList.add("known"); td.innerText = item[1]; tr.appendChild(td); td = document.createElement("td"); td.classList.add("streak"); tr.appendChild(td); td = document.createElement("td"); td.classList.add("mastery"); tr.appendChild(td); td = document.createElement("td"); td.classList.add("lesson"); tr.appendChild(td); list.appendChild(tr); }); document.querySelector("section").appendChild(list); }); //streak getLanguages("active").then( languages => { languages.forEach(function (item) { langIsOnStreak(item[2]).then(function(result) { td = document.querySelector(".languages ." + item[2] + " .streak"); console.log("streak" + result + item[2]) if (result) { td.innerHTML = "streak"; } else { td.innerHTML = "no"; } }); }); }); //mastery getLanguages("active").then( languages => { languages.forEach((item) => { console.log("dave"); getPercentageOfMastery(item[2]).then( percent => { document.querySelector(".languages ." + item[2] + " .mastery").innerHTML = percent.toFixed(2) + "%"; }); }); }); //recent lesson getLanguages("active").then( languages => { languages.forEach(function (item) { getRecentLesson(item[2]).then( recent => { a = document.createElement("a"); a.innerText = recent[0]; a.setAttribute('href', recent[1]); document.querySelector(".languages ." + item[2] + " .lesson").appendChild(a); }); }); }); } } function disableReviewPage() { if (window.location.href.indexOf("review") != -1) { window.location = base_url + "/learn/" + lang + "/web"; } } function waitForElement(id, callback){ var poops = setInterval(function(){ if(document.querySelector(id)){ clearInterval(poops); callback(); } }, 100); } function waitForValue(callback){ var poops = setInterval(function(){ if(document.querySelectorAll(".display-lingqs")[1].getAttribute("title").split(" ")[0] !== "0"){ clearInterval(poops); callback(); } }, 100); } function addGlyph() { var dislike = document.querySelector(".status-bar .status-0"); if (document.querySelector(".status-4").classList.contains("active") || document.querySelector(".status-5").classList.contains("active")) { dislike.className = "status-0 btn btn-default glyphicon glyphicon-link"; } else { dislike.className = "status-0 btn btn-default active glyphicon glyphicon-link"; } dislike.innerHTML = ""; } function likeDislikeLingq() { if (window.location.href.indexOf("lesson/") != -1) { console.log("likeDislikeLingq()"); waitForElement(".status-1", function() { if (document.querySelector(".status-bar .status-1")) { document.querySelector(".status-bar .status-1").remove(); document.querySelector(".status-bar .status-2").remove(); document.querySelector(".status-bar .status-3").remove(); } //TODO: this should be coded in a better way addGlyph(); document.querySelector(".status-bar .status-0") .addEventListener('click', function () { addGlyph(); }); document.querySelector(".status-bar .status-4") .addEventListener('click', function () { addGlyph(); }); }); } } function checkIfLingqTotalChanged() { console.log("checkIfLingqTotalChanged()"); let current_total_lingq_of_lesson = Number(document.querySelector(".words-index").innerText.split("(")[1].split(")")[0]); if (Number(total_linq_of_lesson) != current_total_lingq_of_lesson) { total_linq_of_lesson = current_total_lingq_of_lesson; updateDailyLingq(); } } function whenWordIsClikedDo() { if (window.location.href.indexOf("lesson/") != -1) { console.log("whenWordIsClikedDo()"); waitForElement(".card-widget", function () { if(document.querySelectorAll(".yellow-wrap").length === 1) { likeDislikeLingq(); } var card_widget = document.querySelector(".widget-area"); var observer = new MutationObserver(function() { console.log("something got clicked"); likeDislikeLingq(); checkIfLingqTotalChanged(); refreshPageNumber(); cleanUpSentences(); }); observer.observe(card_widget, {subtree: true, childList: true}); }); } } function addProfileLinkInTopNav() { if (window.location.href.indexOf("learn") != -1) { var li = document.createElement("li"); li.innerHTML = '<a class="profile" href="/en/learn/' + lang + '/web/profile">Profile</a>'; var left_nav = document.querySelector(".left-nav"); left_nav.appendChild(li); } if (window.location.href.indexOf("profile") != -1) { document.querySelector(".left-nav").classList.remove("community"); document.querySelector(".left-nav .profile").style.border = "1px solid"; } } async function langIsOnStreak(lang) { response = await fetch(api_url + lang + "/progress/?interval=today").then(response => response.json()); goal = Number.parseInt(response.cardsCreatedGoal, 10); created = Number.parseInt(response.cardsCreated, 10); if (goal <= created) { return true; } return false; } async function showStreakInTopNav() { console.log("showStreakInTopNav()"); if (window.location.href.indexOf("learn") != -1) { if (await langIsOnStreak(lang)) { document.querySelector(".streak-counter .count").classList.add("streak-in-top-nav"); } } } function removeRightPane() { var known_words = document.querySelector('.known-words.counter'); if (known_words) { known_words.remove(); document.querySelector('.header-title').remove(); document.querySelector('.dailygoal-section').remove(); document.querySelector('.challenges-tab').remove(); } } function addFooter() { console.log("addFooter"); } function addSortByInCourses() { if (window.location.href.indexOf("course") != -1) { waitForElement(".footer .extra-info", function() { var list = document.querySelector(".footer .extra-info"); var article = document.createElement("article"); var select = document.createElement("select"); select.addEventListener("change", () => sortCourse()); var p = document.createElement("p"); var option = document.createElement("option"); option.innerText = "Default"; option.setAttribute("value", "Default"); option.setAttribute("selected", "selected"); var option2 = document.createElement("option"); option2.innerText = "Alphabetical"; option2.setAttribute("value", "Alphabetical"); var option3 = document.createElement("option"); option3.innerText = "Lingq"; option3.setAttribute("value", "Lingq"); var option4 = document.createElement("option"); option4.innerText = "Likes"; option4.setAttribute("value", "Likes"); var option5 = document.createElement("option"); option5.innerText = "Unknown words"; option5.setAttribute("value", "Unknown words"); var option6 = document.createElement("option"); option6.innerText = "Duration"; option6.setAttribute("value", "Duration"); var option7 = document.createElement("option"); option7.innerText = "Total words"; option7.setAttribute("value", "Total words"); select.appendChild(option); select.appendChild(option2); select.appendChild(option3); select.appendChild(option4); select.appendChild(option5); select.appendChild(option6); select.appendChild(option7); article.classList.add("extra-info-item"); article.innerHTML = "<p>Sort by: </p>"; article.firstChild.appendChild(select); list.insertBefore(article, list.firstChild); }); } } function addMoreCourseInfo() { if (window.location.href.indexOf("course") != -1) { console.log("addMoreCourseInfo"); var show_duration = false; waitForElement(".lesson-item .quick-stats", function () { waitForValue(function (){ document.querySelectorAll(".lesson-item .quick-stats").forEach(function (item) { if (item.parentNode.parentNode.querySelector(".lesson-length").children.length === 3) { //var duration = item.parentNode.parentNode.querySelector(".lesson-length span").children[1].innerText; //var stat_duration = document.createElement("span"); //stat_duration.classList.add("quick-stat-item"); //stat_duration.classList.add("display-duration"); //stat_duration.innerHTML = '<img class="label-bullet" src="/static/webapp/images/icons/head-set-icon.svg">' + duration; var length = item.parentNode.parentNode.querySelectorAll(".lesson-length span")[3].innerText; length = length.split(": ")[1]; var stat_total_words = document.createElement("span"); stat_total_words.classList.add("quick-stat-item"); stat_total_words.classList.add("display-total-words"); stat_total_words.innerHTML = '<span class="label-bullet"></span>' + length; } else { var length = item.parentNode.parentNode.querySelector(".lesson-length").innerText.split(":")[2] var stat_total_words = document.createElement("span"); stat_total_words.classList.add("quick-stat-item"); stat_total_words.classList.add("display-total-words"); stat_total_words.innerHTML = '<span class="label-bullet"></span>' + length; } var blue_words = item.querySelector(".display-bluewords").innerText.split("(")[0]; var yellow_words = item.querySelector(".display-lingqs").getAttribute("title").split(" ")[0]; if (yellow_words === "0") { } var percentage_unknown = (Number(blue_words) + Number(yellow_words)) / length * 100; console.log(yellow_words) console.log(blue_words) console.log("length:" + length); console.log("percentage:" + percentage_unknown) var stat_percentage_unknown = document.createElement("span"); stat_percentage_unknown.classList.add("quick-stat-item"); stat_percentage_unknown.classList.add("display-percentage-unknown"); stat_percentage_unknown.innerHTML = '<span class="label-bullet"></span><b>' + percentage_unknown.toFixed(2) + "%</b>"; if (show_duration) { item.append(stat_duration); } item.append(stat_total_words); item.append(stat_percentage_unknown); }); }); }); } } function sortCourse() { var list = []; var counter = 0; var schedule = []; var flip = false; let select = document.querySelector(".footer .extra-info select"); if (select.value === "Default") { // QUICK FIX window.location.reload(false); } if (select.value === "Alphabetical") { flip = true; console.log("sort by: Alphabetical"); list = []; counter = 0; document.querySelectorAll("section .lesson-title h3.title").forEach(function (item) { var temp = [counter, item.innerText]; list.push(temp); counter++; }); console.log("list"); console.log(list); schedule = []; schedule = list.sort(function (a, b) { return (a[1].toLowerCase() < b[1].toLowerCase()) ? -1 : 1; }); console.log("alpha_list"); console.log(schedule); } if (select.value === "Lingq") { flip = true; console.log("sort by: Lingq"); list = []; counter = 0; document.querySelectorAll("section .lesson-item .display-lingqs").forEach(function (item) { var temp = [counter, item.innerText]; list.push(temp); counter++; }); console.log("list"); console.log(list); schedule = []; schedule = list.sort(function (a, b) { return (parseInt(a[1]) < parseInt(b[1])) ? -1 : 1; }); scedule = schedule.reverse(); console.log("lingq_list"); console.log(schedule); } if (select.value === "Likes") { flip = false; console.log("sort by: Likes"); list = []; counter = 0; document.querySelectorAll("section .lesson-item .display-rose").forEach(function (item) { var temp = [counter, item.innerText]; list.push(temp); counter++; }); console.log("list"); console.log(list); schedule = []; schedule = list.sort(function (a, b) { return (parseInt(a[1]) < parseInt(b[1])) ? -1 : 1; }); console.log("likes_list"); console.log(schedule); } if (select.value === "Unknown words") { console.log("sort by: Unknown words"); flip = false; list = []; counter = 0; document.querySelectorAll("section .lesson-item .display-bluewords").forEach(function (item) { var temp = [counter, item.innerText.split("(")[0]]; list.push(temp); counter++; }); console.log("list"); console.log(list); schedule = []; schedule = list.sort(function (a, b) { return (parseInt(a[1]) < parseInt(b[1])) ? -1 : 1; }); console.log("unknown_words_list"); console.log(schedule); } if (select.value === "Duration") { console.log("sort by: Duration"); flip = false; list = []; counter = 0; document.querySelectorAll(".display-duration").forEach(function (item) { var minutes = parseInt(item.innerText.split(":")[0], 10); console.log(counter + "minutes: " + minutes); var seconds = parseInt(item.innerText.split(":")[1].split("m")[0], 10); console.log(counter + "seconds: " + seconds); var time = parseInt((parseInt(minutes, 10)*60) + parseInt(seconds, 10), 10); console.log(counter + "time: " + time); var temp = [counter, time]; list.push(temp); counter++; }); console.log("list"); console.log(list); schedule = []; schedule = list.sort(function (a, b) { return (parseInt(a[1]) < parseInt(b[1])) ? -1 : 1; }); console.log("duration_list"); console.log(schedule); } if (select.value === "Total words") { flip = false; console.log("sort by: Total words"); list = []; counter = 0; document.querySelectorAll(".display-total-words").forEach(function (item) { var temp = [counter, item.innerText]; list.push(temp); counter++; }); console.log("list"); console.log(list); schedule = []; schedule = list.sort(function (a, b) { return (parseInt(a[1]) < parseInt(b[1])) ? -1 : 1; }); console.log("total_words_list"); console.log(schedule); } hussle(getScheduleFrom(schedule), flip); } function getScheduleFrom(list) { let result = []; list.forEach(function (item) { result.push(item[0]); }); return result; } function hussle(schedule, flip) { var lessons = document.querySelector('.lessons-wrap .lesson-list'); var list = []; schedule.forEach(function (position) { list.push(lessons.childNodes[position]); }); if (flip) { list.reverse(); } list.forEach(function (item) { lessons.insertBefore(item, lessons.firstChild); }); } function recentlyTab() { var correct_page = false; var urls = ["feed", "my-lessons", "vocabulary", "playlist"]; urls.forEach(function(item) { if (window.location.href.indexOf(item) != -1) { correct_page = true; } }); if (correct_page) { var global_tabs = document.querySelector(".main-section .nav-tabs"); var li = document.createElement("li"); li.innerHTML = "<a>Recently</a>"; global_tabs.insertBefore(li, global_tabs.firstChild); } } function addVersionInPage() { var div_version = document.createElement("div"); div_version.classList.add("version"); div_version.innerText = version; if (window.location.pathname === "/en/") { waitForElement("#languages", function() { document.querySelector("#languages").append(div_version); }) } else { document.querySelector("#app").append(div_version); } } function getCurrentSegment(segments) { for (var i = 0; i < segments.length; i++) { if(segments[i].classList.contains("current")) { return i + 1; } } } function addPageNumber() { console.log("addPageNumber()"); if (window.location.href.indexOf("lesson/") != -1) { var div_total_pages = document.createElement("div"); div_total_pages.classList.add("total-pages"); text_mode_toggle = document.querySelector(".text-mode-toggle"); waitForElement(".text-mode-toggle", function() { waitForElement(".current", function() { div_total_pages.innerText = "Page: ?/?"; text_mode_toggle.parentElement.insertBefore(div_total_pages, text_mode_toggle); refreshPageNumber(); }); }); } } function getSentenceMode(button) { console.log("getSentenceMode()"); if (button) { var sentece_mode = button.path[0].classList[0]; if (sentece_mode === "sentence-size") { return true; } } return false; } function refreshPageNumber(button) { console.log("refreshPageNumber()"); var sentence_mode = getSentenceMode(button); console.log("sentence_mode" + sentence_mode); waitForElement(".total-pages", function () { var segments = document.querySelectorAll(".segment"); var position = getCurrentSegment(segments); var total_pages = document.querySelector(".total-pages"); total_pages.innerText = position + " of " + segments.length; }); } function eventListenerForTextMode() { waitForElement(".text-mode-toggle", function () { text_mode_toggle = document.querySelector(".text-mode-toggle"); text_mode_toggle.addEventListener('click', function(item) { refreshPageNumber(item); } ); }); } function nextLesson() { console.log("nextLesson()"); waitForElement(".sentence-item", function () { location.reload(); }); } function eventListenerForNextLesson() { waitForElement(".next-lesson .btn", function () { next_lesson = document.querySelector(".next-lesson .btn"); next_lesson.addEventListener('click', function() { nextLesson(); } ); }); } function eventListenerForUpArrow() { if (window.location.href.indexOf("lesson/") != -1) { console.log("eventListenerForUpArrow()"); document.onkeydown = function(e) { switch (e.key) { case 'ArrowUp': console.log('translate'); document.querySelector(".loadedContent > .btn").click(); if (document.querySelectorAll(".lingq-word").length > 0) { document.querySelectorAll(".lingq-word")[0].click() } else { if (document.querySelectorAll(".blue-word").length > 0) { document.querySelectorAll(".blue-word")[0].click() } } break; case '/': console.log('known word'); //TODO: when clicking a dot in all 3 situations it makes the word known } }; } } function cleanUpSentences() { if (window.location.href.indexOf("lesson/") != -1) { console.log("cleanUpSentences()"); var clean_up = true; var final_punctuation = []; var span; waitForElement(".sentence-text .loadedContent", function() { var max_sections = document.querySelector(".sentence-text .loadedContent .sentence-tts-wrap p").childElementCount; for (let i = 0; i < max_sections; i++) { var max_sentences = document.querySelector(".sentence-text .loadedContent .sentence-tts-wrap p").childNodes[i].childElementCount; var punctuation = []; for (let j = 0; j < max_sentences; j++) { //find a punctuation span = document.querySelector(".sentence-text .loadedContent .sentence-tts-wrap p").childNodes[i].childNodes[j]; if (span.getAttribute("class") === "sentence-item punctuation") { punctuation.push(j); } } if (clean_up) { console.log("cleanUpSentences()"); document.querySelector(".sentence-text .loadedContent .sentence-tts-wrap p").childNodes[i].style.visibility = "visible"; } final_punctuation.push(punctuation); punctuation = []; } for (let i = 0; i < final_punctuation; i++) { document.querySelector(".sentence-text .loadedContent .sentence-tts-wrap p").childNodes[i].childNodes[j] } }); } } async function showPercentageOfMastery() { console.log("showPercentageOfMaster"); if (supported_languages.includes(lang)) { mastery_id = mastery_lessons[lang]; var response = await fetch("https://www.lingq.com/api/v3/" + lang + "/collections/counters/?collection=" + mastery_id).then(response => response.json()); var response = Object.entries(response); var newWordsCount = Number(response[0][1]["newWordsCount"]); var uniqueWordCount = unique_words[lang]; var yellowCount = Number(response[0][1]["cardsCount"]) var total = (1 - (newWordsCount + yellowCount) / uniqueWordCount) * 100; span_mastery.innerText = total.toFixed(2) + "%"; } else { span_mastery.innerText = "lang unknown %"; } } async function getPercentageOfMastery(lang) { mastery_id = mastery_lessons[lang]; var response = await fetch("https://www.lingq.com/api/v3/" + lang + "/collections/counters/?collection=" + mastery_id).then(response => response.json()); console.log(response); var response = Object.entries(response); var newWordsCount = Number(response[0][1]["newWordsCount"]); var uniqueWordCount = unique_words[lang]; var yellowCount = Number(response[0][1]["cardsCount"]) console.log("newWordsCount: " + newWordsCount) console.log("uniqueWordCount: " + uniqueWordCount) console.log("yellowCount: " + yellowCount) return total = (1 - (newWordsCount + yellowCount) / uniqueWordCount) * 100; } function open_links() { supported_languages.forEach(function(item) { getRecentLesson(item).then((result) => { console.log(result); var lesson = result[1] window.open(lesson); }); }) } function setUpOpenAllLanguagesLinkInDashboard() { if (window.location.pathname === "/en/") { var a = document.createElement("a"); // Create a <button> element a.innerHTML = "Open All"; a.style.top = "79px"; a.style.fontSize = "30px"; a.style.position = "relative"; a.addEventListener ("click", open_links, false); document.querySelector("section").appendChild(a); } } function removeWhiteSentences() { if (window.location.href.indexOf("lesson") !== -1) { waitForElement(".sentence-tts-wrap p", function() { document.querySelectorAll(".sentence-tts-wrap p").forEach((item) => { console.log(item); if (item.innerHTML.search("lingq-word") !== -1 && item.innerHTML.search("blue-word") !== -1 ) { item.style.display = "none"; } }); }); } } //01. (alpha) never allow the review page redirect to lessons disableReviewPage(); //05b. (beta) page /dashboard has some info about all languages you are learning setUpDashboard(); showLoadingBar(20); addEventListener('load', function () { //02a. (beta) add total lingq in top bar //02b. (beta) update btn for daily lingq //02c. (beta) update daily lingq when loaded. //02d. (beta) total lingq of lesson. setLingqDailies(); updateDailyLingq(); setTotalLingqOfLesson(); showLoadingBar(30); //03. (beta) make sure the last course you did before completing is the first one in the course list. continueWithLastLessonInCourse(); showLoadingBar(40); //04. (beta) continue button in course setContinueButtonInCourse(); //05a. (beta) lingq logo links to /dashboard logoLinksToDashboard(); //06 (alpha) like dislike instead of 5 points whenWordIsClikedDo(); //07 (beta) add profile links addProfileLinkInTopNav(); showLoadingBar(50); //08 (beta) show streak in topnav showStreakInTopNav(); showLoadingBar(60); //09 (beta) add duration and listening length addMoreCourseInfo(); //10. (beta) sort by in courses addSortByInCourses(); showLoadingBar(70); //11 (alpha) add version to page addVersionInPage(); //12 (alpha) add which page you are on in numbers addPageNumber(); eventListenerForTextMode(); eventListenerForNextLesson(); showLoadingBar(80); //13 (alpha) go to one pane parallex style removeRightPane(); //14 (alpha) up arrow is translate eventListenerForUpArrow(); //15 (beta) show loading bar for webpage showLoadingBar(90); //16 (alpha) show percentage of top 5000 words. if (window.location.pathname !== "/en/") { showPercentageOfMastery(); } //17 (alpha) clean up sentences without lingqs cleanUpSentences(); showLoadingBar(100); showLoadingBar(false); // 18 (alpha) button to open all languages in new tabs setUpOpenAllLanguagesLinkInDashboard(); //??. (delayed) having a footer (with social media buttons) //addFooter(); // 19 (alpha) remove sentences that are white //removeWhiteSentences(); });