popup refactoring, bug fixes

This commit is contained in:
Sriram Hariharan
2019-08-12 23:31:30 -05:00
parent 893e882377
commit c3d243c471
10 changed files with 458 additions and 533 deletions

View File

@@ -246,17 +246,6 @@ input[type=number]::-webkit-outer-spin-button {
width: 120px; width: 120px;
} }
#import-export-popup {
background: white;
color: #747474;
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12);
position: absolute;
margin: auto;
bottom: 42px;
right: 10px;
border-radius: inherit;
width: 160px;
}
.flex-container { .flex-container {
display: flex; display: flex;
@@ -329,15 +318,30 @@ input[type=number]::-webkit-outer-spin-button {
margin: 8px 0px; margin: 8px 0px;
} }
#import-export-popup {
background: white;
color: #747474;
box-shadow: 0 2px 5px 0 rgba(0, 0, 0, 0.16), 0 2px 10px 0 rgba(0, 0, 0, 0.12);
position: absolute;
margin: auto;
bottom: 42px;
right: 10px;
border-radius: inherit;
width: 140px;
}
.simple-menu-option { .simple-menu-option {
display: inline-block; display: inline-block;
color: rgba(0, 0, 45, 0.48); color: rgba(0, 0, 45, 0.48);
border: none; border: none;
font-size: 17px; background-color: white;
font-size: 15px;
overflow: hidden; overflow: hidden;
vertical-align: middle; vertical-align: middle;
cursor: pointer;
text-align: left; text-align: left;
padding: 10px 0px 5px 5px; padding: 5px 0px 5px 5px;
border-radius: 7px; border-radius: 7px;
} }
@@ -350,10 +354,11 @@ input[type=number]::-webkit-outer-spin-button {
margin-bottom: 3px; margin-bottom: 3px;
} }
.simple-menu-option:hover { .simple-menu-option:hover {
background-color: rgba(177, 175, 175, 0.324); background-color: rgba(177, 175, 175, 0.200);
-webkit-transition-duration: 0.4s; /* Safari */
transition-duration: 0.4s; transition-duration: 0.4s;
color: #FF9800;
} }
.simple-menu-option:focus { .simple-menu-option:focus {

View File

@@ -52,15 +52,64 @@ class Template {
} }
static calendarLine(line) { static calendarLine(line) {
let {
days,
start_time,
end_time,
location_link,
location_full
} = line;
return `<p class='time' style='font-size:large;'> return `<p class='time' style='font-size:large;'>
<span style='display:inline-block;'>${line[0]}:</span> <span style='display:inline-block;'>${days}:</span>
<span style='margin-left:10px;display:inline-block;text-align:center;'>${line[1]} to ${line[2]}</span> <span style='margin-left:10px;display:inline-block;text-align:center;'>${start_time} to ${end_time}</span>
<span style='float:right;display:inline-block;text-align:right;width: 25%;'> <span style='float:right;display:inline-block;text-align:right;width: 25%;'>
<a target='_blank' style='color:#3c87a3;text-decoration:none;'href='${line[3]}'>${line[4]}</a> <a target='_blank' style='color:#3c87a3;text-decoration:none;'href='${location_link}'>${location_full}</a>
</span> </span>
</p>` </p>`
} }
static popupListItem(i, list_tile_color, unique, department, number, profname, list_sub_color, line) {
return `<li id='${i}'style='padding: 0px 5px 5px 5px; overflow-y: auto;max-height:400px;'>
<div class='card'>
<div class='container' style='background:${list_tile_color}'>
<button class='copybut' title='Copy Unique #' id='copybut' value='${unique}'>
<i style='color:white;float:left;text-shadow: 2px 2px 5px rgba(0, 0, 0, 0.16);font-size:x-large;' id='copyicon' class="material-icons copy">content_copy
</i>
</button>
<h4 class='truncate' style='color:white;margin:5px; display:inline-block;font-size:large;align-items:center;'>
<b>${department} ${number} <span style='font-size:medium'> with <span style='font-size:medium'>${profname} (${unique})</span></b>
</h4>
<p id='arrow' style='float:right;font-size:small;display:inline-block;margin-top:10px;color:white;font-family: sans-serif'>&#9658;</p>
</div>
</div>
<div id='moreInfo' style='display: none;'>
<p style='font-weight:bold;padding:10px;margin:0px 5px 0px 15px;font-size:small;background-color:${list_sub_color};'>${line}</p>
<div id='infoButtons' style='border-radius:0px;'>
<button class='matbut' id='listRemove'style='float:right;background:#F44336; margin:5px;'>Remove</button>
<button class='matbut' id='register' style='float:right;background:#4CAF50; margin:5px;'>Register</button>
<button class='matbut' id='listMoreInfo' style='float:right;background:#2196F3; margin:5px;'>More Info</button>
</div>
</div>
</li>`;
}
static popupLine(line) {
let {
days,
start_time,
end_time,
location_link,
location_full
} = line;
return `<span style='display:inline-block;width: 20%;'>${days}:</span>
<span style='margin-left:10px;display:inline-block;width: 50%;text-align:center;'>${start_time} to ${end_time}</span>
<span style='float:right;display:inline-block;text-align:right;width: 25%;'>
<a target='_blank' style='color:#3c87a3;text-decoration:none;'href='${location_link}'>${location_full}</a>
</span>
<br>`
}
static calendarModal() { static calendarModal() {
return `<div id="myModal" class="modal"> return `<div id="myModal" class="modal">
@@ -82,4 +131,10 @@ class Template {
</div> </div>
</div>` </div>`
} }
static popupConflictMessage(conflict_message) {
return `<p id='conflict' style='font-size:small; font-weight:bold; color:red; margin:5px 5px 5px 10px'>${conflict_message}</>`
}
} }

View File

@@ -80,17 +80,13 @@ function setRegisterButton(status, registerlink) {
$("#register").text("Register").css("background-color", Colors.open); $("#register").text("Register").css("background-color", Colors.open);
} }
function canNotRegister(status, registerlink) {
return status.includes("closed") || status.includes("cancelled") || !status || !registerlink
}
function buildTimeTitle(datetimearr) { function buildTimeTitle(datetimearr) {
$('#timelines').remove(); $('#timelines').remove();
var arr = convertDateTimeArrToLine(datetimearr) var arr = convertDateTimeArrToLine(datetimearr)
var output = ""; var output = "";
for (let i = 0; i < arr.length; i++) { for (let i = 0; i < arr.length; i++) {
output += Template.calendarLine(arr[i]); let line = arr[i];
output += Template.calendarLine(line);
} }
$("#header").after(`<div id='timelines'>${output}</div`); $("#header").after(`<div id='timelines'>${output}</div`);
} }
@@ -196,13 +192,7 @@ $("#clear").click(() => {
chrome.storage.sync.set({ chrome.storage.sync.set({
savedCourses: [] savedCourses: []
}); });
chrome.tabs.query({}, function (tabs) { updateAllTabsCourseList();
for (let i = 0; i < tabs.length; i++) {
chrome.tabs.sendMessage(tabs[i].id, {
command: "updateCourseList"
});
}
});
updateCalendar(); updateCalendar();
chrome.runtime.sendMessage({ chrome.runtime.sendMessage({
command: "updateBadge" command: "updateBadge"
@@ -219,13 +209,7 @@ $("#remove").click(() => {
}, function () { }, function () {
$("#myModal").fadeOut(calendar_fade_time); $("#myModal").fadeOut(calendar_fade_time);
updateCalendar(); updateCalendar();
chrome.tabs.query({}, function (tabs) { updateAllTabsCourseList();
for (let i = 0; i < tabs.length; i++) {
chrome.tabs.sendMessage(tabs[i].id, {
command: "updateCourseList"
});
}
});
}); });
}, button_delay); }, button_delay);
}); });

View File

@@ -15,6 +15,10 @@ class Colors {
static waitlisted = "#FF9800"; static waitlisted = "#FF9800";
static closed = "#FF5722"; static closed = "#FF5722";
static open_light = "#C8E6C9";
static waitlisted_light = "#FFE0B2";
static closed_light = "#FFCCBC";
static highlight_conflict = "#F44336"; static highlight_conflict = "#F44336";
static highlight_default = "#333333"; static highlight_default = "#333333";
static highlight_saved = "#4CAF50"; static highlight_saved = "#4CAF50";
@@ -32,4 +36,16 @@ class Export {
class Text { class Text {
static emptyText() {
let index = Math.floor(Math.random() * emptyText.length);
let arr = ["Doesn't Look Like Anything To Me.", "You Can't Fail Classes You're Not In.", "Pro-Tip: Don't Take O-Chem.",
"No Work Happens On PCL 5th Floor.", "Sophomore But Freshman By Credit.", "Pain is temporary, GPA is forever.",
"You've Yee'd Your Last Haw.", "lol everything is already waitlisted.", "At Least You're Not At A&M.",
`It's ${moment().format("h:mm")} and OU Still Sucks.`, 'TeXAs iS BaCK GuYZ', "'Academically Challenged'",
'Does McCombs teach Parseltongue?', 'Lets make Daddy Fenves proud.', 'Feel bad if you say Wampus.', 'No Cruce Enfrente Del Bus.',
'Midterm 1 has been Unmuted', 'Omae Wa Mou Shindeiru...', 'Bevo Bucks are the new Bitcoin'
]
return arr[index];
}
} }

View File

@@ -184,18 +184,17 @@ function updateListConflictHighlighting(start = 0) {
$('table').find('tr').each(function (i) { $('table').find('tr').each(function (i) {
if (i >= start) { if (i >= start) {
if (!($(this).find('td').hasClass("course_header")) && $(this).has('th').length == 0) { if (!($(this).find('td').hasClass("course_header")) && $(this).has('th').length == 0) {
var this_form = this;
var unique = $(this).find('td[data-th="Unique"]').text(); var unique = $(this).find('td[data-th="Unique"]').text();
chrome.runtime.sendMessage({ chrome.runtime.sendMessage({
command: "isSingleConflict", command: "isSingleConflict",
dtarr: getDayTimeArray(this), dtarr: getDayTimeArray(this),
unique: unique unique: unique
}, function (response) { }, (response) => {
let { let {
isConflict, isConflict,
alreadyContains alreadyContains
} = response } = response
updateTextHighlighting($(this_form).find('td'), canHighlight, isConflict, alreadyContains); updateTextHighlighting($(this).find('td'), canHighlight, isConflict, alreadyContains);
}); });
} }
} }

View File

@@ -30,13 +30,7 @@ $("#togglecourseConflictHighlight").click(function () {
off('courseConflictHighlight'); off('courseConflictHighlight');
}); });
} }
chrome.tabs.query({}, function (tabs) { updateAllTabsCourseList();
for (var i = 0; i < tabs.length; i++) {
chrome.tabs.sendMessage(tabs[i].id, {
command: "updateCourseList"
});
}
});
}); });

View File

@@ -1,99 +1,62 @@
var courses; var courses;
// get the courses from storage
setCourseList(); setCourseList();
// var modhtml = '<div class=modal id=myModal><div class=modal-content><span class=close>×</span><div class=card><div class=cardcontainer></div></div></div></div>';
// $("#html").prepend(modhtml);
getSemesters(); getSemesters();
var canremove = true; var can_remove = true;
function setCourseList() { function setCourseList() {
$("#courseList").empty() $("#courseList").empty()
chrome.storage.sync.get('savedCourses', function (data) { chrome.storage.sync.get('savedCourses', function (data) {
updateConflicts(); updateConflicts();
courses = data.savedCourses courses = data.savedCourses
console.log(courses.length); handleEmpty();
if (courses.length != 0) {
$("#empty").hide();
$("#courseList").show();
} else {
showEmpty();
}
// build and append the course list element // build and append the course list element
for (var i = 0; i < courses.length; i++) { for (var i = 0; i < courses.length; i++) {
var color; let {
var subcolor; coursename,
status = courses[i].status; unique,
if (status.includes("open")) { profname,
color = "#4CAF50"; status,
subcolor = "#C8E6C9"; datetimearr
} else if (status.includes("waitlisted")) { } = courses[i];
color = "#FF9800" profname = capitalizeString(profname);
subcolor = "#FFE0B2"; let line = buildTimeLines(datetimearr);
} else if (status.includes("closed") || status.includes("cancelled")) { let list_tile_color = getStatusColor(status)
color = "#FF5722"; let list_sub_color = getStatusColor(status, true);
subcolor = "#FFCCBC"; let {
} department,
var department = courses[i].coursename.substring(0, courses[i].coursename.search(/\d/) - 2); number
var course_nbr = courses[i].coursename.substring(courses[i].coursename.search(/\d/), courses[i].coursename.indexOf(" ", courses[i].coursename.search(/\d/))); } = seperateCourseNameParts(coursename)
var profname = prettifyName(courses[i].profname);
if (profname == "") { let list_html = Template.popupListItem(i, list_tile_color, unique, department, number, profname, list_sub_color, line);
profname = "Undecided Professor"; $("#courseList").append(list_html);
}
var listhtml = `<li id='${i}'style='padding: 0px 5px 5px 5px; overflow-y: auto;max-height:400px;'>
<div class='card'>
<div class='container' style='background:${color}'>
<button class='copybut' title='Copy Unique #' id='copybut' value='${courses[i].unique}'>
<i style='color:white;float:left;text-shadow: 2px 2px 5px rgba(0, 0, 0, 0.16);font-size:x-large;' id='copyicon' class="material-icons copy">content_copy
</i>
</button>
<h4 class='truncate' style='color:white;margin:5px; display:inline-block;font-size:large;align-items:center;'>
<b>${department} ${course_nbr} <span style='font-size:medium'> with <span style='font-size:medium'>${profname} (${courses[i].unique})</span></b>
</h4>
<p id='arrow' style='float:right;font-size:small;display:inline-block;margin-top:10px;color:white;font-family: sans-serif'>&#9658;</p>
</div>
</div>
<div id='moreInfo' style='display: none;'>
<p style='font-weight:bold;padding:10px;margin:0px 5px 0px 15px;font-size:small;background-color:${subcolor};'>${makeLine(i)}</p>
<div id='infoButtons' style='border-radius:0px;'>
<button class='matbut' id='listRemove'style='float:right;background:#F44336; margin:5px;'>Remove</button>
<button class='matbut' id='register' style='float:right;background:#4CAF50; margin:5px;'>Register</button>
<button class='matbut' id='listMoreInfo' style='float:right;background:#2196F3; margin:5px;'>More Info</button>
</div>
</div>
</li>`;
$("#courseList").append(listhtml);
} }
}); });
} }
function showEmpty() { /* convert from the dtarr and maek the time lines*/
var emptyText = ["Doesn't Look Like Anything To Me.", "You Can't Fail Classes You're Not In.", "Pro-Tip: Don't Take O-Chem.", function buildTimeLines(datetimearr) {
"No Work Happens On PCL 5th Floor.", "Sophomore But Freshman By Credit.", "Pain is temporary, GPA is forever.", let lines = convertDateTimeArrToLine(datetimearr);
"You've Yee'd Your Last Haw.", "lol everything is already waitlisted.", "At Least You're Not At A&M.", let output = "";
`It's ${moment().format("h:mm")} and OU Still Sucks.`, 'TeXAs iS BaCK GuYZ', "'Academically Challenged'", if (lines.length == 0) {
'Does McCombs teach Parseltongue?', 'Lets make Daddy Fenves proud.', 'Feel bad if you say Wampus.', 'No Cruce Enfrente Del Bus.', output = "<span style='font-size:medium;'>This class has no meeting times.</span>"
'Midterm 1 has been Unmuted', 'Omae Wa Mou Shindeiru...', 'Bevo Bucks are the new Bitcoin' } else {
] for (let i = 0; i < lines.length; i++) {
// console.log(emptyText.length); let line = lines[i];
$("#courseList").hide(); output += Template.popupLine(line)
$("#empty").fadeIn(200); }
$("#main").html(emptyText[Math.floor(Math.random() * emptyText.length)]); }
return output;
} }
/* prettify the name for the conflict messages*/ /* prettify the name for the conflict messages*/
function getSimpleName(coursename, unique) { function formatShortenedCourseName(course) {
var department = coursename.substring(0, coursename.search(/\d/) - 2); let {
var course_nbr = coursename.substring(coursename.search(/\d/), coursename.indexOf(" ", coursename.search(/\d/))); number,
return department + " " + course_nbr + " (" + unique + ")"; department
} } = seperateCourseNameParts(course.coursename)
return `${department} ${number} (${course.unique})`;
/* Format the Professor Name */
function prettifyName(profname) {
return profname.replace(/\w\S*/g, function (txt) {
return txt.charAt(0).toUpperCase() + txt.substr(1).toLowerCase();
});
} }
/* Update the conflict messages */ /* Update the conflict messages */
@@ -101,213 +64,203 @@ function updateConflicts() {
chrome.runtime.sendMessage({ chrome.runtime.sendMessage({
command: "checkConflicts" command: "checkConflicts"
}, function (response) { }, function (response) {
var isConflicted = [];
if (response.isConflict) { if (response.isConflict) {
var between = response.between; var between = response.between;
var text = ""; let conflict_message = "";
for (var i = 0; i < between.length; i++) { for (var i = 0; i < between.length; i++) {
text += "CONFLICT: " + getSimpleName(between[i][0].coursename, between[i][0].unique) + " and " + getSimpleName(between[i][1].coursename, between[i][1].unique); let courseA = between[i][0];
isConflicted.push(between[i][0].unique); let courseB = between[i][1];
isConflicted.push(between[i][1].unique); conflict_message += `CONFLICT: ${formatShortenedCourseName(courseA)} and ${formatShortenedCourseName(courseB)}`;
if (i != between.length - 1) { if (i != between.length - 1)
text += "<br>"; conflict_message += "<br>";
}
} }
$("<p id='conflict' style='font-size:small; font-weight:bold; color:red; margin:5px 5px 5px 10px'>" + text + "</>").prependTo("#courseList").hide().fadeIn(200); $(Template.popupConflictMessage(conflict_message)).prependTo("#courseList").hide().fadeIn(200);
} }
}); });
} }
/* Handle the button clicks */
$(document).ready(function () {
$("#courseList").on('mouseover', '.copybut', function () {
$(this).addClass('shadow');
}).on('mouseleave', '.copybut', function () {
$(this).removeClass('shadow');
});
$("#courseList").on('click', '.copybut', function (e) { function handleRegisterButton(clicked_item, curr_course) {
e.stopPropagation(); let {
var temp = $("<input>"); status,
$(this).find('i').text('check'); registerlink
$(this).stop(true, false).removeAttr('style').removeClass('shadow', { } = curr_course;
duration: 200 let register_button = $(clicked_item).find("#register");
}); let can_not_register = canNotRegister(status, registerlink);
$(this).find('i').delay(400).queue(function (n) {
$(this).text('content_copy'); let register_text = can_not_register ? "Can't Register" :
$(this).parent().removeClass('shadow'); status.includes("waitlisted") ? "Join Waitlist" : "Register";
if ($(this).parent().is(":hover")) { let register_color = can_not_register ? Colors.closed :
$(this).parent().addClass('shadow'); status.includes("waitlisted") ? Colors.waitlisted : Colors.open;
}
n(); $(register_button).text(register_text).css('background-color', register_color);
if (!can_not_register) {
$(register_button).click(function () {
setCurrentTabUrl(registerlink);
}) })
}
}
$("body").append(temp); function handleRemoveButton(clicked_item, curr_course) {
temp.val($(this).val()).select(); let list = $(clicked_item).closest("ul");
document.execCommand("copy"); $(clicked_item).find("#listRemove").click(function () {
temp.remove(); if (can_remove) {
}); can_remove = false;
$(list).find("#conflict").fadeOut(300, function () {
$("#courseList").on('click', 'li', function () { $(clicked_item).remove();
$(this).find("#listMoreInfo").click(function () { });
window.open(courses[$(this).closest("li").attr("id")].link); chrome.runtime.sendMessage({
}); command: "courseStorage",
let status = courses[$(this).closest("li").attr("id")].status; course: curr_course,
let registerlink = courses[$(this).closest("li").attr("id")].registerlink; action: "remove"
if (status.includes("closed") || status.includes("cancelled") || !status || !registerlink) { }, () => {
$(this).find("#register").text("Can't Register").css("background-color", "#FF5722"); $(clicked_item).fadeOut(200);
} else { if ($(list).children(':visible').length === 1)
if (status.includes("waitlisted")) { showEmpty();
$(this).find("#register").text("Join Waitlist").css("background-color", "#FF9800"); can_remove = true;
} else { updateConflicts();
$(this).find("#register").text("Register").css("background-color", "#4CAF50"); updateAllTabsCourseList();
} });
$(this).find("#register").click(function () {
chrome.tabs.query({
currentWindow: true,
active: true
}, function (tab) {
chrome.tabs.update(tab.id, {
url: registerlink
});
});
})
}
/* clear the conflict messages, then remove the course and updateConflicts. update the tabs*/
$(this).find("#listRemove").click(function () {
var thisForm = this;
if (canremove) {
canremove = false;
$(thisForm).closest("ul").find("#conflict").fadeOut(300, function () {
$(this).remove();
});
chrome.runtime.sendMessage({
command: "courseStorage",
course: courses[$(thisForm).closest("li").attr("id")],
action: "remove"
}, function (response) {
$(thisForm).closest("li").fadeOut(200);
if ($(thisForm).closest("ul").children(':visible').length === 1) {
showEmpty();
}
canremove = true;
console.log('computedconflicts');
updateConflicts();
chrome.tabs.query({}, function (tabs) {
for (var i = 0; i < tabs.length; i++) {
chrome.tabs.sendMessage(tabs[i].id, {
command: "updateCourseList"
});
}
});
});
}
});
/* Show the times popout and more info options*/
if ($(this).find("#moreInfo").is(":hidden")) {
$(this).find("#moreInfo").fadeIn(200);
$(this).find('#arrow').css('transform', 'rotate(90deg)');
} else {
$(this).find("#moreInfo").fadeOut(200);
$(this).find('#arrow').css('transform', '');
} }
}); });
}
$("#clear").click(function () { function handleMoreInfo(clicked_item, curr_course) {
clear(); $(clicked_item).find("#listMoreInfo").click(function () {
window.open(curr_course.link);
}); });
}
$("#schedule").click(function () { function copyButtonAnimation() {
chrome.tabs.create({ $(this).find('i').text('check');
'url': 'https://registrar.utexas.edu/schedules' $(this).stop(true, false).removeAttr('style').removeClass('shadow', {
}); duration: 200
}); });
$(this).find('i').delay(400).queue(function (n) {
$("#impexp").click(function () { $(this).text('content_copy');
// Close import export window $(this).parent().removeClass('shadow');
if ($("#impexp>i").text() == 'close') { if ($(this).parent().is(":hover")) {
hideImportExportPopup(); $(this).parent().addClass('shadow');
// $(this).removeClass('selected');
} else {
// Open import export window
// If search window open, close it first to prevent overlap
if ($("#search>i").text() == 'close') {
hideSearchPopup();
}
showImportExportPopup();
// $(this).addClass('selected');
} }
}); n();
})
}
$("#search").click(function () {
// Close search window function toggleTimeDropdown(clicked_item) {
let more_info_button = $(clicked_item).find('#moreInfo');
let arrow = $('clicked_item').find("#arrow");
if ($(more_info_button).is(":hidden")) {
$(more_info_button).fadeIn(200);
$(arrow).css('transform', 'rotate(90deg)');
} else {
$(more_info_button).fadeOut(200);
$(arrow).css('transform', '');
}
}
$("#courseList").on('mouseover', '.copybut', function () {
$(this).addClass('shadow');
}).on('mouseleave', '.copybut', function () {
$(this).removeClass('shadow');
});
$("#courseList").on('click', '.copybut', function (e) {
e.stopPropagation();
var temp = $("<input>");
copyButtonAnimation();
$("body").append(temp);
temp.val($(this).val()).select();
document.execCommand("copy");
temp.remove();
});
$("#courseList").on('click', 'li', function () {
let clicked_item = $(this).closest('li');
let curr_course = courses[$(clicked_item).attr("id")];
handleMoreInfo(clicked_item, curr_course);
handleRegisterButton(clicked_item, curr_course)
handleRemoveButton(clicked_item, curr_course)
toggleTimeDropdown(clicked_item);
});
$("#clear").click(function () {
clear();
});
$("#schedule").click(function () {
chrome.tabs.create({
'url': 'https://registrar.utexas.edu/schedules'
});
});
$("#impexp").click(function () {
if ($("#impexp>i").text() == 'close') {
hideImportExportPopup();
} else {
if ($("#search>i").text() == 'close') { if ($("#search>i").text() == 'close') {
hideSearchPopup(); hideSearchPopup();
// $(this).removeClass('selected'); }
showImportExportPopup();
}
});
$("#search").click(function () {
if ($("#search>i").text() == 'close') {
hideSearchPopup();
} else {
if ($("#impexp>i").text() == 'close') {
hideImportExportPopup();
}
showSearchPopup();
}
});
$('#import-class').click(function () {
$("#importOrig").click();
});
$('#export-class').click(function () {
chrome.storage.sync.get('savedCourses', function (data) {
if (data.savedCourses.length > 0) {
var exportlink = document.createElement('a');
var url = window.URL.createObjectURL(new Blob([JSON.stringify(data.savedCourses, null, 4)], {
type: "octet/stream"
}));
exportlink.setAttribute('href', url);
exportlink.setAttribute('download', 'my_courses.json');
exportlink.click();
} else { } else {
// Open search window alert('No Saved Courses to Export.');
// If import export window open, close it first to prevent overlap
if ($("#impexp>i").text() == 'close') {
hideImportExportPopup();
}
showSearchPopup();
// $(this).addClass('selected');
} }
}); });
});
$('#import-class').click(function () { $("#search-class").click(() => {
$("#importOrig").click(); var unique_id = $("#class_id_input").val();
}); if (!isNaN(unique_id)) {
if (unique_id.length == 5) {
$('#export-class').click(function () { let selected_semester = $("#semesters").find(":selected").val();
chrome.storage.sync.get('savedCourses', function (data) { openCoursePage(selected_semester, unique_id);
if (data.savedCourses.length > 0) { $("#class_id_input").val('');
var exportlink = document.createElement('a'); return;
var url = window.URL.createObjectURL(new Blob([JSON.stringify(data.savedCourses, null, 4)], {
type: "octet/stream"
}));
exportlink.setAttribute('href', url);
exportlink.setAttribute('download', 'my_courses.json');
exportlink.click();
} else {
alert('No Saved Courses to Export.');
}
});
});
$("#search-class").click(() => {
var uniqueId = $("#class_id_input").val();
if (!isNaN(uniqueId)) {
if (uniqueId.length == 5) {
let selectedSemester = $("#semesters").find(":selected").val();
openCoursePage(selectedSemester, uniqueId);
$("#class_id_input").val('');
return;
}
} }
alert("Oops, check your input. Class IDs should have 5 digits!"); }
}); alert("Oops, check your input. Class IDs should have 5 digits!");
});
$("#open").click(function () { $("#options_button").click(function () {
chrome.tabs.create({ chrome.tabs.create({
'url': "options.html" 'url': "options.html"
});
}); });
});
$("#calendar").click(function () { $("#calendar").click(function () {
chrome.tabs.create({ chrome.tabs.create({
'url': "calendar.html" 'url': "calendar.html"
});
}); });
}); });
$("#importOrig").change(function (e) { $("#importOrig").change(function (e) {
@@ -315,124 +268,50 @@ $("#importOrig").change(function (e) {
var reader = new FileReader(); var reader = new FileReader();
reader.onload = function () { reader.onload = function () {
try { try {
var impCourses = JSON.parse(this.result); var imported_courses = JSON.parse(this.result);
console.log(impCourses); if (imported_courses && imported_courses.length && (imported_courses.length == 0 || validateObject(imported_courses))) {
if (impCourses && impCourses.length && (impCourses.length == 0 || validateObject(impCourses))) {
chrome.storage.sync.set({ chrome.storage.sync.set({
savedCourses: impCourses savedCourses: imported_courses
}); });
chrome.runtime.sendMessage({ chrome.runtime.sendMessage({
command: "updateBadge" command: "updateBadge"
}); });
chrome.tabs.query({}, function (tabs) { updateAllTabsCourseList();
for (var i = 0; i < tabs.length; i++) {
chrome.tabs.sendMessage(tabs[i].id, {
command: "updateCourseList"
});
}
});
setCourseList(); setCourseList();
chrome.runtime.sendMessage({ chrome.runtime.sendMessage({
command: "updateStatus", command: "updateStatus",
}); });
} }
} catch (err) { } catch (err) {
console.log(err);
} }
importOrig.value = ''; importOrig.value = '';
} }
reader.readAsText(files[0]); reader.readAsText(files[0]);
}); });
function validateObject(impCourses) { function validateObject(imported_courses) {
for (var i = 0; i < impCourses.length; i++) { for (var i = 0; i < imported_courses.length; i++) {
var course = impCourses[i]; var course = imported_courses[i];
var isValid = true; var is_valid = true;
var props = ["coursename", "datetimearr", "link", "profname", "status", "unique"]; var props = ["coursename", "datetimearr", "link", "profname", "status", "unique"];
console.log(course.coursename);
for (let j = 0; j < props.length; j++) { for (let j = 0; j < props.length; j++) {
isValid &= course.hasOwnProperty(props[j]); is_valid &= course.hasOwnProperty(props[j]);
} }
console.log(isValid); if (!is_valid) {
if (!isValid) {
return false; return false;
} }
} }
return true; return true;
} }
/* convert from the dtarr and maek the time lines*/
function makeLine(index) {
var datetimearr = courses[index].datetimearr;
//converted times back
var dtmap = new Map([]);
for (var i = 0; i < datetimearr.length; i++) {
datetimearr[i][1][0] = moment(datetimearr[i][1][0], ["HH:mm"]).format("h:mm a");
datetimearr[i][1][1] = moment(datetimearr[i][1][1], ["HH:mm"]).format("h:mm a");
}
for (var i = 0; i < datetimearr.length; i++) {
if (dtmap.has(String(datetimearr[i][1]))) {
dtmap.set(String(datetimearr[i][1]), dtmap.get(String(datetimearr[i][1])) + datetimearr[i][0]);
} else {
dtmap.set(String(datetimearr[i][1]), datetimearr[i][0]);
}
}
var output = "";
var timearr = Array.from(dtmap.keys());
var dayarr = Array.from(dtmap.values());
if (timearr.length == 0) {
output = "<span style='font-size:medium;'>This class has no meeting times.</span>"
} else {
for (var i = 0; i < dayarr.length; i++) {
var place = findLoc(dayarr[i], timearr[i], datetimearr);
var building = place.substring(0, place.search(/\d/) - 1);
if (building == "") {
building = "Undecided Location";
}
output += `<span style='display:inline-block;width: 20%;'>${dayarr[i]}:</span><span style='margin-left:10px;display:inline-block;width: 50%;text-align:center;'>${timearr[i].split(",")[0]} to ${timearr[i].split(",")[1]}</span><span style='float:right;display:inline-block;text-align:right;width: 25%;'><a target='_blank' style='color:#3c87a3;text-decoration:none;'href='https://maps.utexas.edu/buildings/UTM/${building}'>${place}</a></span><br>`;
}
}
return output;
}
//find the location of a class given its days and timearrs.
function findLoc(day, timearr, datetimearr) {
for (let i = 0; i < datetimearr.length; i++) {
var dtl = datetimearr[i];
// console.log(dtl[1]);
// console.log(timearr);
if (day.includes(dtl[0])) {
if (JSON.stringify(timearr) == JSON.stringify(fixDtl1(dtl[1]))) {
return dtl[2];
}
}
}
}
function fixDtl1(dtl1) {
let output = "";
for (let i = 0; i < dtl1.length; i++) {
output += dtl1[i];
if (i != dtl1.length - 1) {
output += ",";
}
}
return output;
}
/*Clear the list and the storage of courses*/ /*Clear the list and the storage of courses*/
function clear() { function clear() {
chrome.storage.sync.set({ chrome.storage.sync.set({
savedCourses: [] savedCourses: []
}); });
chrome.tabs.query({}, function (tabs) { updateAllTabsCourseList();
for (var i = 0; i < tabs.length; i++) {
chrome.tabs.sendMessage(tabs[i].id, {
command: "updateCourseList"
});
}
});
chrome.runtime.sendMessage({ chrome.runtime.sendMessage({
command: "updateBadge" command: "updateBadge"
}); });
@@ -442,8 +321,8 @@ function clear() {
} }
function getSemesters() { function getSemesters() {
var schedulelist = 'https://registrar.utexas.edu/schedules'; var schedule_list = 'https://registrar.utexas.edu/schedules';
$.get(schedulelist, function (response) { $.get(schedule_list, function (response) {
if (response) { if (response) {
var object = $('<div/>').html(response).contents(); var object = $('<div/>').html(response).contents();
object.find('.callout2>ul>li>a').each(function (index) { object.find('.callout2>ul>li>a').each(function (index) {
@@ -451,9 +330,9 @@ function getSemesters() {
if ($(this).text() != "Course Schedule Archive") { if ($(this).text() != "Course Schedule Archive") {
const semester = $(this).text().split(" ")[0]; const semester = $(this).text().split(" ")[0];
const year = $(this).text().split(" ")[1] const year = $(this).text().split(" ")[1]
let semname = semester + " " + year; let sem_name = semester + " " + year;
console.log('semname:::: ' + semname); console.log('semname:::: ' + sem_name);
$("#semesters").append(`<option>${semname}</option>`); $("#semesters").append(`<option>${sem_name}</option>`);
$.get($(this).attr('href'), function (response) { $.get($(this).attr('href'), function (response) {
if (response) { if (response) {
var object = $('<div/>').html(response).contents(); var object = $('<div/>').html(response).contents();
@@ -465,12 +344,12 @@ function getSemesters() {
console.log('name:::: ' + name); console.log('name:::: ' + name);
object.find('.gobutton>a').each(function () { object.find('.gobutton>a').each(function () {
var semnum = $(this).attr('href').substring($(this).attr('href').lastIndexOf('/') + 1); var sem_num = $(this).attr('href').substring($(this).attr('href').lastIndexOf('/') + 1);
console.log('semnum:::: ' + semnum); console.log('semnum:::: ' + sem_num);
$("option").each(function () { $("option").each(function () {
console.log($(this).text()); console.log($(this).text());
if ($(this).text() == name) { if ($(this).text() == name) {
$(this).val(semnum); $(this).val(sem_num);
console.log($(this).val()); console.log($(this).val());
} }
}) })
@@ -484,67 +363,24 @@ function getSemesters() {
}); });
} }
/*Course object for passing to background*/
function Course(coursename, unique, profname, datetimearr, status, link, registerlink) {
this.coursename = coursename;
this.unique = unique;
this.profname = profname;
this.datetimearr = datetimearr;
this.status = status;
this.link = link;
this.registerlink = registerlink;
}
function openCoursePage(sem, unique) { function openCoursePage(sem, unique) {
var link = `https://utdirect.utexas.edu/apps/registrar/course_schedule/${sem}/${unique}/`; var link = `https://utdirect.utexas.edu/apps/registrar/course_schedule/${sem}/${unique}/`;
window.open(link); window.open(link);
} }
/*For a row, get all the course information and add the date-time-lines*/ function handleEmpty() {
function getCourseObject(object, link) { if (courses.length != 0) {
let coursename = object.find("#details h2").text(); $("#empty").hide();
let uniquenum = object.find('td[data-th="Unique"]').text(); $("#courseList").show();
let profname = object.find("td[data-th='Instructor']").text().split(', ')[0]; } else {
if (profname.indexOf(" ") == 0) { showEmpty();
profname = profname.substring(1);
} }
let datetimearr = getDtarr(object);
let status = object.find('td[data-th="Status"]').text();
let indlink = link;
let registerlink = object.find('td[data-th="Add"] a').prop('href');
return new Course(coursename, uniquenum, profname, datetimearr, status, indlink, registerlink);
} }
/* For a row, get the date-time-array for checking conflicts*/ function showEmpty() {
function getDtarr(object) { $("#courseList").hide();
var numlines = object.find('td[data-th="Days"]>span').length; $("#empty").fadeIn(200);
var dtarr = []; $("#main").html(Text.emptyText());
for (var i = 0; i < numlines; i++) {
var date = object.find('td[data-th="Days"]>span:eq(' + i + ')').text();
var time = object.find('td[data-th="Hour"]>span:eq(' + i + ')').text();
var place = object.find('td[data-th="Room"]>span:eq(' + i + ')').text();
for (var j = 0; j < date.length; j++) {
var letter = date.charAt(j);
var day = "";
if (letter == "T" && j < date.length - 1 && date.charAt(j + 1) == "H") {
dtarr.push(["TH", convertTime(time), place]);
} else {
if (letter != "H") {
dtarr.push([letter, convertTime(time), place]);
}
}
}
}
return dtarr;
}
/* Convert time to 24hour format */
function convertTime(time) {
var converted = time.replace(/\./g, '').split("-");
for (var i = 0; i < 2; i++) {
converted[i] = moment(converted[i], ["h:mm A"]).format("HH:mm");
}
return converted;
} }
function hideSearchPopup() { function hideSearchPopup() {

View File

@@ -6,14 +6,14 @@ const days = new Map([
["F", "Friday"] ["F", "Friday"]
]); ]);
function getStatusColor(status) { function getStatusColor(status, sub = false) {
let color = "black"; let color = "black";
if (status.includes("open")) { if (status.includes("open")) {
color = Colors.open; color = sub ? Colors.open_light : Colors.open;
} else if (status.includes("waitlisted")) { } else if (status.includes("waitlisted")) {
color = Colors.waitlisted; color = sub ? Colors.waitlisted_light : Colors.waitlisted;
} else if (status.includes("closed") || status.includes("cancelled")) { } else if (status.includes("closed") || status.includes("cancelled")) {
color = Colors.closed; color = sub ? Colors.closed_light : Colors.closed;
} }
return color; return color;
} }
@@ -98,6 +98,42 @@ function prettifyDaysText(arr) {
return output return output
} }
function seperateCourseNameParts(name) {
let num_index = name.search(/\d/);
department = name.substring(0, num_index).trim();
number = name.substring(num_index, name.indexOf(" ", num_index)).trim();
name = capitalizeString(name.substring(name.indexOf(" ", num_index)).trim());
return {
name: name,
department: department,
number: number
}
}
function updateAllTabsCourseList() {
chrome.tabs.query({}, function (tabs) {
for (var i = 0; i < tabs.length; i++) {
chrome.tabs.sendMessage(tabs[i].id, {
command: "updateCourseList"
});
}
});
}
function setCurrentTabUrl(link) {
chrome.tabs.query({
currentWindow: true,
active: true
}, function (tab) {
chrome.tabs.update(tab.id, {
url: link
});
});
}
function semesterSort(semA, semB) { function semesterSort(semA, semB) {
let semOrder = { let semOrder = {
@@ -121,6 +157,77 @@ function semesterSort(semA, semB) {
return 0; return 0;
} }
/* convert from the dtarr and maek the time lines*/
function convertDateTimeArrToLine(datetimearr) {
var output = [];
console.log(datetimearr)
var dtmap = makeDateTimeMap(datetimearr);
var timearr = Array.from(dtmap.keys());
var dayarr = Array.from(dtmap.values());
console.log(timearr);
console.log(dayarr);
for (var i = 0; i < dayarr.length; i++) {
var place = findLocation(dayarr[i], timearr[i], datetimearr);
var building = place.substring(0, place.search(/\d/)).trim();
building = building ? building : "Undecided Location"
output.push({
"days": dayarr[i],
"start_time": timearr[i].split(",")[0],
"end_time": timearr[i].split(',')[1],
"location_link": `https://maps.utexas.edu/buildings/UTM/${building}`,
"location_full": place
})
}
return output;
}
function makeDateTimeMap(datetimearr) {
var dtmap = new Map([]);
for (var i = 0; i < datetimearr.length; i++) {
datetimearr[i][1][0] = moment(datetimearr[i][1][0], ["HH:mm A"]).format("h:mm A");
datetimearr[i][1][1] = moment(datetimearr[i][1][1], ["HH:mm A"]).format("h:mm A");
}
for (var i = 0; i < datetimearr.length; i++) {
if (dtmap.has(String(datetimearr[i][1]))) {
dtmap.set(String(datetimearr[i][1]), dtmap.get(String(datetimearr[i][1])) + datetimearr[i][0]);
} else {
dtmap.set(String(datetimearr[i][1]), datetimearr[i][0]);
}
}
return dtmap
}
//find the location of a class given its days and timearrs.
function findLocation(day, timearr, datetimearr) {
for (let i = 0; i < datetimearr.length; i++) {
var dtl = datetimearr[i];
if (day.includes(dtl[0])) {
if (JSON.stringify(timearr) == JSON.stringify(reformatDateTime(dtl[1]))) {
return dtl[2];
}
}
}
}
function reformatDateTime(dtl1) {
let output = "";
for (let i = 0; i < dtl1.length; i++) {
output += dtl1[i];
if (i != dtl1.length - 1) {
output += ",";
}
}
return output;
}
function rgb2hex(rgb) {
rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
function hex(x) {
return ("0" + parseInt(x).toString(16)).slice(-2);
}
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
}
function buildChartConfig(data) { function buildChartConfig(data) {
return { return {
chart: { chart: {
@@ -230,81 +337,6 @@ function buildChartConfig(data) {
} }
} }
function seperateCourseNameParts(name) { function canNotRegister(status, register_link) {
let num_index = name.search(/\d/); return status.includes("closed") || status.includes("cancelled") || !status || !register_link
department = name.substring(0, num_index).trim();
number = name.substring(num_index, name.indexOf(" ", num_index)).trim();
name = capitalizeString(name.substring(name.indexOf(" ", num_index)).trim());
return {
name: name,
department: department,
number: number
}
}
/* convert from the dtarr and maek the time lines*/
function convertDateTimeArrToLine(datetimearr) {
var output = [];
var dtmap = makeDateTimeApp(datetimearr);
var timearr = Array.from(dtmap.keys());
var dayarr = Array.from(dtmap.values());
for (var i = 0; i < dayarr.length; i++) {
var place = findLocation(dayarr[i], timearr[i], datetimearr);
var building = place.substring(0, place.search(/\d/) - 1);
if (building == "") {
building = "Undecided Location";
}
output.push([dayarr[i], timearr[i].split(",")[0], timearr[i].split(",")[1], 'https://maps.utexas.edu/buildings/UTM/' + building, place]);
}
return output;
}
function makeDateTimeApp(datetimearr) {
var dtmap = new Map([]);
for (var i = 0; i < datetimearr.length; i++) {
//console.log(datetimearr[i][1][0]);
datetimearr[i][1][0] = moment(datetimearr[i][1][0], ["HH:mm A"]).format("h:mm A");
datetimearr[i][1][1] = moment(datetimearr[i][1][1], ["HH:mm A"]).format("h:mm A");
}
for (var i = 0; i < datetimearr.length; i++) {
if (dtmap.has(String(datetimearr[i][1]))) {
dtmap.set(String(datetimearr[i][1]), dtmap.get(String(datetimearr[i][1])) + datetimearr[i][0]);
} else {
dtmap.set(String(datetimearr[i][1]), datetimearr[i][0]);
}
}
return dtmap
}
//find the location of a class given its days and timearrs.
function findLocation(day, timearr, datetimearr) {
for (let i = 0; i < datetimearr.length; i++) {
var dtl = datetimearr[i];
// console.log(dtl[1]);
// console.log(timearr);
if (day.includes(dtl[0])) {
if (JSON.stringify(timearr) == JSON.stringify(reformatDateTime(dtl[1]))) {
return dtl[2];
}
}
}
}
function reformatDateTime(dtl1) {
let output = "";
for (let i = 0; i < dtl1.length; i++) {
output += dtl1[i];
if (i != dtl1.length - 1) {
output += ",";
}
}
return output;
}
function rgb2hex(rgb) {
rgb = rgb.match(/^rgb\((\d+),\s*(\d+),\s*(\d+)\)$/);
function hex(x) {
return ("0" + parseInt(x).toString(16)).slice(-2);
}
return "#" + hex(rgb[1]) + hex(rgb[2]) + hex(rgb[3]);
} }

View File

@@ -22,9 +22,10 @@
Off</button> Off</button>
</div> </div>
<p style="padding:0px 5px 5px 0px; float: right">(v<span id="version"></span>), Sriram Hariharan, 2018<p> <p style="padding:0px 5px 5px 0px; float: right">(v<span id="version"></span>), Sriram Hariharan, 2018</p>
<script src="js/lib/jquery-3.3.1.min.js"></script> <script src="js/lib/jquery-3.3.1.min.js"></script>
<script src="js/options.js"></script> <script src="js/util.js"></script>
<script src="js/options.js"></script>
</body> </body>
</html> </html>

View File

@@ -74,7 +74,7 @@
</div> </div>
</div> </div>
<button title='Options' style="background-color:white; margin-right: 0px;" class="settingsbut" id='open'> <button title='Options' style="background-color:white; margin-right: 0px;" class="settingsbut" id='options_button'>
<i style='color:#FF9800' class="material-icons"> <i style='color:#FF9800' class="material-icons">
settings settings
</i></button> </i></button>
@@ -83,6 +83,9 @@
<script src="js/lib/jquery-3.3.1.min.js"></script> <script src="js/lib/jquery-3.3.1.min.js"></script>
<script src="js/lib/moment.min.js"></script> <script src="js/lib/moment.min.js"></script>
<script src="js/Template.js"></script>
<script src="js/config.js"></script>
<script src="js/util.js"></script>
<script src="js/popup.js"></script> <script src="js/popup.js"></script>
</body> </body>