-
-
Save jithurjacob/4af5e9e8d231d79f17f6e553ba166864 to your computer and use it in GitHub Desktop.
//credits - https://greasyfork.org/en/scripts/28295-udemy-show-section-time | |
// greasyfonrk was throwing me an error so I created this gist | |
(function() { | |
$.getScript("https://greasyfork.org/scripts/5392-waitforkeyelements/code/WaitForKeyElements.js?version=115012", function(){ | |
// waits for the cards to be loaded | |
waitForKeyElements(selectors.sectionCard, run, true); | |
}); | |
var selectors = { | |
sectionCard: 'curriculum-navigation-section', | |
sectionName: '.curriculum-navigation__section__title', | |
// class needed by this user script | |
sectionTime: '.section-time', | |
lectureItem: '.lecture__item', | |
lectureTime: '.lecture__item__link__time', | |
lectureStatus: '.cur-status', | |
lectureCheck: '.udi-check', | |
lectureProgress : '#top-detail > div.detail__progress > div > div.fx', | |
}; | |
// run(); | |
/** | |
Gets total and remaining time for each section. | |
Displays these per section. | |
Display the total of all sections | |
*/ | |
function run() { | |
var sections = $(selectors.sectionCard); | |
var totalLectureTime = 0; | |
var remainingLectureTime = 0; | |
$.each(sections, function(index, section) { | |
// remove previous time display | |
$(section).find(selectors.sectionTime).remove(); | |
// get the section title | |
var title = $(section).find(selectors.sectionName).text(); | |
// get the total times | |
var totalTimeTexts = getTimeTexts(section, false); | |
var totalTimeSeconds = textTimesToSeconds(totalTimeTexts); | |
var totalTime = secondsToTextTime(totalTimeSeconds); | |
// update the lecture time | |
totalLectureTime += totalTimeSeconds; | |
// initialize the text to display with the total time | |
var textToDisplay = totalTime; | |
// check if we need to display partial time | |
if (checkPartialTime(section)) { | |
// sum the partial times | |
var partialTimeTexts = getTimeTexts(section, true); | |
var partialTimeSeconds = textTimesToSeconds(partialTimeTexts); | |
var partialTime = secondsToTextTime(partialTimeSeconds); | |
// update the lecture time | |
remainingLectureTime += partialTimeSeconds; | |
// prepend partial time | |
textToDisplay = partialTime + ' / ' + textToDisplay; | |
} | |
// check if we need to add up the total time to remaining time | |
if (getRemainingParts(section) === 0) { | |
remainingLectureTime += totalTimeSeconds; | |
} | |
// display the section text | |
displaySectionTime(section, textToDisplay); | |
}); | |
// display lecture totals | |
displayLectureTimeProgress(totalLectureTime, remainingLectureTime); | |
// stops the script from running continuously | |
return false; | |
} | |
function displayLectureTimeProgress(totalLectureTime, remainingLectureTime) { | |
// start with total | |
var displayText = secondsToTextTime(totalLectureTime); | |
// conditional add remaining | |
if (remainingLectureTime) { | |
displayText = secondsToTextTime(remainingLectureTime) + ' / ' + displayText; | |
} | |
// surround in parens | |
displayText = '(' + displayText + ')'; | |
// add to DOM | |
var lectureProgressClass = 'lecture-progress-time'; | |
var lectureProgressSpans = $(selectors.lectureProgress).find('.' + lectureProgressClass); | |
if (lectureProgressSpans.length > 0) { | |
$(lectureProgressSpans[0]).text(displayText); | |
} else { | |
$(selectors.lectureProgress + ' > div').before( | |
'<span' | |
+ ' class="'+ lectureProgressClass + '"' | |
+ ' style="margin-left: 1em;"' | |
+'">' | |
+ displayText + '</span>' | |
); | |
} | |
return displayText; | |
} | |
/* | |
Gets the section parts and checks if it's not 0 or the total parts | |
*/ | |
function checkPartialTime(section) { | |
// get the section parts | |
var sectionParts = getSectionParts(section); | |
// determine what times to get | |
var totalSections = sectionParts[1]; | |
var sectionsToGo = sectionParts[0]; | |
return sectionsToGo !== 0 && sectionsToGo != totalSections; | |
} | |
function getRemainingParts(section) { | |
// get the section parts | |
var sectionParts = getSectionParts(section); | |
// determine what times to get | |
return sectionParts[0]; | |
} | |
/** | |
Get the section's time. Whether partial or total is determined by the passed in | |
parameter. | |
*/ | |
function getTimeTexts(section, isPartialTime) { | |
// get the times | |
var $lectures = $(section).find(selectors.lectureItem); | |
// Check for partial time | |
if (isPartialTime) { | |
// filter down to just the non-completed ones | |
$lectures = $lectures.filter(':not(.completed)'); | |
} | |
// get the time spans | |
var timeSpans = $lectures.find(selectors.lectureTime); | |
// convert to timeTexts and return | |
return convertTimeSpansToTexts(timeSpans); | |
} | |
function displaySectionTime(section, displayText) { | |
var sectionTimeClass = 'section-time'; | |
// prepend to lecture status | |
var totalTimeSpan = $(section).find(selectors.lectureStatus).find(sectionTimeClass); | |
// check to see if we've already added the time to the DOM | |
if (totalTimeSpan.length > 0) { | |
$(totalTimeSpan[0]).text(displayText); | |
} else { | |
// we haven't, so create the element and add it | |
$(section).find(selectors.lectureStatus) | |
.prepend('<span class="' + sectionTimeClass + '" style="margin-right:1em">'+ displayText + '</span>'); | |
} | |
} | |
function getSectionParts(section) { | |
return $(section).find(selectors.lectureStatus).text() | |
// split up the parts by "/" | |
.split('/') | |
// trim up the space | |
.map(function(text) { return text.trim(); }); | |
} | |
function convertTimeSpansToTexts(timeSpans) { | |
var timeTexts = []; | |
for (var i=0; i<timeSpans.length; i++) { | |
timeTexts.push($(timeSpans[i]).text()); | |
} | |
return timeTexts; | |
} | |
function convertTextToSeconds(textTime) { | |
var timeParts = textTime.split(':'); | |
var seconds = parseInt(timeParts[1]); | |
seconds += parseInt(timeParts[0]) * 60; | |
return seconds; | |
} | |
// get the summation of the times | |
function textTimesToSeconds(textTimes) { | |
var totalSeconds = 0; | |
// get total minutes | |
$.each(textTimes, function(index, textTime) { | |
totalSeconds += convertTextToSeconds(textTime); | |
}); | |
return totalSeconds; | |
} | |
function secondsToTextTime(totalSeconds) { | |
// convert back to hh:mm | |
var hours = Math.floor(totalSeconds / 60 / 60); | |
var remainingTime = totalSeconds - hours * 60 * 60; | |
var minutes = Math.floor(remainingTime / 60); | |
remainingTime = remainingTime - minutes * 60; | |
var seconds = remainingTime; | |
return getTime(hours, minutes, seconds); | |
} | |
// get the time in the following format -> hh:mm:ss | |
function getTime(hours, minutes, seconds) { | |
var result = ''; | |
// get the hours part | |
if (hours > 0) { | |
result += hours + ':'; | |
result += timePad(minutes); | |
} else { | |
// we didn't have any hours | |
result += minutes; | |
} | |
// check for minutes | |
if (minutes > 0) { | |
result += ':' + timePad(seconds); | |
} else { | |
// we didn't have any minutes, but we should say 0 | |
result += '0:' + timePad(seconds); | |
} | |
return result; | |
} | |
// time should be a length of 2, so prepend with 0 | |
function timePad(timeSegment) { | |
var result = timeSegment + ''; | |
while (result.length < 2) { | |
result = '0' + result; | |
} | |
return result; | |
} | |
})(); |
Can someone teach me how to fix this script? I would maintain it full-time.
Tbh idk what does the above code do, but if someone wants to check how many mins left for their course
you can copy-paste the code below to your console in dev tools :)
function getLeftTime() {
// Open all the sections
console.log('Opening Sections...');
document.querySelectorAll('.js-panel-toggler').forEach((item) => {
const isExpanded = item.getAttribute('aria-expanded');
if (!isExpanded) {
item.click();
}
})
console.log('Opening Sections DONE');
console.log('Calculation Total ...')
let total = 0;
const items = document.querySelectorAll('.item-link.udlite-custom-focus-visible') // each item
items.forEach((item) => {
// console.log(item);
const isChecked = item.querySelector('.udlite-real-toggle-input').checked;
if (!isChecked) {
let timer = item.querySelector('.udlite-text-xs span');
if (timer) {
time = timer.innerText.replace('min', '');
// console.log('time', time);
total+= parseInt(time);
}
}
})
console.log('Calculation Total DONE')
console.log('left Time(Min): ', total);
}
getLeftTime()
An updated version that works:
(function getLeftTime() {
const scrollTopValue = window.scrollY;
// Opening unopened sections
const unopened = [];
document
.querySelectorAll('.section--section--BukKG > span')
.forEach((item) => {
const isExpanded = item.getAttribute('data-checked') === 'checked';
if (!isExpanded) {
item.parentNode
.querySelector('.udlite-accordion-panel-title')
.click();
unopened.push(item);
}
});
// Calculating total
let total = 0;
const items = document.querySelectorAll(
'.item-link.udlite-custom-focus-visible'
);
items.forEach((item) => {
const isChecked = item.querySelector(
'.udlite-real-toggle-input'
).checked;
if (!isChecked) {
let timer = item.querySelector('.udlite-text-xs span');
if (timer) {
time = timer.innerText.replace('min', '');
total += parseInt(time);
}
}
});
unopened.forEach((item) =>
item.parentNode.querySelector('.udlite-accordion-panel-title').click()
);
window.scrollTo({ top: scrollTopValue });
const hourString =
total / 60.0 < 10
? '0' + String(Math.trunc(total / 60.0))
: String(Math.trunc(total / 60.0));
const minuteString =
total % 60.0 < 10
? '0' + String(Math.trunc(total % 60.0))
: String(Math.trunc(total % 60.0));
console.log(`Time left (HH:MM): ${hourString}:${minuteString}`);
})();
I created a gist with updated working code here:
https://gist.github.com/lundeen-bryan/3fc513ce89564af0904c053b56aba36f
I will try to keep it updated for everyone, but it's pretty straight forward and has good comments to document what each block of js is doing.
You can find my repo here for it : https://github.com/edenizk/udemyRemainingTimerExtention
Also I've added as an extension in extension store:
https://chromewebstore.google.com/detail/udemy-remaining-time-calc/klpecghaflmikhifcnphellhoacmnibg
If anyone needs any new feature just leave it in issue section, or create a PR 🙂
This no longer works : (