summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlex Xu (Hello71) <alex_y_xu@yahoo.ca>2018-09-20 10:52:02 -0400
committerAlex Xu (Hello71) <alex_y_xu@yahoo.ca>2018-09-20 10:52:02 -0400
commit132fa09384decd7b4ae297a3e3194cf02b323671 (patch)
tree770d12ff145ac3f5a22e358a152375c471461b9c
parent07a03aa6411db45022c3d2bb6549281a56c5292d (diff)
downloadyorku-course-query-132fa09384decd7b4ae297a3e3194cf02b323671.tar.xz
yorku-course-query-132fa09384decd7b4ae297a3e3194cf02b323671.zip
add features
-rw-r--r--script.js361
1 files changed, 300 insertions, 61 deletions
diff --git a/script.js b/script.js
index 43740fa..b363ce7 100644
--- a/script.js
+++ b/script.js
@@ -1,25 +1,195 @@
(function () {
"use strict";
-const FACS = new Set();
-const DEPTS = new Map();
-// maintain: CDM Advanced Search,
-// console.log(Array.prototype.map.call(document.getElementsByName("subjectPopup")[0].children,(e)=>'"'+e.textContent.match(/[A-Z]{2,4}/)[0] + '"').join(", "))
-[
- ["AP", "ADMB", "ADMS", "ANTH", "ARB", "ASL", "CCY", "CDNS", "CH", "CLST", "CLTR", "COGS", "COMN", "CRIM", "DEMS", "DLLL", "ECON", "EN", "ESL", "FND", "FR", "GCIN", "GEOG", "GER", "GK", "GKM", "GWST", "HEB", "HIST", "HREQ", "HRM", "HUMA", "INDG", "INDV", "IT", "ITEC", "JC", "JP", "KOR", "LA", "LASO", "LING", "LLS", "MIST", "MODR", "PERS", "PHIL", "POLS", "POR", "PPAS", "PRWR", "RU", "SOCI", "SOSC", "SOWK", "SP", "SWAH", "SXST", "TESL", "TYP", "WKLS", "WRIT"],
- ["ED", "AUCO", "BBED", "BIOL", "CHEM", "DANC", "DEST", "DRAA", "ECON", "EDFE", "EDFR", "EDIN", "EDIS", "EDJI", "EDPJ", "EDPR", "EDST", "EDUC", "EN", "ENVS", "FAST", "FREN", "GEOG", "HEB", "HIST", "INDS", "LAW", "LLDV", "MATH", "MUSI", "ORCO", "PHED", "PHIL", "PHYS", "POLS", "PRAC", "SCIE", "SLGS", "SOSC", "TECH", "TLSE", "VISA"],
- ["ES", "ENVS"],
- ["FA", "ARTH", "DANC", "DATT", "DESN", "FACS", "FILM", "INDV", "MUSI", "PANF", "THEA", "VISA", "YSDN"],
- ["GL", "BIOL", "BUEC", "CAT", "CDNS", "COMS", "CSLA", "DRST", "ECON", "EN", "ENSL", "FRAN", "FSL", "GWST", "HIST", "HUMA", "ILST", "ITEC", "LIN", "LYON", "MATH", "MODR", "NATS", "PHIL", "PHYS", "POLS", "PSYC", "SOCI", "SOSC", "SP", "SXST", "TRAN", "WKST", "WMST"],
- ["GS", "ANTH", "ARTH", "BIOL", "BLIS", "CDIS", "CGTA", "CHEM", "CIVL", "CMCT", "DANC", "DEMS", "DIGM", "DVST", "ECON", "EDUC", "EECS", "EIL", "EN", "ENG", "ENVS", "ESS", "FACC", "FILM", "FREN", "GEOG", "GFWS", "HIST", "HLTH", "HRM", "HUMA", "INST", "INTE", "ITEC", "KAHS", "LAL", "LAW", "LREL", "MATH", "MDES", "MECH", "MUSI", "NURS", "OVGS", "PACC", "PHIL", "PHYS", "PIA", "POLS", "PPAL", "PSYC", "SLST", "SOCI", "SOWK", "SPTH", "STS", "THEA", "THST", "TRAN", "TRAS", "TXLW", "VISA", "WMST"],
- ["HH", "HLST", "IHST", "KINE", "NURS", "PKIN", "PSYC"],
- ["LE", "CIVL", "COOP", "EECS", "ENG", "ESSE", "MECH"],
- ["SB", "ACTG", "ARTM", "BSUS", "DCAD", "ECON", "EMBA", "ENTR", "EXCH", "FINE", "FNEN", "FNSV", "HIMP", "IBUS", "MBA", "INTL", "MACC", "MBAN", "MFIN", "MGMT", "MINE", "MKTG", "MSTM", "OMIS", "ORGS", "OVGS", "PLCY", "PROP", "PUBL", "SGMT", "SOCM"],
- ["SC", "BC", "BCHM", "BIOL", "BPHS", "CHEM", "COOP", "ENVB", "GEOG", "ISCI", "MATH", "NATS", "PHYS", "SENE", "STS"]
-].forEach((arr) => {
- let faculty = arr.shift();
- FACS.add(faculty);
- arr.forEach((subj) => DEPTS.set(subj, faculty));
-});
+
+// as of 2018, LW does not use CDM, but leave it in just in case
+const FACS = new Set(["AP", "ED", "ES", "FA", "GL", "GS", "HH", "LE", "LW", "SB", "SC"]);
+const SUBJS = {
+ "ACTG": ["SB"],
+ "ADMB": ["AP"],
+ "ADMS": ["AP"],
+ "ANTH": ["AP", "GS"],
+ "ARB": ["AP"],
+ "ARTH": ["FA", "GS"],
+ "ARTM": ["SB"],
+ "ASL": ["AP"],
+ "AUCO": ["ED"],
+ "BBED": ["ED"],
+ "BC": ["SC"],
+ "BCHM": ["SC"],
+ "BIOL": ["SC", "GL", "GS", "ED"],
+ "BLIS": ["GS"],
+ "BPHS": ["SC"],
+ "BSUS": ["SB"],
+ "BUEC": ["GL"],
+ "CAT": ["GL"],
+ "CCY": ["AP"],
+ "CDIS": ["GS"],
+ "CDNS": ["AP", "GL"],
+ "CGTA": ["GS"],
+ "CH": ["AP"],
+ "CHEM": ["SC", "GS", "ED"],
+ "CIVL": ["LE", "GS"],
+ "CLST": ["AP"],
+ "CLTR": ["AP"],
+ "CMCT": ["GS"],
+ "COGS": ["AP"],
+ "COMN": ["AP"],
+ "COMS": ["GL"],
+ "COOP": ["LE", "SC"],
+ "CRIM": ["AP"],
+ "CSLA": ["GL"],
+ "DANC": ["FA", "GS", "ED"],
+ "DATT": ["FA"],
+ "DCAD": ["SB"],
+ "DEMS": ["AP", "GS"],
+ "DESN": ["FA"],
+ "DEST": ["ED"],
+ "DIGM": ["GS"],
+ "DLLL": ["AP"],
+ "DRAA": ["ED"],
+ "DRST": ["GL"],
+ "DVST": ["GS"],
+ "ECON": ["AP", "GL", "SB", "GS", "ED"],
+ "EDFE": ["ED"],
+ "EDFR": ["ED"],
+ "EDIN": ["ED"],
+ "EDIS": ["ED"],
+ "EDJI": ["ED"],
+ "EDPJ": ["ED"],
+ "EDPR": ["ED"],
+ "EDST": ["ED"],
+ "EDUC": ["ED", "GS"],
+ "EECS": ["LE", "GS"],
+ "EIL": ["GS"],
+ "EMBA": ["SB"],
+ "EN": ["AP", "GL", "GS", "ED"],
+ "ENG": ["LE", "GS"],
+ "ENSL": ["GL"],
+ "ENTR": ["SB"],
+ "ENVB": ["SC"],
+ "ENVS": ["GS", "ED"],
+ "ESL": ["AP"],
+ "ESS": ["GS"],
+ "ESSE": ["LE"],
+ "EXCH": ["SB"],
+ "FACC": ["GS"],
+ "FACS": ["FA"],
+ "FAST": ["ED"],
+ "FILM": ["FA", "GS"],
+ "FINE": ["SB"],
+ "FND": ["AP"],
+ "FNEN": ["SB"],
+ "FNSV": ["SB"],
+ "FR": ["AP"],
+ "FRAN": ["GL"],
+ "FREN": ["ED", "GS"],
+ "FSL": ["GL"],
+ "GCIN": ["AP"],
+ "GEOG": ["AP", "SC", "GS", "ED"],
+ "GER": ["AP"],
+ "GFWS": ["GS"],
+ "GK": ["AP"],
+ "GKM": ["AP"],
+ "GWST": ["AP", "GL"],
+ "HEB": ["AP", "ED"],
+ "HIMP": ["SB"],
+ "HIST": ["AP", "GL", "GS", "ED"],
+ "HLST": ["HH"],
+ "HLTH": ["GS"],
+ "HREQ": ["AP"],
+ "HRM": ["AP", "GS"],
+ "HUMA": ["AP", "GL", "GS"],
+ "IBUS": ["SB"],
+ "IHST": ["HH"],
+ "ILST": ["GL"],
+ "INDG": ["AP"],
+ "INDS": ["ED"],
+ "INDV": ["AP", "FA"],
+ "INST": ["GS"],
+ "INTE": ["GS"],
+ "INTL": ["SB"],
+ "ISCI": ["SC"],
+ "IT": ["AP"],
+ "ITEC": ["AP", "GL", "GS"],
+ "JC": ["AP"],
+ "JP": ["AP"],
+ "KAHS": ["GS"],
+ "KINE": ["HH"],
+ "KOR": ["AP"],
+ "LA": ["AP"],
+ "LAL": ["GS"],
+ "LASO": ["AP"],
+ "LAW": ["ED", "GS", "LW"],
+ "LIN": ["GL"],
+ "LING": ["AP"],
+ "LLDV": ["ED"],
+ "LLS": ["AP"],
+ "LREL": ["GS"],
+ "LYON": ["GL"],
+ "MACC": ["SB"],
+ "MATH": ["SC", "GL", "ED", "GS"],
+ "MBA": ["SB"],
+ "MBAN": ["SB"],
+ "MDES": ["GS"],
+ "MECH": ["GS"],
+ "MFIN": ["SB"],
+ "MGMT": ["SB"],
+ "MINE": ["SB"],
+ "MIST": ["AP"],
+ "MKTG": ["SB"],
+ "MODR": ["AP", "GL"],
+ "MSTM": ["SB"],
+ "MUSI": ["FA", "GS", "ED"],
+ "NATS": ["SC", "GL"],
+ "NURS": ["HH", "GS"],
+ "OMIS": ["SB"],
+ "ORCO": ["ED"],
+ "ORGS": ["SB"],
+ "OVGS": ["SB", "GS"],
+ "PACC": ["GS"],
+ "PANF": ["FA"],
+ "PERS": ["AP"],
+ "PHED": ["ED"],
+ "PHIL": ["AP", "GL", "GS", "ED"],
+ "PHYS": ["SC", "GL", "GS", "ED"],
+ "PIA": ["GS"],
+ "PKIN": ["HH"],
+ "PLCY": ["SB"],
+ "POLS": ["AP", "GL", "GS", "ED"],
+ "POR": ["AP"],
+ "PPAL": ["GS"],
+ "PPAS": ["AP"],
+ "PRAC": ["ED"],
+ "PROP": ["SB"],
+ "PRWR": ["AP"],
+ "PSYC": ["GS", "GL"],
+ "PUBL": ["SB"],
+ "RU": ["AP"],
+ "SCIE": ["ED"],
+ "SENE": ["SC"],
+ "SGMT": ["SB"],
+ "SLGS": ["ED"],
+ "SLST": ["GS"],
+ "SOCI": ["AP", "GL", "GS"],
+ "SOSC": ["AP", "GL", "ED"],
+ "SOWK": ["AP", "GS"],
+ "SP": ["AP", "GL"],
+ "SPTH": ["GS"],
+ "STS": ["GS"],
+ "SWAH": ["AP"],
+ "SXST": ["AP", "GL"],
+ "TECH": ["ED"],
+ "TESL": ["AP"],
+ "THEA": ["FA", "GS"],
+ "THST": ["GS"],
+ "TLSE": ["ED"],
+ "TRAN": ["GL", "GS"],
+ "TRAS": ["GS"],
+ "TXLW": ["GS"],
+ "TYP": ["AP"],
+ "VISA": ["FA", "GS"],
+ "WKLS": ["AP"]
+}
const TOKEN_DELIM_RE = /[^A-Za-z0-9.=]/;
const CRSN_RE = /^[0-9]{4}$/;
@@ -29,12 +199,16 @@ const MAYBE_CRED_RE = /^[0-9]{1,2}$/;
const MAYBE_DEPT_RE = /^[A-Z]{2,4}$/;
const IGNORE_RE = /^[A-Z]$/;
-let ycq_storage = JSON.parse(localStorage.ycq || "{}");
-if (!ycq_storage)
- ycq_storage = {};
-ycq_storage.course_creds = ycq_storage.course_creds || {};
-ycq_storage.course_subjs = ycq_storage.course_subjs || {};
-ycq_storage.default_subj = ycq_storage.default_subj || "";
+function parse_ycq_s(str) {
+ let ycq_s = JSON.parse(str || "{}");
+ ycq_s.course_creds = ycq_s.course_creds || {};
+ ycq_s.course_subjs = ycq_s.course_subjs || {};
+ ycq_s.course_facs = ycq_s.course_facs || {};
+ ycq_s.subj_facs = ycq_s.subj_facs || {};
+ ycq_s.default_facs = ycq_s.default_facs || [];
+ return ycq_s;
+}
+var cached_ycq_s = parse_ycq_s(localStorage.ycq);
let now = new Date();
let month = now.getMonth();
@@ -55,7 +229,7 @@ let s_sess = document.createElement("option");
let s_sess_val = "SU " + (s_year - 1);
s_sess.value = s_sess_val;
s_sess.textContent = `Summer ${s_year}`;
-switch (ycq_storage.sess) {
+switch (cached_ycq_s.sess) {
case fw_sess_val: fw_sess.selected = true; break;
case s_sess_val: s_sess.selected = true; break;
default:
@@ -97,7 +271,7 @@ function ready() {
let tryParse = function (token) {
let subjcrsn, cred;
- if (DEPTS.has(token)) {
+ if (SUBJS.hasOwnProperty(token)) {
got("subj", token);
} else if (FACS.has(token)) {
got("fac", token);
@@ -130,25 +304,61 @@ function ready() {
warn.push("guessing subject is " + state.maybeSubj);
}
- if (!state.subj && ycq_storage.course_subjs[state.crsn]) {
- state.subj = ycq_storage.course_subjs[state.crsn];
+ if (!state.subj && state.crsn && cached_ycq_s.course_subjs[state.crsn]) {
+ state.subj = cached_ycq_s.course_subjs[state.crsn];
warn.push(`using saved subject for ${state.crsn}: ${state.subj}`);
}
- if (!state.subj && ycq_storage.default_subj) {
- state.subj = ycq_storage.default_subj;
+ if (!state.subj && cached_ycq_s.default_subj) {
+ state.subj = cached_ycq_s.default_subj;
warn.push(`using saved default subject: ${state.subj}`);
}
if (!state.fac && state.subj) {
- state.fac = DEPTS.get(state.subj);
- if (!state.fac)
+ // if no faculty, try:
+ // 1. most recent faculty for this course
+ // 2. most recent faculty for this subject
+ // 3. most recent compatible faculty
+ // 4. first compatible faculty
+
+ // 1. most recent faculty for this course
+ if (state.crsn && cached_ycq_s.course_facs[state.subj + state.crsn]) {
+ state.fac = cached_ycq_s.course_facs[state.subj + state.crsn];
+ warn.push(`using saved faculty for ${state.subj} ${state.crsn}: ${state.fac}, other options maybe: ${other_facs}`);
+ } else if (cached_ycq_s.subj_facs[state.subj]) {
+ // 2. most recent faculty for this subject
+ state.fac = cached_ycq_s.subj_facs[state.subj];
+ warn.push(`using saved faculty for ${state.subj}: ${state.fac}, other options: ${other_facs}`);
+ } else if (SUBJS.hasOwnProperty(state.subj)) {
+ let compat_facs = SUBJS[state.subj];
+
+ // 3. most recent compatible faculty
+ if (cached_ycq_s.default_facs)
+ for (let i = cached_ycq_s.default_facs.length - 1; i >= 0; i--)
+ if (compat_facs.indexOf(cached_ycq_s.default_facs[i]) > -1)
+ state.fac = cached_ycq_s.default_facs[i];
+
+ let using_faculty = "saved";
+ // 4. first compatible faculty
+ if (!state.fac) {
+ state.fac = compat_facs[0];
+ using_faculty = "default";
+ }
+
+ let other_facs = compat_facs
+ .filter(f => f != state.fac)
+ .map(f => `<a href="#" class="prepend-query">${f}</a>`)
+ .join(", ");
+ if (other_facs)
+ warn.push(`using ${using_faculty} faculty for ${state.subj}: ${state.fac}, other options: ${other_facs}`);
+ } else {
error.push("no faculty provided and unknown subject");
+ }
}
if (state.subj && state.crsn && !state.cred) {
- if (ycq_storage.course_creds[state.subj + state.crsn]) {
- state.cred = ycq_storage.course_creds[state.subj + state.crsn];
+ if (cached_ycq_s.course_creds[state.subj + state.crsn]) {
+ state.cred = cached_ycq_s.course_creds[state.subj + state.crsn];
warn.push(`using saved credit number for ${state.subj} ${state.crsn}: ${state.cred}`);
} else {
state.cred = "3.00";
@@ -156,18 +366,17 @@ function ready() {
}
}
- let r_sess = document.getElementById("sessions").value;
- let sess = r_sess.split(" ");
+ let sess = document.getElementById("sessions").value.split(" ");
state.sess = sess[0];
state.year = parseInt(sess[1], 10);
if (state.fac && state.subj && state.crsn && state.cred && state.year && state.sess) {
link.href = `https://w2prod.sis.yorku.ca/Apps/WebObjects/cdm.woa/wa/crsq?fa=${state.fac}&sj=${state.subj}&cn=${state.crsn}&cr=${state.cred}&ay=${state.year}&ss=${state.sess}`;
- link.textContent = `York University: ${state.fac}/${state.subj} ${state.crsn} ${state.cred} (${sessions.selectedOptions[0].textContent})`;
+ link.textContent = `${state.fac}/${state.subj} ${state.crsn} ${state.cred} (${sessions.selectedOptions[0].textContent}) | York University`;
linkContainer.style.display = "block";
} else if (state.fac && state.subj && state.sess) {
link.href = `https://w2prod.sis.yorku.ca/Apps/WebObjects/cdm.woa/wa/crsq1?faculty=${state.fac}&subject=${state.subj}&academicyear=${state.year}&studysession=${state.sess}`;
- link.textContent = `York University: ${state.fac}/${state.subj} Courses (${sessions.selectedOptions[0].textContent})`;
+ link.textContent = `${state.fac}/${state.subj} Courses (${sessions.selectedOptions[0].textContent}) | York University`;
linkContainer.style.display = "block";
} else {
linkContainer.style.display = "none";
@@ -179,15 +388,12 @@ function ready() {
document.getElementById("warning").innerHTML = warn.map(w => 'warning: ' + w).join("<br>");
document.getElementById("error").innerHTML = error.map(e => 'error: ' + e).join("<br>");
-
- ycq_storage.sess = r_sess;
- localStorage.ycq = JSON.stringify(ycq_storage);
};
input.addEventListener("input", apply);
sessions.addEventListener("change", apply);
- document.getElementById("sample-queries").addEventListener("click", function (e) {
- if (e.target.tagName == "A") {
+ document.body.addEventListener("click", function (e) {
+ if (e.target.closest(".sample-query")) {
e.preventDefault();
input.select();
// doesn't work in Firefox, oh well
@@ -195,26 +401,57 @@ function ready() {
input.value = e.target.textContent;
apply();
input.focus();
+ } else if (e.target.closest(".prepend-query")) {
+ e.preventDefault();
+ let r = false;
+ if (document.execCommand) {
+ input.setSelectionRange(0, 0);
+ r = document.execCommand("insertText", false, e.target.textContent + " ");
+ }
+ if (!r)
+ input.value = e.target.textContent + " " + input.value;
+ apply();
}
});
- let save_crsn = function () {
- let modified = false;
- if (state.crsn) {
- if (state.subj && state.cred) {
- ycq_storage.course_creds[state.subj + state.crsn] = state.cred;
- modified = true;
+ let save_defaults = function () {
+ let old_ycq_s_s = localStorage.ycq;
+ let new_ycq_s = parse_ycq_s(old_ycq_s_s);
+
+ if (state.fac) {
+ let default_facs = new Set(new_ycq_s.default_facs);
+ default_facs.delete(state.fac);
+ default_facs.add(state.fac);
+ let new_facs = Array.from(default_facs);
+ if (new_facs.length != new_ycq_s.default_facs.length ||
+ new_facs.some((v, i) => v !== new_ycq_s.default_facs[i])) {
+ new_ycq_s.default_facs = new_facs;
}
- if (state.subj) {
- ycq_storage.course_subjs[state.crsn] = state.subj;
- ycq_storage.default_subj = state.subj;
- modified = true;
+ }
+
+ if (state.subj) {
+ if (state.crsn) {
+ if (state.fac)
+ new_ycq_s.course_facs[state.subj + state.crsn] = state.fac;
+
+ if (state.cred)
+ new_ycq_s.course_creds[state.subj + state.crsn] = state.cred;
+
+ new_ycq_s.course_subjs[state.crsn] = state.subj;
}
+
+ new_ycq_s.default_subj = state.subj;
+ }
+
+ new_ycq_s.sess = document.getElementById("sessions").value;
+
+ let new_ycq_s_s = JSON.stringify(new_ycq_s);
+ if (new_ycq_s_s != old_ycq_s_s) {
+ cached_ycq_s = new_ycq_s;
+ localStorage.ycq = new_ycq_s_s;
}
- if (modified)
- localStorage.ycq = JSON.stringify(ycq_storage);
};
- link.addEventListener("click", save_crsn);
+ link.addEventListener("click", save_defaults);
document.forms[0].addEventListener("submit", function (e) {
e.preventDefault();
if (linkContainer.style.display == "block")
@@ -225,14 +462,16 @@ function ready() {
e.preventDefault();
if (linkContainer.style.display == "block") {
// firefox silently ignores simulated link events with modifiers
- if (/(?:Firefox|Gecko)\//.test(navigator.userAgent) && (e.ctrlKey || e.shiftKey || e.altKey || e.metaKey)) {
+ // use [\/] to fix syntax highlighting
+ if (/(?:Firefox|Gecko)[\/]/.test(navigator.userAgent) && (e.ctrlKey || e.shiftKey || e.altKey || e.metaKey)) {
if (e.ctrlKey) {
link.target = "_blank";
link.click();
link.target = "";
} else if (e.shiftKey) {
- // only need save_crsn here because other methods already trigger the link click event
- save_crsn();
+ // only need save here because other methods already trigger the link click event
+ // for efficiency, don't save twice
+ save_defaults();
window.open(link.href, "_blank",
"noopener,width=625,resizable,menubar,toolbar,location,personalbar,status,scrollbars");
} else {