diff --git a/calendar.html b/calendar.html index 6e3cfbd4..7b767804 100644 --- a/calendar.html +++ b/calendar.html @@ -37,6 +37,6 @@ - + \ No newline at end of file diff --git a/css/popup.css b/css/popup.css index abd6d89b..ded50742 100644 --- a/css/popup.css +++ b/css/popup.css @@ -341,7 +341,7 @@ input[type=number]::-webkit-outer-spin-button { vertical-align: middle; cursor: pointer; text-align: left; - padding: 5px 0px 5px 5px; + padding: 10px 0px 5px 5px; border-radius: 7px; } diff --git a/js/background.js b/js/background.js index a0da10b0..6cb33401 100644 --- a/js/background.js +++ b/js/background.js @@ -89,6 +89,16 @@ chrome.runtime.onInstalled.addListener(function (details) { }); +chrome.storage.onChanged.addListener(function (changes) { + for (key in changes) { + console.log(changes); + if (key === 'savedCourses') { + updateBadge(false, changes.savedCourses.newValue); + } + } +}); + + function executeQuery(query, sendResponse) { console.log(grades) var res = grades.exec(query)[0]; @@ -97,7 +107,6 @@ function executeQuery(query, sendResponse) { }); } - /* Load the database*/ function loadDataBase() { sql = window.SQL; @@ -120,31 +129,34 @@ function loadBinaryFile(path, success) { xhr.send(); }; -function updateBadge(first) { - chrome.storage.sync.get('savedCourses', function (data) { - if (data.savedCourses) { - let text = ""; - if (data.savedCourses.length > 0) { - text += data.savedCourses.length - } - chrome.browserAction.setBadgeText({ - text: text - }); - let timeout = 0; - if (!first) { - chrome.browserAction.setBadgeBackgroundColor({ - color: '#FF5722' - }); - timeout = 200; - } - setTimeout(function () { - chrome.browserAction.setBadgeBackgroundColor({ - color: '#bf5700' - }); - }, timeout); +function updateBadge(first, new_changes) { + if (new_changes) { + updateBadgeText(first, new_changes); + } else { + chrome.storage.sync.get('savedCourses', function (data) { + let courses = data.savedCourses; + updateBadgeText(first, courses); + }); + } +} - } + +function updateBadgeText(first, courses) { + let badge_text = courses.length > 0 ? `${courses.length}` : ""; + let flash_time = !first ? 200 : 0; + chrome.browserAction.setBadgeText({ + text: badge_text }); + if (!first) { + chrome.browserAction.setBadgeBackgroundColor({ + color: Colors.badge_flash + }); + } + setTimeout(function () { + chrome.browserAction.setBadgeBackgroundColor({ + color: Colors.badge_default + }); + }, flash_time); } /* Find all the conflicts in the courses and send them out/ if there is even a conflict*/ @@ -229,7 +241,6 @@ function add(request, sender, sendResponse) { savedCourses: courses }); } - updateBadge(); sendResponse({ done: "Added: (" + request.course.unique + ") " + request.course.coursename, label: "Remove Course -" @@ -249,7 +260,6 @@ function remove(request, sender, sendResponse) { chrome.storage.sync.set({ savedCourses: courses }); - updateBadge(); sendResponse({ done: "Removed: (" + request.course.unique + ") " + request.course.coursename, label: "Add Course +" @@ -291,6 +301,8 @@ function updateTabs() { const UPDATE_INTERVAL = 1000 * 60 * 16; setInterval(updateStatus, UPDATE_INTERVAL); // updateStatus(); + + function updateStatus(sendResponse) { chrome.storage.sync.get('savedCourses', function (data) { var courses = data.savedCourses; diff --git a/js/calendar.js b/js/calendar.js index 48bf26d8..3a48a71a 100644 --- a/js/calendar.js +++ b/js/calendar.js @@ -194,9 +194,6 @@ $("#clear").click(() => { }); updateAllTabsCourseList(); updateCalendar(); - chrome.runtime.sendMessage({ - command: "updateBadge" - }); }); diff --git a/js/config.js b/js/config.js index 475dd0ca..0e054022 100644 --- a/js/config.js +++ b/js/config.js @@ -22,6 +22,9 @@ class Colors { static highlight_conflict = "#F44336"; static highlight_default = "#333333"; static highlight_saved = "#4CAF50"; + + static badge_flash = "#FF5722"; + static badge_default = "#bf5700"; } class Export { @@ -33,12 +36,13 @@ class Export { } } +class Popup { + static num_semesters = 2; +} + 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.", @@ -46,6 +50,8 @@ class Text { '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' ] + let index = Math.floor(Math.random() * arr.length); + return arr[index]; } } \ No newline at end of file diff --git a/js/courseCatalog.js b/js/courseCatalog.js index ce69248d..dffaca3f 100644 --- a/js/courseCatalog.js +++ b/js/courseCatalog.js @@ -413,8 +413,7 @@ function getDescription(course_info) { url: course_info["individual"], success: function (response) { if (response) { - response_node = $('
').html(response).contents(); - description_lines = response_node.find('#details > p').toArray().map(x => $(x).text()); + description_lines = htmlToNode(response).find('#details > p').toArray().map(x => $(x).text()); displayDescription(buildFormattedDescription(description_lines)); let first_name = extractFirstName(response_node); updateLinks(course_info, first_name); @@ -433,7 +432,7 @@ function loadNextPages() { toggleLoadingPage(true); $.get(link, function (response) { if (response) { - var next_page = $('').html(response).contents(); + var next_page = htmlToNode(response); var current = $('tbody'); var old_length = $('tbody tr').length; var last = current.find('.course_header>h2:last').text(); diff --git a/js/popup.js b/js/popup.js index 026b5418..7be9fa52 100644 --- a/js/popup.js +++ b/js/popup.js @@ -50,15 +50,6 @@ function buildTimeLines(datetimearr) { return output; } -/* prettify the name for the conflict messages*/ -function formatShortenedCourseName(course) { - let { - number, - department - } = seperateCourseNameParts(course.coursename) - return `${department} ${number} (${course.unique})`; -} - /* Update the conflict messages */ function updateConflicts() { chrome.runtime.sendMessage({ @@ -79,9 +70,177 @@ function updateConflicts() { }); } +/* prettify the name for the conflict messages*/ +function formatShortenedCourseName(course) { + let { + number, + department + } = seperateCourseNameParts(course.coursename) + return `${department} ${number} (${course.unique})`; +} -function handleRegisterButton(clicked_item, curr_course) { +$("#clear").click(function () { + chrome.storage.sync.set({ + savedCourses: [] + }); + updateAllTabsCourseList(); + $("#courseList").empty() + showEmpty(); +}); + +$("#schedule").click(function () { + chrome.tabs.create({ + 'url': 'https://registrar.utexas.edu/schedules' + }); +}); + +$("#calendar").click(function () { + chrome.tabs.create({ + 'url': "calendar.html" + }); +}); + + +$("#impexp").click(function () { + if ($("#impexp>i").text() == 'close') { + hideImportExportPopup(); + } else { + if ($("#search>i").text() == 'close') { + hideSearchPopup(); + } + showImportExportPopup(); + } +}); + +$("#search").click(function () { + if ($("#search>i").text() == 'close') { + hideSearchPopup(); + } else { + if ($("#impexp>i").text() == 'close') { + hideImportExportPopup(); + } + showSearchPopup(); + } +}); + +$('#import-class').click(function () { + $("#import_input").click(); +}); + +function isImportedValid(imported_courses) { + return imported_courses && imported_courses.length && (imported_courses.length == 0 || validateCourses(imported_courses)) +} + +$("#import_input").change(function (e) { + var files = e.target.files; + var reader = new FileReader(); + reader.onload = function () { + try { + var imported_courses = JSON.parse(this.result); + if (isImportedValid(imported_courses)) { + chrome.storage.sync.set({ + savedCourses: imported_courses + }); + updateAllTabsCourseList(); + setCourseList(); + hideImportExportPopup(); + } else { + Alert('There was an error.'); + } + } catch (err) { + console.log(err); + } + } + reader.readAsText(files[0]); +}); + + +function exportCourses(url) { + var exportlink = document.createElement('a'); + exportlink.setAttribute('href', url); + exportlink.setAttribute('download', 'my_courses.json'); + exportlink.click(); +} + +function createBlob(export_courses) { + return new Blob([JSON.stringify(export_courses, null, 4)], { + type: "octet/stream" + }) +} + +$('#export-class').click(function () { + chrome.storage.sync.get('savedCourses', function (data) { + let export_courses = data.savedCourses; + if (export_courses.length > 0) { + let url = window.URL.createObjectURL(createBlob(export_courses)); + exportCourses(url); + } else { + alert('No Saved Courses to Export.'); + } + hideImportExportPopup(); + }); +}); + + +function openCoursePage(sem, unique) { + var link = `https://utdirect.utexas.edu/apps/registrar/course_schedule/${sem}/${unique}/`; + window.open(link); +} + +$("#search-class").click(() => { + var unique_id = $("#class_id_input").val(); + if (!isNaN(unique_id)) { + if (unique_id.length == 5) { + let selected_semester = $("#semesters").find(":selected").val(); + openCoursePage(selected_semester, unique_id); + $("#class_id_input").val(''); + return; + } + } + alert("Oops, check your input. Class IDs should have 5 digits!"); +}); + +$("#options_button").click(function () { + chrome.tabs.create({ + 'url': "options.html" + }); +}); + + + +$("#courseList").on('mouseover', '.copybut', function () { + $(this).addClass('shadow'); +}).on('mouseleave', '.copybut', function () { + $(this).removeClass('shadow'); +}); + +$("#courseList").on('click', '.copybut', function (e) { + e.stopPropagation(); + copyButtonAnimation(); + let unique = $(this).val(); + copyUnique(unique); +}); + +function copyUnique(unique) { + var temp = $(""); + $("body").append(temp); + temp.val(unique).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); + handleRegister(clicked_item, curr_course) + handleRemove(clicked_item, curr_course) + toggleTimeDropdown(clicked_item); +}); + + +function handleRegister(clicked_item, curr_course) { let { status, registerlink @@ -102,7 +261,7 @@ function handleRegisterButton(clicked_item, curr_course) { } } -function handleRemoveButton(clicked_item, curr_course) { +function handleRemove(clicked_item, curr_course) { let list = $(clicked_item).closest("ul"); $(clicked_item).find("#listRemove").click(function () { if (can_remove) { @@ -132,6 +291,47 @@ function handleMoreInfo(clicked_item, curr_course) { }); } + +function getSemesters() { + var schedule_list = 'https://registrar.utexas.edu/schedules'; + $.get(schedule_list, function (response) { + if (response) { + htmlToNode(response).find('.callout2>ul>li>a').each(function (i) { + if (i < Popup.num_semesters) { + let sem_name = $(this).text().trim(); + if (sem_name != "Course Schedule Archive") { + $("#semesters").append(``); + $.get($(this).attr('href'), function (response) { + if (response) { + let response_node = htmlToNode(response); + let name = response_node.find(".page-title").text().substring(17).trim(); + response_node.find('.gobutton>a').each(function () { + let link = $(this).attr('href'); + var sem_num = link.substring(link.lastIndexOf('/') + 1).trim(); + $("option").each(function () { + if ($(this).text() == name) + $(this).val(sem_num); + }) + }); + } + }); + } + } + }); + } + }); +} + +function handleEmpty() { + if (courses.length != 0) { + $("#empty").hide(); + $("#courseList").show(); + } else { + showEmpty(); + } +} + + function copyButtonAnimation() { $(this).find('i').text('check'); $(this).stop(true, false).removeAttr('style').removeClass('shadow', { @@ -160,223 +360,6 @@ function toggleTimeDropdown(clicked_item) { } } - -$("#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 = $(""); - 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') { - hideSearchPopup(); - } - 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 { - alert('No Saved Courses to Export.'); - } - }); -}); - -$("#search-class").click(() => { - var unique_id = $("#class_id_input").val(); - if (!isNaN(unique_id)) { - if (unique_id.length == 5) { - let selected_semester = $("#semesters").find(":selected").val(); - openCoursePage(selected_semester, unique_id); - $("#class_id_input").val(''); - return; - } - } - alert("Oops, check your input. Class IDs should have 5 digits!"); -}); - -$("#options_button").click(function () { - chrome.tabs.create({ - 'url': "options.html" - }); -}); - -$("#calendar").click(function () { - chrome.tabs.create({ - 'url': "calendar.html" - }); -}); - -$("#importOrig").change(function (e) { - var files = e.target.files; - var reader = new FileReader(); - reader.onload = function () { - try { - var imported_courses = JSON.parse(this.result); - if (imported_courses && imported_courses.length && (imported_courses.length == 0 || validateObject(imported_courses))) { - chrome.storage.sync.set({ - savedCourses: imported_courses - }); - chrome.runtime.sendMessage({ - command: "updateBadge" - }); - updateAllTabsCourseList(); - setCourseList(); - chrome.runtime.sendMessage({ - command: "updateStatus", - }); - } - } catch (err) { - console.log(err); - } - importOrig.value = ''; - } - reader.readAsText(files[0]); -}); - -function validateObject(imported_courses) { - for (var i = 0; i < imported_courses.length; i++) { - var course = imported_courses[i]; - var is_valid = true; - var props = ["coursename", "datetimearr", "link", "profname", "status", "unique"]; - for (let j = 0; j < props.length; j++) { - is_valid &= course.hasOwnProperty(props[j]); - } - if (!is_valid) { - return false; - } - } - return true; -} - - -/*Clear the list and the storage of courses*/ -function clear() { - chrome.storage.sync.set({ - savedCourses: [] - }); - updateAllTabsCourseList(); - chrome.runtime.sendMessage({ - command: "updateBadge" - }); - $("#courseList").empty() - console.log("cleared"); - showEmpty(); -} - -function getSemesters() { - var schedule_list = 'https://registrar.utexas.edu/schedules'; - $.get(schedule_list, function (response) { - if (response) { - var object = $('').html(response).contents(); - object.find('.callout2>ul>li>a').each(function (index) { - if (index < 2) { - if ($(this).text() != "Course Schedule Archive") { - const semester = $(this).text().split(" ")[0]; - const year = $(this).text().split(" ")[1] - let sem_name = semester + " " + year; - console.log('semname:::: ' + sem_name); - $("#semesters").append(``); - $.get($(this).attr('href'), function (response) { - if (response) { - var object = $('').html(response).contents(); - - // Check title of page and see if it matches semester name - var name = object.find(".page-title").text(); - name = name.substring(name.lastIndexOf('|') + 1).trim(); - name = name.split(" ")[0] + " " + name.split(" ")[1]; - - console.log('name:::: ' + name); - object.find('.gobutton>a').each(function () { - var sem_num = $(this).attr('href').substring($(this).attr('href').lastIndexOf('/') + 1); - console.log('semnum:::: ' + sem_num); - $("option").each(function () { - console.log($(this).text()); - if ($(this).text() == name) { - $(this).val(sem_num); - console.log($(this).val()); - } - }) - }); - } - }); - } - } - }); - } - }); -} - -function openCoursePage(sem, unique) { - var link = `https://utdirect.utexas.edu/apps/registrar/course_schedule/${sem}/${unique}/`; - window.open(link); -} - -function handleEmpty() { - if (courses.length != 0) { - $("#empty").hide(); - $("#courseList").show(); - } else { - showEmpty(); - } -} - function showEmpty() { $("#courseList").hide(); $("#empty").fadeIn(200); diff --git a/js/util.js b/js/util.js index 78be7450..672d0663 100644 --- a/js/util.js +++ b/js/util.js @@ -123,6 +123,10 @@ function updateAllTabsCourseList() { }); } +function htmlToNode(response) { + return $('').html(response).contents(); +} + function setCurrentTabUrl(link) { chrome.tabs.query({ currentWindow: true, @@ -208,6 +212,26 @@ function findLocation(day, timearr, datetimearr) { } } + +function validateCourses(courses) { + for (var i = 0; i < courses.length; i++) { + if (!validateCourseObject(courses[i])) { + return false; + } + } + return true; +} + +function validateCourseObject(course) { + var is_valid = true; + var props = ["coursename", "datetimearr", "link", "profname", "status", "unique"]; + for (let j = 0; j < props.length; j++) { + is_valid &= course.hasOwnProperty(props[j]); + } + return is_valid; +} + + function reformatDateTime(dtl1) { let output = ""; for (let i = 0; i < dtl1.length; i++) { diff --git a/manifest.json b/manifest.json index 7b12f4bc..c9abd31b 100644 --- a/manifest.json +++ b/manifest.json @@ -35,7 +35,7 @@ "grades.db", "images/disticon.png" ], "background": { - "scripts": ["js/lib/jquery-3.3.1.min.js", "js/lib/sql-memory-growth.js", "js/lib/moment.min.js", "js/background.js"], + "scripts": ["js/lib/jquery-3.3.1.min.js", "js/lib/sql-memory-growth.js", "js/lib/moment.min.js", "js/config.js", "js/background.js"], "persistent": true }, "browser_action": { diff --git a/popup.html b/popup.html index a0f424ac..3f24574c 100644 --- a/popup.html +++ b/popup.html @@ -29,7 +29,7 @@ - +