Udemy Course Progress JS Bookmarklet
The Udemy video course UI doesn’t give you a lot of information about your progress through a course. I find it helpful to be able to see progress and the amount of time remaining in a course, so I made this JavaScript bookmarklet to display some figures about progress through a Udemy course.
You need to be on the Udemy video player page when you trigger the bookmarklet. It will display progress stats in a browser alert.
javascript:(async () => {
const panelButtonsToClose = [];
document.querySelectorAll("button[class*='accordion-panel-module--panel-toggler'][aria-expanded='false']").forEach(button => {
button.click();
panelButtonsToClose.push(button);
});
let playbackRate = 1.0;
const playBackspan = document.querySelector("span[class^='ud-focus-visible-target playback-rate--trigger-text']");
if (playBackspan && playBackspan.innerText) {
playbackRate = parseFloat(playBackspan.innerText.replace(/[^0-9\.]/g, ""));
}
let completedMinutes = 0;
let uncompleteMinutes = 0;
document.querySelectorAll("li[class^='curriculum-item-link--curriculum-item']").forEach(item => {
const itemTitleMatch = item.innerText.match(/\n[0-9]+\. .+\n/);
if (itemTitleMatch) {
console.log(itemTitleMatch[0].trim());
}
let itemMinutes = 0;
const itemMinutesMatch = item.innerText.match(/([0-9]{1,2})min/);
if (itemMinutesMatch && itemMinutesMatch.length >= 2) {
itemMinutes = Number(itemMinutesMatch[1]);
}
let itemHours = 0;
const itemHoursMatch = item.innerText.match(/([0-9]{1})hr/);
if (itemHoursMatch && itemHoursMatch.length >= 2) {
itemHours = Number(itemHoursMatch[1]);
}
const itemTotalMinutes = (itemHours * 60) + itemMinutes;
if (item.innerText.includes("Lecture completed")) {
completedMinutes += itemTotalMinutes;
} else {
uncompleteMinutes += itemTotalMinutes;
}
});
const minutesToHoursAndMinutes = minutes => {
minutes = Math.ceil(minutes);
const wholeHours = Math.floor(minutes / 60);
const remainderMinutes = minutes % 60;
if (wholeHours < 1) {
return `${remainderMinutes} min`;
}
if (remainderMinutes === 0) {
return `${wholeHours} hr`;
}
return `${wholeHours} hr ${remainderMinutes} min`;
};
const courseTotalMinutes = completedMinutes + uncompleteMinutes;
const onePercentCourseTime = minutesToHoursAndMinutes(courseTotalMinutes*0.01);
const completion = Math.round((completedMinutes/(courseTotalMinutes))*100);
const summary = `
${minutesToHoursAndMinutes(courseTotalMinutes)} course total.\n
${completion}% complete.\n
${minutesToHoursAndMinutes(completedMinutes)} completed.\n
${minutesToHoursAndMinutes(uncompleteMinutes)} to go.\n
${playbackRate} playback rate.\n
1% = ${minutesToHoursAndMinutes(courseTotalMinutes*0.01)} course time, ${minutesToHoursAndMinutes((courseTotalMinutes*0.01)/playbackRate)} real time.\n
${[7,5,4,3,2].map(days => `With ${days} days, need ${minutesToHoursAndMinutes((uncompleteMinutes/playbackRate)/days)} real time / day.`).join("\n")}
`;
console.log(summary);
panelButtonsToClose.forEach(button => button.click());
await window.navigator.clipboard.writeText(summary);
window.alert(summary);
})();