Udemy Progress Control

The script can automatically check or uncheck off completed lessons of courses or sections, saving users time and effort in manually marking them as completed.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey, Greasemonkey или Violentmonkey.

Для установки этого скрипта вам необходимо установить расширение, такое как Tampermonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Violentmonkey.

Чтобы установить этот скрипт, вы сначала должны установить расширение браузера, например Tampermonkey или Userscripts.

Чтобы установить этот скрипт, сначала вы должны установить расширение браузера, например Tampermonkey.

Чтобы установить этот скрипт, вы должны установить расширение — менеджер скриптов.

(у меня уже есть менеджер скриптов, дайте мне установить скрипт!)

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение браузера, например Stylus.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

Чтобы установить этот стиль, сначала вы должны установить расширение — менеджер стилей.

(у меня уже есть менеджер стилей, дайте мне установить скрипт!)

// ==UserScript==
// @name         Udemy Progress Control
// @namespace    http://tampermonkey.net/
// @version      0.1
// @description  The script can automatically check or uncheck off completed lessons of courses or sections, saving users time and effort in manually marking them as completed.
// @author       realzam
// @match        https://www.udemy.com/course/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=udemy.com
// @grant        none
// @license MIT
// ==/UserScript==


function awaitToElement(element){
    return new Promise((resolve) => {
        let nIntervId = setInterval(()=>{
            const isReady=document.querySelectorAll(element).length != 0
            if(isReady){
                resolve()
                clearInterval(nIntervId)
            }
        },100)
        });
}

function seccionCollapse(seccion,action){
    return new Promise(async(resolve) => {
        const seccionButtonCollapse =seccion.querySelector('button[type="button"]')
        const isChecked = seccion.querySelector('span[data-checked]').getAttribute('data-checked') === 'checked'
        console.log(seccion.getAttribute('data-purpose'),isChecked)
        if(isChecked!=action){
            seccionButtonCollapse.click()
            if(action){
                await awaitToElement('ul.ud-unstyled-list')
            }
        }
        resolve()
    });
}

const isPageLoaded = async()=> awaitToElement('div[data-purpose="curriculum-section-container"]')

async function actioSeccion(seccion,action){
    await seccionCollapse(seccion,true)
    const leccions=seccion.childNodes[2].childNodes[0].childNodes[0].childNodes
    for(const leccion of leccions)
    {
        if(leccion.querySelector('input').checked !=action)
        {
            leccion.querySelector('input').click()
        }
    }
    await seccionCollapse(seccion,false)

}

async function actionCourse(seccions,action){
    for(const seccion of seccions)
    {
        await actioSeccion(seccion,action)
    }
}


async function main() {
    await isPageLoaded();
    const seccions = document.querySelector('#ct-sidebar-scroll-container > div > div').childNodes;
    const courseActions = document.querySelector('section[data-purpose="sidebar"]').childNodes[0];

    let completeAllCourseBtn = document.createElement("div");
    completeAllCourseBtn.tabIndex=0
    completeAllCourseBtn.role="button"
    completeAllCourseBtn.className = "item-link ud-btn ud-btn-small ud-btn-primary ud-heading-sm";
    completeAllCourseBtn.innerHTML ='<span>Complete</span>'
    completeAllCourseBtn.onclick = ()=>{actionCourse(seccions,true)};

    let resetCourseBtn = document.createElement("div");
    resetCourseBtn.tabIndex=0
    resetCourseBtn.role="button"
    resetCourseBtn.className = "item-link ud-btn ud-btn-small ud-btn-secondary ud-heading-sm";
    resetCourseBtn.innerHTML ='<span>Reset</span>'
    resetCourseBtn.onclick = ()=>{actionCourse(seccions,false)};

    courseActions.appendChild(completeAllCourseBtn)
    courseActions.appendChild(resetCourseBtn)

    for(const seccion of seccions)
    {
        let checkAllSeccionnBtn = document.createElement("div");
        checkAllSeccionnBtn.tabIndex=0
        checkAllSeccionnBtn.role="button"
        checkAllSeccionnBtn.className = "item-link ud-btn ud-btn-small ud-btn-primary ud-heading-sm";
        checkAllSeccionnBtn.innerHTML ='<span>Check All</span>'
        checkAllSeccionnBtn.style.margin='5px'
        checkAllSeccionnBtn.onclick = ()=>{actioSeccion(seccion,true)}

        let uncheckAllSeccionnBtn = document.createElement("div");
        uncheckAllSeccionnBtn.tabIndex=0
        uncheckAllSeccionnBtn.role="button"
        uncheckAllSeccionnBtn.className = "item-link ud-btn ud-btn-small ud-btn-secondary ud-heading-sm";
        uncheckAllSeccionnBtn.innerHTML ='<span>Uncheck All</span';
        uncheckAllSeccionnBtn.style.margin='5px'
        uncheckAllSeccionnBtn.onclick = ()=>{actioSeccion(seccion,false)};

        seccion.appendChild(checkAllSeccionnBtn)
        seccion.appendChild(uncheckAllSeccionnBtn)
    }

}

main()