您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
What if you got a 45/50 on that next test? What would your grade be? This extension answers those questions without you having to manually calculate the answer. All grades are editable, and the buttons are self-explanatory. (New Jersey)
// ==UserScript== // @name Genesis What If? // @namespace http://tampermonkey.net/ // @version 1.35 // @description What if you got a 45/50 on that next test? What would your grade be? This extension answers those questions without you having to manually calculate the answer. All grades are editable, and the buttons are self-explanatory. (New Jersey) // @author You // @license MIT // @match https://parents.c3.genesisedu.net/*/parents?tab1=studentdata&tab2=gradebook&tab3=coursesummary* // @icon https://parents.robbinsville.k12.nj.us//genesis/images/newIcon2.ico // @grant none // ==/UserScript== (function() { const fractionPattern = /(\d+(\.\d+)?) \/ (\d+)/; var numerator = 0; var denominator = 0; // const headings = document.querySelectorAll(".listheading") let specialnumber = -2 var listHeadings = document.querySelectorAll('.listheading'); var listRowEvens = document.querySelectorAll('.listroweven'); var listRowOdds = document.querySelectorAll('.listrowodd'); function HowManyCategories() { var secondListHeading = listHeadings[1]; var thirdListHeading = listHeadings[2]; var elementsBetweenHeadings = 0; // Iterate through the elements between the second and third list headings for (let i = 0; i < listRowEvens.length; i++) { let element = listRowEvens[i]; if (element.compareDocumentPosition(secondListHeading) & Node.DOCUMENT_POSITION_PRECEDING && element.compareDocumentPosition(thirdListHeading) & Node.DOCUMENT_POSITION_FOLLOWING) { elementsBetweenHeadings++; } } for (let i = 0; i < listRowOdds.length; i++) { let element = listRowOdds[i]; if (element.compareDocumentPosition(secondListHeading) & Node.DOCUMENT_POSITION_PRECEDING && element.compareDocumentPosition(thirdListHeading) & Node.DOCUMENT_POSITION_FOLLOWING) { elementsBetweenHeadings++; } } return elementsBetweenHeadings; } var categoryWeightage = {} var categoryGrades = {} function AssignWeightage(row){ let categoryName = row.querySelector('td.cellLeft b').textContent; let weightString = row.querySelector('td.cellRight:nth-child(2)').textContent; let weight = parseFloat(weightString.replace('%', '')) / 100; // Convert to decimal categoryGrades[categoryName] = [0,0] categoryWeightage[categoryName] = weight; //console.log(categoryGrades) } if (listHeadings.length >= 3) { var weightage = true; var numCategories = HowManyCategories() specialnumber -= numCategories //console.log(numCategories) let rows = document.querySelectorAll('.listroweven, .listrowodd'); let filteredRows = Array.from(rows).slice(0, -2) let catArray = Array.from(filteredRows).slice(filteredRows.length - numCategories, filteredRows.length) catArray.forEach(row => AssignWeightage(row)) //console.log(categoryWeightage) } function IdentifyGrade(){ newGrade.textContent = " " newGrade.textContent = "|| " + percentage + "% " + percentageToLetterGrade(percentage) originalGrade.insertAdjacentElement('afterend', newGrade) } function EditableGrade(row){ let cells = row.querySelectorAll('.cellLeft') let cell = cells[1] if(weightage){ var categoryName2 = cells[0].querySelectorAll('div')[2].textContent.trim() //console.log(categoryName) var cellLeft = cells[0]; var existingDiv = cellLeft.querySelector('div[style="font-size: 8pt;font-style: italic;"]'); // Create a select element var selectElement = document.createElement('select'); // Populate the select element with options from the dictionary for (var category in categoryWeightage) { var optionElement = document.createElement('option'); optionElement.value = category; optionElement.text = category; if (category === existingDiv.textContent.trim()) { optionElement.selected = true; } selectElement.appendChild(optionElement); } // Add an event listener to the select element selectElement.addEventListener('change', function() { var selectedCategory = selectElement.options[selectElement.selectedIndex].text; var selectedValue = categoryWeightage[selectedCategory]; // You can do something with the selected value if needed // Update the content of the element based on the selected category cellLeft.querySelector('input[type="hidden"]').value = selectedCategory; }); // Replace the existing div with the select element existingDiv.replaceWith(selectElement); } let childNodes = cell.childNodes; var divElements = cell.getElementsByTagName('div'); var secondToLastDiv = divElements[divElements.length - 2]; if (secondToLastDiv !== undefined) { var spanElement = secondToLastDiv.querySelector('span'); } if (spanElement && (spanElement.textContent.trim() === 'Absent' || spanElement.textContent.trim() === 'Missing')) { return; } let innerGrade = ""; for (let i = 0; i < childNodes.length; i++) { if (childNodes[i].nodeType === Node.TEXT_NODE && childNodes[i].textContent.indexOf('/') !== -1) { //current issue tha innerGrade += childNodes[i].textContent; childNodes[i].textContent = " "; let spanElement = document.createElement('span'); spanElement.textContent = innerGrade; spanElement.setAttribute('contentEditable', true) cell.replaceChild(spanElement, childNodes[i]) break; } } innerGrade = innerGrade.trim().replace(/\s+/g, " ") const [num, denom] = innerGrade.split('/').map(num => parseFloat(num.trim())); if(!weightage){ numerator += num; denominator += denom; } else{ categoryGrades[categoryName2][0] += num categoryGrades[categoryName2][1] += denom } //console.log(innerGrade, num, denom) } function SelectGrade(row){ let cells = row.querySelectorAll('.cellLeft') let cell = cells[1] if(weightage){ //var categoryName2 = cells[0].querySelectorAll('div')[2].textContent.trim() var selectElement = row.querySelector('.cellLeft select'); var categoryName2 = selectElement.value; //console.log(categoryName2); } var divElements = cell.getElementsByTagName('div'); var secondToLastDiv = divElements[divElements.length - 2]; if (secondToLastDiv !== undefined) { var spanElement = secondToLastDiv.querySelector('span'); } if (spanElement && (spanElement.textContent.trim() === 'Absent' || spanElement.textContent.trim() === 'Missing')) { return; } //let cell = row.querySelectorAll('.cellLeft')[1] const spanElements = cell.querySelectorAll('span') let innerGrade = cell.querySelectorAll('span')[spanElements.length - 1].textContent.trim().replace(/\s+/g, " ") const [num, denom] = innerGrade.split('/').map(num => parseFloat(num.trim())); var percen = 0; if(denom != 0){ percen = ((num / denom) * 100).toFixed(2); } else{ percen = "NaN" } // Select the bottom div element const bottomDivElement = cell.querySelector('div[style="font-weight: bold;"]'); // Set the percentage as its content //console.log(percen) if(percen != "NaN"){ bottomDivElement.textContent = percen + '%'; } if(!weightage){ numerator += num; denominator += denom; }else{ categoryGrades[categoryName2][0] += num categoryGrades[categoryName2][1] += denom } //console.log(innerGrade, num, denom) } function SelectAssignments(){ let rows = document.querySelectorAll('.listroweven, .listrowodd') let rowArray = Array.from(rows).slice(0, specialnumber) //console.log(rowArray) rowArray.forEach(row => EditableGrade(row)) } function Refresh(){ numerator = 0; denominator = 0; for (let category in categoryGrades) { if (categoryGrades.hasOwnProperty(category)) { categoryGrades[category] = categoryGrades[category].map(value => 0); // Set all values to zero } } let rows = document.querySelectorAll('.listroweven, .listrowodd'); let filteredRows = Array.from(rows).slice(0, -2) let catArray = Array.from(filteredRows).slice(filteredRows.length - numCategories, filteredRows.length) let rowArray = Array.from(rows).slice(0, specialnumber) //console.log(rowArray) rowArray.forEach(row => SelectGrade(row)) let percentage = 0.000 if(!weightage){ percentage = ((numerator/denominator) * 100 ) } else { for (const category in categoryGrades) { const categoryPercentage = (categoryGrades[category][0] / categoryGrades[category][1]) * 100; percentage += categoryPercentage * categoryWeightage[category]; } catArray.forEach(row => changeCategoryPercentage(row)) } percentage = percentage.toFixed(2) newGrade.textContent = "|| " + percentage + "% " + percentageToLetterGrade(percentage) console.log(categoryGrades) } function changeCategoryPercentage(row){ let categoryName = row.querySelector('td.cellLeft b').textContent; let weightString = row.querySelector('td.cellRight:nth-child(3)').textContent; let category = row.querySelector('td.cellLeft').textContent let categoryPercentage = (categoryGrades[category][0] / categoryGrades[category][1]) * 100; row.querySelector('td.cellRight:nth-child(3)').textContent = categoryPercentage.toFixed(1) + " %"; } function addRow(){ //CHANGE THIS SO IT DOES NOT RELY ON CLONING, SO IT WORKS WITH JUST ONE ROW let row = document.querySelectorAll('.listroweven, .listrowodd') let rowArray = Array.from(row).slice(0, specialnumber) //const numberOfRows = rowArray.length let lastRow = rowArray[rowArray.length - 1]; let secondToLastRow = rowArray[rowArray.length - 2]; let clonedRow = secondToLastRow.cloneNode(true); clonedRow.querySelector('b').textContent = "Genesis What If" clonedRow.querySelector('b').style.color = "Green" clonedRow.querySelectorAll('div')[5].textContent = 'N/A' clonedRow.querySelectorAll('div')[5].setAttribute('contentEditable', 'true') lastRow.parentNode.insertBefore(clonedRow, lastRow.nextSibling); } function percentageToLetterGrade(numberGrade){ let letter; if (numberGrade >= 96.5) { letter = 'A+'; } else if (numberGrade >= 92.5) { letter = 'A'; return letter; } else if (numberGrade >= 89.5) { letter = 'A-'; } else if (numberGrade >= 86.5) { letter = 'B+'; } else if (numberGrade >= 82.5) { letter = 'B'; } else if (numberGrade >= 79.5) { letter = 'B-'; } else if (numberGrade >= 76.5) { letter = 'C+'; } else if (numberGrade >= 72.5) { letter = 'C'; } else if (numberGrade >= 69.5) { letter = 'C-'; } else if (numberGrade >= 66.5) { letter = 'D+'; } else if (numberGrade >= 59.5) { letter = 'D-'; } else { letter = 'F'; } return letter; }; function AddButtons(){ const headerT = document.querySelectorAll('.listheading')[0]; const parentDiv = headerT//.parentNode let refreshButton = document.createElement("button") refreshButton.id="refreshButton" refreshButton.innerHTML = "Refresh" refreshButton.onclick = () => Refresh(); refreshButton.title = "The keyboard shortcut for refreshButton is shift + R"; let addRowButton = document.createElement("button") addRowButton.innerHTML = "Add Row" addRowButton.onclick = () => addRow(); addRowButton.title = "The keyboard shortcut for addRowButton is shift + T"; parentDiv.insertAdjacentElement('beforebegin', refreshButton) parentDiv.insertAdjacentElement('beforebegin', addRowButton) } SelectAssignments(); let originalGrade = document.querySelectorAll('b')[0] //console.log(originalGrade.textContent.trim().replace(/\s+/g, ' ')) let percentage = 0.000 if(!weightage){ percentage = ((numerator/denominator) * 100 ) } else { for (const category in categoryGrades) { const categoryPercentage = (categoryGrades[category][0] / categoryGrades[category][1]) * 100; percentage += categoryPercentage * categoryWeightage[category]; } } percentage = percentage.toFixed(2) let newGrade = document.createElement('b') IdentifyGrade(); AddButtons(); // console.log(categoryGrades) function doc_keyUp(e) { // this would test for whichever key is 40 (down arrow) and the ctrl key at the same time if (e.shiftKey && e.key === 'R') { // call your function to do the thing Refresh(); } } function doc_keyUp2(e) { if (e.shiftKey && e.key === 'R') { Refresh(); } if (e.shiftKey && e.key === 'T') { addRow(); } } // Add event listeners for keyup event document.addEventListener('keyup', doc_keyUp2, false); // register the handler document.addEventListener('keyup', doc_keyUp, false); })();