This commit is contained in:
Kevin Dao
2019-08-05 21:10:20 -05:00
8 changed files with 570 additions and 271 deletions

View File

@@ -31,6 +31,7 @@
animation: spin 2s linear infinite;
}
@keyframes spin {
0% {
transform: rotate(0deg);
@@ -73,10 +74,16 @@
.dateTimePlace {
margin-left: 5px;
margin-bottom: 0px;
font-size: smaller;
font-weight: bold;
}
#chartcontainer {
max-width: 100%;
height: 250px;
}
#chart {
min-width: auto;
max-width: 100%;

View File

@@ -1,6 +1,8 @@
updateBadge(true);
var grades;
loadDataBase()
/* Handle messages and their commands from content and popup scripts*/
chrome.runtime.onMessage.addListener(function(request, sender, response) {
chrome.runtime.onMessage.addListener(function (request, sender, response) {
switch (request.command) {
case "courseStorage":
if (request.action == "add") {
@@ -31,6 +33,8 @@ chrome.runtime.onMessage.addListener(function(request, sender, response) {
case "updateCourseList":
updateTabs();
break;
case "gradesQuery":
executeQuery(request.query, response);
default:
const xhr = new XMLHttpRequest();
const method = request.method ? request.method.toUpperCase() : "GET";
@@ -51,35 +55,35 @@ chrome.runtime.onMessage.addListener(function(request, sender, response) {
});
/* Initially set the course data in storage */
chrome.runtime.onInstalled.addListener(function(details) {
chrome.runtime.onInstalled.addListener(function (details) {
if (details.reason == "install") {
chrome.storage.sync.get('savedCourses', function(data) {
chrome.storage.sync.get('savedCourses', function (data) {
if (!data.savedCourses) {
var arr = new Array();
chrome.storage.sync.set({
savedCourses: arr
}, function() {
}, function () {
console.log('initial course list');
});
chrome.storage.sync.set({
courseConflictHighlight: true
}, function() {
}, function () {
console.log('initial highlighting: true');
});
chrome.storage.sync.set({
loadAll: true
}, function() {
}, function () {
console.log('initial loadAll: true');
});
}
});
} else if (details.reason == "update") {
console.log("updated");
chrome.storage.sync.get('loadAll', function(data) {
chrome.storage.sync.get('loadAll', function (data) {
if (data.loadAll == undefined) {
chrome.storage.sync.set({
loadAll: true
}, function() {
}, function () {
console.log('initial loadAll: true');
});
}
@@ -88,8 +92,39 @@ chrome.runtime.onInstalled.addListener(function(details) {
});
function executeQuery(query, sendResponse) {
console.log(grades)
var res = grades.exec(query)[0];
sendResponse({
data: res,
});
}
/* Load the database*/
function loadDataBase() {
sql = window.SQL;
loadBinaryFile('grades.db', function (data) {
var sqldb = new SQL.Database(data);
grades = sqldb;
});
}
/* load the database from file */
function loadBinaryFile(path, success) {
var xhr = new XMLHttpRequest();
xhr.open("GET", chrome.extension.getURL(path), true);
xhr.responseType = "arraybuffer";
xhr.onload = function () {
var data = new Uint8Array(xhr.response);
var arr = new Array();
for (var i = 0; i != data.length; ++i) arr[i] = String.fromCharCode(data[i]);
success(arr.join(""));
};
xhr.send();
};
function updateBadge(first) {
chrome.storage.sync.get('savedCourses', function(data) {
chrome.storage.sync.get('savedCourses', function (data) {
if (data.savedCourses) {
let text = "";
if (data.savedCourses.length > 0) {
@@ -105,7 +140,7 @@ function updateBadge(first) {
});
timeout = 200;
}
setTimeout(function() {
setTimeout(function () {
chrome.browserAction.setBadgeBackgroundColor({
color: '#bf5700'
});
@@ -117,7 +152,7 @@ function updateBadge(first) {
/* Find all the conflicts in the courses and send them out/ if there is even a conflict*/
function checkConflicts(sendResponse) {
chrome.storage.sync.get('savedCourses', function(data) {
chrome.storage.sync.get('savedCourses', function (data) {
var conflicts = [];
var courses = data.savedCourses;
for (var i = 0; i < courses.length; i++) {
@@ -144,7 +179,7 @@ function checkConflicts(sendResponse) {
/* Find if the course at unique and with currdatearr is contained in the saved courses and if it conflicts with any other courses*/
function isSingleConflict(currdatearr, unique, sendResponse) {
chrome.storage.sync.get('savedCourses', function(data) {
chrome.storage.sync.get('savedCourses', function (data) {
var courses = data.savedCourses;
var conflict = false;
for (var i = 0; i < courses.length; i++) {
@@ -188,7 +223,7 @@ function isConflict(adtarr, bdtarr) {
/* Add the requested course to the storage*/
function add(request, sender, sendResponse) {
chrome.storage.sync.get('savedCourses', function(data) {
chrome.storage.sync.get('savedCourses', function (data) {
var courses = data.savedCourses;
if (!contains(courses, request.course.unique)) {
courses.push(request.course)
@@ -206,7 +241,7 @@ function add(request, sender, sendResponse) {
}
/* Find and Remove the requested course from the storage*/
function remove(request, sender, sendResponse) {
chrome.storage.sync.get('savedCourses', function(data) {
chrome.storage.sync.get('savedCourses', function (data) {
var courses = data.savedCourses;
console.log(courses);
var index = 0;
@@ -227,7 +262,7 @@ function remove(request, sender, sendResponse) {
/* Find if the unique is already contained within the storage*/
function alreadyContains(unique, sendResponse) {
chrome.storage.sync.get('savedCourses', function(data) {
chrome.storage.sync.get('savedCourses', function (data) {
var courses = data.savedCourses;
sendResponse({
alreadyContains: contains(courses, unique)
@@ -247,7 +282,7 @@ function contains(courses, unique) {
}
function updateTabs() {
chrome.tabs.query({}, function(tabs) {
chrome.tabs.query({}, function (tabs) {
for (var i = 0; i < tabs.length; i++) {
chrome.tabs.sendMessage(tabs[i].id, {
command: "updateCourseList"
@@ -260,7 +295,7 @@ const UPDATE_INTERVAL = 1000 * 60 * 16;
setInterval(updateStatus, UPDATE_INTERVAL);
// updateStatus();
function updateStatus(sendResponse) {
chrome.storage.sync.get('savedCourses', function(data) {
chrome.storage.sync.get('savedCourses', function (data) {
var courses = data.savedCourses;
var nochange = true;
for (let i = 0; i < courses.length; i++) {
@@ -268,23 +303,27 @@ function updateStatus(sendResponse) {
let c = courses[i];
let oldstatus = c.status;
let oldlink = c.link;
$.ajax({url: oldlink, success: function(result){
if(result){
console.log(result);
var object = $('<div/>').html(result).contents();
let newstatus = object.find('[data-th="Status"]').text();
let registerlink = object.find('td[data-th="Add"] a');
if (registerlink) {
registerlink = registerlink.attr('href');
$.ajax({
url: oldlink,
success: function (result) {
if (result) {
console.log(result);
var object = $('<div/>').html(result).contents();
let newstatus = object.find('[data-th="Status"]').text();
let registerlink = object.find('td[data-th="Add"] a');
if (registerlink) {
registerlink = registerlink.attr('href');
}
var haschanged = (newstatus == oldstatus && registerlink == oldlink);
if (!haschanged) {
console.log(c.unique + ' updated from ' + oldstatus + " to " + newstatus + " and " + oldlink + " to " + registerlink);
}
nochange &= haschanged;
c.registerlink = registerlink;
c.status = newstatus;
}
var haschanged = (newstatus == oldstatus && registerlink == oldlink);
if (!haschanged) {
console.log(c.unique + ' updated from ' + oldstatus + " to " + newstatus + " and " + oldlink + " to " + registerlink);
}
nochange &= haschanged;
c.registerlink = registerlink;
c.status = newstatus;
}}});
}
});
} catch (e) {

2
js/config.js Normal file
View File

@@ -0,0 +1,2 @@
const fadetime = 150;
const butdelay = 75;

View File

@@ -1,4 +1,3 @@
var grades;
var rmpLink;
var next;
var bottom;
@@ -20,18 +19,11 @@ var semesterCode;
var isIndividual = false;
var done = true;
const days = new Map([
["M", "Monday"],
["T", "Tuesday"],
["W", "Wednesday"],
["TH", "Thursday"],
["F", "Friday"]
]);
const fadetime = 150;
const butdelay = 75;
//This extension may be super lit, but you know what's even more lit?
//Matthew Tran's twitter and insta: @MATTHEWTRANN and @matthew.trann
console.log('UT Registration Plus is running on this page.');
if (document.querySelector('#fos_fl')) {
let params = (new URL(document.location)).searchParams;
@@ -44,14 +36,17 @@ if (document.querySelector('#fos_fl')) {
}
}
}
next = $("#next_nav_link");
chrome.storage.sync.get('loadAll', function (data) {
if (data.loadAll) {
$('[title*="next listing"]').remove();
}
});
loadDataBase();
next = $("#next_nav_link");
if (next) {
chrome.storage.sync.get('loadAll', function (data) {
if (data.loadAll) {
$('[title*="next listing"]').remove();
}
});
}
//make heading and modal
if (!$("#kw_results_table").length) {
$("table thead th:last-child").after('<th scope=col>Plus</th>');
@@ -111,7 +106,7 @@ if (!$("#kw_results_table").length) {
//update the conflicts
update(0);
/*Handle the button clicks*/
$("tbody").on('click', '#distButton', function () {
$("body").on('click', '#distButton', function () {
var row = $(this).closest('tr');
$('.modal-content').stop().animate({
scrollTop: 0
@@ -205,7 +200,7 @@ function loadNextPages() {
nextpage.find('tbody>tr').each(function () {
let hasCourseHead = $(this).find('td').hasClass("course_header");
if (!(hasCourseHead && $(this).has('th').length == 0)) {
$(this).append(`<td data-th="Plus"><input type="image" class="distButton" id="distButton" style="vertical-align: bottom; display:block;" width="20" height="20" src='${chrome.extension.getURL('images/disticon.png')}'/></td>`);
$(this).append(`<td data-th="Plus"><input type="image" class="distButton" id="distButton" style="vertical-align: bottom;" width="20" height="20" src='${chrome.extension.getURL('images/disticon.png')}'/></td>`);
// if ($(this).find('td[data-th="Status"]').text().includes('waitlisted')) {
// $(this).find('td').each(function () {
// $(this).css('background-color', '#E0E0E0');
@@ -338,7 +333,7 @@ function Course(coursename, unique, profname, datetimearr, status, link, registe
/*For a row, get all the course information and add the date-time-lines*/
function getCourseInfo(row) {
console.log('WHAT');
console.log(row);
semesterCode = new URL(window.location.href).pathname.split('/')[4];
$("h2.dateTimePlace").remove();
$('table').find('tr').each(function () {
@@ -452,27 +447,29 @@ function getDistribution(sem) {
query += "and sem like '%" + sem + "%'";
}
query += "order by a1+a2+a3+b1+b2+b3+c1+c2+c3+d1+d2+d3+f desc";
var res = grades.exec(query)[0];
var output = "";
if (!sem) {
openDialog(department, coursename, "aggregate", profname, res);
} else {
var data;
if (typeof res == 'undefined' || profname == "") {
data = [];
chrome.runtime.sendMessage({
command: "gradesQuery",
query: query
}, function (response) {
var res = response.data;
if (!sem) {
openDialog(department, coursename, "aggregate", profname, res);
} else {
data = res.values[0];
var data;
if (typeof res == 'undefined' || profname == "") {
data = [];
} else {
data = res.values[0];
}
setChart(data);
}
setChart(data);
}
});
}
/*Open the modal and show all the data*/
function openDialog(dep, cls, sem, professor, res) {
$("#myModal").fadeIn(fadetime);
//initial text on the "save course button"
chrome.runtime.sendMessage({
command: "alreadyContains",
unique: uniquenum
@@ -487,35 +484,11 @@ function openDialog(dep, cls, sem, professor, res) {
var data;
$("#semesters").empty();
if (typeof res == 'undefined' || profname == "") {
data = [];
$("#semesters").append("<option>No Data</option>")
data = [];
} else {
var semesters = res.values[0][18].split(",");
semesters.sort(function (a, b) {
var as = a.split(' ')[0];
var ay = parseInt(a.split(' ')[1]);
var bs = b.split(' ')[0];
var by = parseInt(b.split(' ')[1]);
if (ay < by) {
return -1;
}
if (ay > by) {
return 1;
}
var seas = {
"Spring": 0,
"Fall": 1,
"Summer": 2,
"Winter": 3
}
if (seas[as] < seas[bs]) {
return -1;
}
if (seas[as] > seas[bs]) {
return 1;
}
return 0;
});
semesters.sort(semesterSort);
semesters.reverse().unshift('Aggregate');
var sems = [];
for (var i = 0; i < semesters.length; i++) {
@@ -568,112 +541,7 @@ function close() {
function setChart(data) {
//set up the chart
chart = Highcharts.chart('chart', {
chart: {
type: 'column',
backgroundColor: ' #fefefe',
spacingLeft: 10
},
title: {
text: null
},
subtitle: {
text: null
},
legend: {
enabled: false
},
xAxis: {
title: {
text: 'Grades'
},
categories: [
'A',
'A-',
'B+',
'B',
'B-',
'C+',
'C',
'C-',
'D+',
'D',
'D-',
'F'
],
crosshair: true
},
yAxis: {
min: 0,
title: {
text: 'Students'
}
},
credits: {
enabled: false
},
lang: {
noData: "The professor hasn't taught this class :("
},
tooltip: {
headerFormat: '<span style="font-size:small; font-weight:bold">{point.key}</span><table>',
pointFormat: '<td style="color:{black};padding:0;font-size:small; font-weight:bold;"><b>{point.y:.0f} Students</b></td>',
footerFormat: '</table>',
shared: true,
useHTML: true
},
plotOptions: {
bar: {
pointPadding: 0.2,
borderWidth: 0
},
series: {
animation: {
duration: 700
}
}
},
series: [{
name: 'Grades',
data: [{
y: data[6],
color: '#4CAF50'
}, {
y: data[7],
color: '#8BC34A'
}, {
y: data[8],
color: '#CDDC39'
}, {
y: data[9],
color: '#FFEB3B'
}, {
y: data[10],
color: '#FFC107'
}, {
y: data[11],
color: '#FFA000'
}, {
y: data[12],
color: '#F57C00'
}, {
y: data[13],
color: '#FF5722'
}, {
y: data[14],
color: '#FF5252'
}, {
y: data[15],
color: '#E64A19'
}, {
y: data[16],
color: '#F44336'
}, {
y: data[17],
color: '#D32F2F'
}]
}]
}, function (chart) { // on complete
chart = Highcharts.chart('chart', buildChartConfig(data), function (chart) { // on complete
if (data.length == 0) {
//if no data, then show the message and hide the series
chart.renderer.text('Could not find data for this Instructor teaching this Course.', 100, 120)
@@ -716,77 +584,59 @@ function getDescription() {
// console.log(window.location.href);
// console.log(profurl);
console.log('hello');
$.ajax({url: profurl, success: function(response){
if (response) {
console.log(profurl);
var output = "";
var object = $('<div/>').html(response).contents();
object.find('#details > p').each(function () {
var sentence = $(this).text();
if (sentence.indexOf("Prerequisite") == 0) {
sentence = "<li style='font-weight: bold;' class='descriptionli'>" + sentence + "</li>";
} else if (sentence.indexOf("May be") >= 0) {
sentence = "<li style='font-style: italic;' class='descriptionli'>" + sentence + "</li>";
} else if (sentence.indexOf("Restricted to") == 0) {
sentence = "<li style='color:red;' class='descriptionli'>" + sentence + "</li>";
} else {
sentence = "<li class='descriptionli'>" + sentence + "</li>";
$.ajax({
url: profurl,
success: function (response) {
if (response) {
console.log(profurl);
var output = "";
var object = $('<div/>').html(response).contents();
object.find('#details > p').each(function () {
var sentence = $(this).text();
if (sentence.indexOf("Prerequisite") == 0) {
sentence = "<li style='font-weight: bold;' class='descriptionli'>" + sentence + "</li>";
} else if (sentence.indexOf("May be") >= 0) {
sentence = "<li style='font-style: italic;' class='descriptionli'>" + sentence + "</li>";
} else if (sentence.indexOf("Restricted to") == 0) {
sentence = "<li style='color:red;' class='descriptionli'>" + sentence + "</li>";
} else {
sentence = "<li class='descriptionli'>" + sentence + "</li>";
}
output += sentence;
});
description = output;
console.log(response);
if (!description) {
description = "<p style='color:red;font-style:bold'>There was an error. Please refresh the page and/or log back in using your UT EID and password.</p>"
}
$("#description").animate({
'opacity': 0
}, 200, function () {
$(this).html(description).animate({
'opacity': 1
}, 200);
});
var first = object.find('td[data-th="Instructor"]').text();
first = first.substring(first.indexOf(", "), first.indexOf(" ", first.indexOf(", ") + 2));
first = first.substring(2);
rmpLink = `http://www.ratemyprofessors.com/search.jsp?queryBy=teacherName&schoolName=university+of+texas+at+austin&queryoption=HEADER&query=${first} ${profname};&facetSearch=true`;
if (profname == "") {
eCISLink = `http://utdirect.utexas.edu/ctl/ecis/results/index.WBX?s_in_action_sw=S&s_in_search_type_sw=C&s_in_max_nbr_return=10&s_in_search_course_dept=${department}&s_in_search_course_num=${course_nbr}`;
} else {
eCISLink = `http://utdirect.utexas.edu/ctl/ecis/results/index.WBX?&s_in_action_sw=S&s_in_search_type_sw=N&s_in_search_name=${profname.substring(0, 1) + profname.substring(1).toLowerCase()}%2C%20${first.substring(0, 1) + first.substring(1).toLowerCase()}`;
}
output += sentence;
});
description = output;
console.log(response);
if (!description) {
description = "<p style='color:red;font-style:bold'>You have been logged out. Please refresh the page and log back in using your UT EID and password.</p>"
}
$("#description").animate({
'opacity': 0
}, 200, function () {
$(this).html(description).animate({
'opacity': 1
}, 200);
});
var first = object.find('td[data-th="Instructor"]').text();
first = first.substring(first.indexOf(", "), first.indexOf(" ", first.indexOf(", ") + 2));
first = first.substring(2);
rmpLink = `http://www.ratemyprofessors.com/search.jsp?queryBy=teacherName&schoolName=university+of+texas+at+austin&queryoption=HEADER&query=${first} ${profname};&facetSearch=true`;
if (profname == "") {
eCISLink = `http://utdirect.utexas.edu/ctl/ecis/results/index.WBX?s_in_action_sw=S&s_in_search_type_sw=C&s_in_max_nbr_return=10&s_in_search_course_dept=${department}&s_in_search_course_num=${course_nbr}`;
} else {
eCISLink = `http://utdirect.utexas.edu/ctl/ecis/results/index.WBX?&s_in_action_sw=S&s_in_search_type_sw=N&s_in_search_name=${profname.substring(0, 1) + profname.substring(1).toLowerCase()}%2C%20${first.substring(0, 1) + first.substring(1).toLowerCase()}`;
description = "<p style='color:red;font-style:bold'>You have been logged out. Please refresh the page and log back in using your UT EID and password.</p>"
$("#description").animate({
'opacity': 0
}, 200, function () {
$(this).html(description).animate({
'opacity': 1
}, 200);
});
rmpLink = "http://www.ratemyprofessors.com/campusRatings.jsp?sid=1255";
eCISLink = "http://utdirect.utexas.edu/ctl/ecis/results/index.WBX?";
}
} else {
description = "<p style='color:red;font-style:bold'>You have been logged out. Please refresh the page and log back in using your UT EID and password.</p>"
$("#description").animate({
'opacity': 0
}, 200, function () {
$(this).html(description).animate({
'opacity': 1
}, 200);
});
rmpLink = "http://www.ratemyprofessors.com/campusRatings.jsp?sid=1255";
eCISLink = "http://utdirect.utexas.edu/ctl/ecis/results/index.WBX?";
}
}});
}
/* Load the database*/
function loadDataBase() {
sql = window.SQL;
loadBinaryFile('grades.db', function (data) {
var sqldb = new SQL.Database(data);
grades = sqldb;
});
}
/* load the database from file */
function loadBinaryFile(path, success) {
var xhr = new XMLHttpRequest();
xhr.open("GET", chrome.extension.getURL(path), true);
xhr.responseType = "arraybuffer";
xhr.onload = function () {
var data = new Uint8Array(xhr.response);
var arr = new Array();
for (var i = 0; i != data.length; ++i) arr[i] = String.fromCharCode(data[i]);
success(arr.join(""));
};
xhr.send();
};

1
js/jquery.initialize.min.js vendored Normal file
View File

@@ -0,0 +1 @@
(function($){"use strict";var combinators=[" ",">","+","~"];var fraternisers=["+","~"];var complexTypes=["ATTR","PSEUDO","ID","CLASS"];function grok(msobserver){if(!$.find.tokenize){msobserver.isCombinatorial=true;msobserver.isFraternal=true;msobserver.isComplex=true;return}msobserver.isCombinatorial=false;msobserver.isFraternal=false;msobserver.isComplex=false;var token=$.find.tokenize(msobserver.selector);for(var i=0;i<token.length;i++){for(var j=0;j<token[i].length;j++){if(combinators.indexOf(token[i][j].type)!=-1)msobserver.isCombinatorial=true;if(fraternisers.indexOf(token[i][j].type)!=-1)msobserver.isFraternal=true;if(complexTypes.indexOf(token[i][j].type)!=-1)msobserver.isComplex=true}}}var MutationSelectorObserver=function(selector,callback,options){this.selector=selector.trim();this.callback=callback;this.options=options;grok(this)};var msobservers=[];msobservers.initialize=function(selector,callback,options){var seen=[];var callbackOnce=function(){if(seen.indexOf(this)==-1){seen.push(this);$(this).each(callback)}};$(options.target).find(selector).each(callbackOnce);var msobserver=new MutationSelectorObserver(selector,callbackOnce,options);this.push(msobserver);var observer=new MutationObserver(function(mutations){var matches=[];for(var m=0;m<mutations.length;m++){if(mutations[m].type=="attributes"){if(mutations[m].target.matches(msobserver.selector))matches.push(mutations[m].target);if(msobserver.isFraternal)matches.push.apply(matches,mutations[m].target.parentElement.querySelectorAll(msobserver.selector));else matches.push.apply(matches,mutations[m].target.querySelectorAll(msobserver.selector))}if(mutations[m].type=="childList"){for(var n=0;n<mutations[m].addedNodes.length;n++){if(!(mutations[m].addedNodes[n]instanceof Element))continue;if(mutations[m].addedNodes[n].matches(msobserver.selector))matches.push(mutations[m].addedNodes[n]);if(msobserver.isFraternal)matches.push.apply(matches,mutations[m].addedNodes[n].parentElement.querySelectorAll(msobserver.selector));else matches.push.apply(matches,mutations[m].addedNodes[n].querySelectorAll(msobserver.selector))}}}for(var i=0;i<matches.length;i++)$(matches[i]).each(msobserver.callback)});var defaultObeserverOpts={childList:true,subtree:true,attributes:msobserver.isComplex};observer.observe(options.target,options.observer||defaultObeserverOpts);return observer};$.fn.initialize=function(callback,options){return msobservers.initialize(this.selector,callback,$.extend({},$.initialize.defaults,options))};$.initialize=function(selector,callback,options){return msobservers.initialize(selector,callback,$.extend({},$.initialize.defaults,options))};$.initialize.defaults={target:document.documentElement,observer:null}})(jQuery);

152
js/util.js Normal file
View File

@@ -0,0 +1,152 @@
const days = new Map([
["M", "Monday"],
["T", "Tuesday"],
["W", "Wednesday"],
["TH", "Thursday"],
["F", "Friday"]
]);
const semOrder = {
"Spring": 0,
"Fall": 1,
"Summer": 2,
"Winter": 3
}
function buildQuery(course_data, sem) {
let query = !sem ? "select * from agg" : "select * from grades";
query += " where dept like '%" + course_data["department"] + "%'";
query += " and prof like '%" + course_data["prof_name"].replace(/'/g, "") + "%'";
query += " and course_nbr like '%" + course_data["number"] + "%'";
if (sem) {
query += "and sem like '%" + sem + "%'";
}
return query + "order by a1+a2+a3+b1+b2+b3+c1+c2+c3+d1+d2+d3+f desc";
}
function semesterSort(semA, semB) {
let aName = semA.split(' ')[0];
let aYear = parseInt(semA.split(' ')[1]);
let bName = semB.split(' ')[0];
let bYear = parseInt(semB.split(' ')[1]);
if (aYear < bYear)
return -1;
if (aYear > bYear)
return 1;
if (semOrder[aName] < semOrder[bName])
return -1;
if (semOrder[aName] > semOrder[bName])
return 1;
return 0;
}
function buildChartConfig(data) {
return {
chart: {
type: 'column',
backgroundColor: ' #fefefe',
spacingLeft: 10
},
title: {
text: null
},
subtitle: {
text: null
},
legend: {
enabled: false
},
xAxis: {
title: {
text: 'Grades'
},
categories: [
'A',
'A-',
'B+',
'B',
'B-',
'C+',
'C',
'C-',
'D+',
'D',
'D-',
'F'
],
crosshair: true
},
yAxis: {
min: 0,
title: {
text: 'Students'
}
},
credits: {
enabled: false
},
lang: {
noData: "The professor hasn't taught this class :("
},
tooltip: {
headerFormat: '<span style="font-size:small; font-weight:bold">{point.key}</span><table>',
pointFormat: '<td style="color:{black};padding:0;font-size:small; font-weight:bold;"><b>{point.y:.0f} Students</b></td>',
footerFormat: '</table>',
shared: true,
useHTML: true
},
plotOptions: {
bar: {
pointPadding: 0.2,
borderWidth: 0
},
series: {
animation: {
duration: 700
}
}
},
series: [{
name: 'Grades',
data: [{
y: data[6],
color: '#4CAF50'
}, {
y: data[7],
color: '#8BC34A'
}, {
y: data[8],
color: '#CDDC39'
}, {
y: data[9],
color: '#FFEB3B'
}, {
y: data[10],
color: '#FFC107'
}, {
y: data[11],
color: '#FFA000'
}, {
y: data[12],
color: '#F57C00'
}, {
y: data[13],
color: '#FF5722'
}, {
y: data[14],
color: '#FF5252'
}, {
y: data[15],
color: '#E64A19'
}, {
y: data[16],
color: '#F44336'
}, {
y: data[17],
color: '#D32F2F'
}]
}]
}
}

241
js/utplanner.js Normal file
View File

@@ -0,0 +1,241 @@
if ($('html').hasClass('gr__utexas_collegescheduler_com')) {
$.initialize("table.section-detail-grid", function () {
$(this).find('thead>tr').append('<th> Plus</th')
$(this).find('tbody>tr').each(function () {
$(this).append(`<td data-th="Plus"><input type="image" class="distButton" id="distButton" style="vertical-align: bottom;" width="20" height="20" src='${chrome.extension.getURL('images/disticon.png')}'/></td>`);
})
});
}
curr_course = {}
var modhtml = `<div class=modal id=myModal>
<div class=modal-content>
<span class=close>×</span>
<div class=card>
<div class=cardcontainer>
<h2 class=title id="title">Computer Fluency (C S 302)</h2>
<h2 class=profname id="profname">with Bruce Porter</h2>
<div id="topbuttons" class=topbuttons>
<button class=matbut id="rateMyProf" style="background: #4CAF50;"> RMP </button>
<button class=matbut id="eCIS" style="background: #CDDC39;"> eCIS </button>
<button class=matbut id="Syllabi"> Past Syllabi </button>
</div>
</div>
</div>
<div class=card style='text-align:center'>
<select id="semesters" style='text-align-last:center;color:#666666;fill:#666666;'></select>
<div class="loader" id='loader' style="position:absolute;"></div>
<div id="chartcontainer" class=cardcontainer>
<div id=chart></div>
</div>
</div>
</div>
</div>`;
$("body").prepend(modhtml);
$("body").on('click', '#distButton', function () {
var row = $(this).closest('tr');
console.log(row.text())
$('.modal-content').stop().animate({
scrollTop: 0
}, 500);
$(this).blur();
getCourseInfo(row)
});
function getCourseInfo(row) {
let rowdata = $(row).find('td').slice(3).toArray().map(x => $(x).text().trim());
let [uniquenum, department, coursenum, coursename, profname, notes, rawtime] = rowdata
let profinit = ""
if (profname !== undefined && profname != "Staff") {
profinit = profname.split(',')[1].trim();
profname = profname.split(',')[0].trim();
}
let times = rawtime.split('\n').map(x => x.trim());
var course_data = {
"unique": uniquenum,
"department": department,
"number": coursenum,
"name": coursename,
"prof_name": profname,
"initial": profinit,
"notes": notes,
"times": times,
}
curr_course = course_data;
getDistribution(course_data);
var modal = document.getElementById('myModal');
window.onclick = function (event) {
if (event.target == modal) {
close();
}
}
}
function badData(course_data, res) {
return typeof res == 'undefined' || course_data["prof_name"] == "Staff";
}
$("#semesters").on('change', function () {
var sem = $(this).val();
sem = sem == "Aggregate" ? undefined : sem;
getDistribution(curr_course, sem);
});
function showLoading(loading) {
if (loading) {
$('#loader').css('display', 'inline-block');
$("#chart").hide();
} else {
$('#loader').hide();
$("#chart").show();
}
}
function openDialog(course_data, res) {
$("#title").text(buildTitle(course_data))
$("#topbuttons").before(buildTimeTitle(course_data["times"]));
$("#profname").text(buildProfTitle(course_data));
$("#myModal").fadeIn(fadetime);
buildSemestersDropdown(course_data, res)
var data;
if (badData(course_data, res)) {
data = [];
} else {
data = res.values[0];
}
setChart(data);
}
function buildProfTitle(course_data) {
const {
initial,
prof_name
} = course_data;
return `with ${initial?initial+". ":""}${prof_name}`;
}
function buildSemestersDropdown(course_data, res) {
$("#semesters").empty();
if (badData(course_data, res)) {
$("#semesters").append("<option>No Data</option>")
} else {
var semesters = res.values[0][18].split(",");
semesters.sort(semesterSort);
semesters.reverse().unshift('Aggregate');
var sems = [];
for (var i = 0; i < semesters.length; i++) {
sems.push($(`<option value="${semesters[i]}">${semesters[i]}</option>`));
}
$("#semesters").append(sems);
}
}
/*Query the grades database*/
function getDistribution(course_data, sem) {
showLoading(true);
let query = buildQuery(course_data, sem);
chrome.runtime.sendMessage({
command: "gradesQuery",
query: query
}, function (response) {
var res = response.data;
if (!sem) {
openDialog(course_data, res);
} else {
var data = badData(course_data, res) ? [] : res.values[0];
setChart(data);
}
});
}
function buildTitle(course_data) {
return `${course_data["name"]} (${course_data["department"]} ${course_data["number"]})`
}
function buildTimeTitle(times) {
$("h2.dateTimePlace").remove();
var lines = []
for (var i = 0; i < times.length; i++) {
date = times[i].substring(0, times[i].indexOf(' ')).toUpperCase();
time = times[i].substring(times[i].indexOf(' ') + 1, times[i].lastIndexOf('-')).trim();
place = times[i].substring(times[i].lastIndexOf('-') + 1).trim();
lines.push($(`<h2 class="dateTimePlace">${makeLine(date, time, place)}</th>`));
}
return lines
}
function close() {
$("#myModal").fadeOut(fadetime);
}
function makeLine(date, time, place) {
var arr = seperateDays(date)
var output = prettifyDaysText(arr)
var building = place.substring(0, place.search(/\d/) - 1);
building = building == "" ? "Undecided Location" : building;
return `${output} at ${time.replace(/\./g, '').replace(/\-/g, ' to ')} in <a style='font-size:medium' target='_blank' href='https://maps.utexas.edu/buildings/UTM/${building}'>${building}</>`;
}
function seperateDays(date) {
let arr = [];
for (var i = 0; i < date.length; i++) {
let letter = date.charAt(i);
if (letter == "T" && i < date.length - 1 && date.charAt(i + 1) == "H") {
arr.push(days.get("TH"));
} else {
if (letter != "H") {
arr.push(days.get(letter));
}
}
}
return arr;
}
function prettifyDaysText(arr) {
var output = "";
if (arr.length > 2) {
for (var i = 0; i < arr.length; i++) {
if (i < arr.length - 1)
output += arr[i] + ", "
if (i == arr.length - 2)
output += "and ";
if (i == arr.length - 1)
output += arr[i];
}
} else if (arr.length == 2) {
output = arr[0] + " and " + arr[1];
} else {
output = arr[0];
}
return output
}
function setChart(data) {
//set up the chart
showLoading(false);
chart = Highcharts.chart('chart', buildChartConfig(data), function (chart) { // on complete
if (data.length == 0) {
//if no data, then show the message and hide the series
chart.renderer.text('Could not find data for this Instructor teaching this Course.', 100, 120)
.css({
fontSize: '20px',
width: '300px',
align: 'center',
left: '160px'
})
.add();
$.each(chart.series, function (i, ser) {
ser.hide();
});
}
});
}

View File

@@ -9,14 +9,21 @@
"declarativeContent",
"storage",
"*://*.utdirect.utexas.edu/apps/registrar/course_schedule/*",
"*://*.utexas.collegescheduler.com/*",
"*://*.catalog.utexas.edu/ribbit/",
"*://*.registrar.utexas.edu/schedules/*",
"*://*.login.utexas.edu/login/*"
],
"content_scripts": [{
"css": ["css/styles.css"],
"js": ["js/moment.min.js", "js/sql-memory-growth.js", "js/highcharts.js", "js/jquery-3.3.1.min.js", "js/content.js"],
"js": ["js/moment.min.js", "js/highcharts.js", "js/jquery-3.3.1.min.js", "js/jquery.initialize.min.js", "js/config.js", "js/util.js",
"js/content.js"
],
"matches": ["https://utdirect.utexas.edu/apps/registrar/course_schedule/*"]
}, {
"css": ["css/styles.css"],
"js": ["js/moment.min.js", "js/highcharts.js", "js/jquery-3.3.1.min.js", "js/jquery.initialize.min.js", "js/config.js", "js/util.js", "js/utplanner.js"],
"matches": ["https://utexas.collegescheduler.com/*"]
}, {
"css": ["css/styles.css"],
"js": ["js/moment.min.js", "js/sql-memory-growth.js", "js/highcharts.js", "js/jquery-3.3.1.min.js", "js/import.js"],
@@ -26,7 +33,7 @@
"grades.db", "images/disticon.png"
],
"background": {
"scripts": ["js/jquery-3.3.1.min.js", "js/background.js", "js/moment.min.js"],
"scripts": ["js/jquery-3.3.1.min.js", "js/sql-memory-growth.js", "js/background.js", "js/moment.min.js"],
"persistent": true
},
"browser_action": {