(function () {
"use strict";
// 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}$/;
const DEPTCRSN_RE = /^([A-Z]{2,4})([0-9]{4})$/;
const CRED_RE = /^(?:Cr=([0-9]{1,2}(?:\.[0-9]{0,2})?)|([0-9]{1,2}\.[0-9]{0,2}))$/;
const MAYBE_CRED_RE = /^[0-9]{1,2}$/;
const MAYBE_DEPT_RE = /^[A-Z]{2,4}$/;
const IGNORE_RE = /^[A-Z]$/;
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();
// change to next summer on new year
// begin next FW on July 1
let fw_year, s_year;
if (month >= 6) {
fw_year = now.getFullYear();
} else {
fw_year = now.getFullYear() - 1;
}
s_year = now.getFullYear();
let fw_sess = document.createElement("option");
let fw_sess_val = "FW " + fw_year;
fw_sess.value = fw_sess_val;
fw_sess.textContent = `Fall/Winter ${fw_year}-${fw_year+1}`;
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 (cached_ycq_s.sess) {
case fw_sess_val: fw_sess.selected = true; break;
case s_sess_val: s_sess.selected = true; break;
default:
/* assume enrolling for summer courses between March and May inclusive */
if (month >= 2 && month <= 4)
s_sess.selected = true;
else
fw_sess.selected = true;
}
let ENGLISH_TYPES = {"fac": "faculty", "subj": "subject", "crsn": "course number", "cred": "credit number"};
function ready() {
let ywhAd = document.getElementById("ywh-ad");
if (location.protocol != "http:" && location.protocol != "https:" && location.protocol != "file:") {
ywhAd.style.display = "none";
}
let sessions = document.querySelector("#sessions");
sessions.appendChild(fw_sess);
sessions.appendChild(s_sess);
let input = document.getElementById("input");
let link = document.getElementById("link");
let linkContainer = document.getElementById("link-container");
let state;
let apply = function () {
state = {subj: "", fac: "", crsn: "", cred: ""};
let multiple = new Set();
let warn = [], error = [];
let got = function (type, token) {
if (state[type])
multiple.add(ENGLISH_TYPES[type]);
state[type] = token;
};
let tryParse = function (token) {
let subjcrsn, cred;
if (SUBJS.hasOwnProperty(token)) {
got("subj", token);
} else if (FACS.has(token)) {
got("fac", token);
} else if ((subjcrsn = DEPTCRSN_RE.exec(token))) {
got("subj", subjcrsn[1]);
got("crsn", subjcrsn[2]);
} else if ((cred = CRED_RE.exec(token))) {
got("cred", parseFloat(cred[1] || cred[2]).toFixed(2));
} else if (CRSN_RE.test(token)) {
got("crsn", token);
} else if (MAYBE_CRED_RE.test(token)) {
got("cred", parseFloat(token).toFixed(2));
warn.push(`assuming ${token} is the number of credits`);
} else if (MAYBE_DEPT_RE.test(token)) {
state["maybeSubj"] = token;
} else if (!IGNORE_RE.test(token)) {
return false;
}
return true;
};
input.value.split(TOKEN_DELIM_RE).forEach(function (token) {
if (!token || tryParse(token) || tryParse(token.toUpperCase()))
return;
warn.push(`don't understand search term: ${token}`);
});
if (!state["subj"] && state["maybeSubj"]) {
state["subj"] = state["maybeSubj"];
warn.push("guessing subject is " + state["maybeSubj"]);
}
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"] && 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"]) {
// 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
let compat_facs = SUBJS[state["subj"]];
let other_options = function () {
if (compat_facs) {
let other_facs = compat_facs
.filter(f => f != state["fac"])
.map(f => `${f}`)
.join(", ");
if (other_facs.length)
return ", other options: " + other_facs;
}
return "";
}
// 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()}`);
} 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()}`);
} else if (compat_facs) {
// 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];
if (state["fac"]) {
warn.push(`using saved faculty: ${state["fac"]}${other_options()}`);
} else {
// 4. first compatible faculty
state["fac"] = compat_facs[0];
warn.push(`using default faculty for ${state["subj"]}: ${state["fac"]}${other_options()}`);
}
} else {
error.push("no faculty provided and unknown subject");
}
}
if (state["subj"] && state["crsn"] && !state["cred"]) {
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";
warn.push("assuming the number of credits is 3.00");
}
}
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 = `${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 = `${state["fac"]}/${state["subj"]} Courses (${sessions.selectedOptions[0].textContent}) | York University`;
linkContainer.style.display = "block";
} else {
linkContainer.style.display = "none";
error.push("need at least subject. see examples above");
}
if (multiple.size)
warn.push("multiple terms for " + Array.from(multiple.values()).join(", ") + ", using last occurrence for each");
document.getElementById("warning").innerHTML = warn.map(w => 'warning: ' + w).join("
");
document.getElementById("error").innerHTML = error.map(e => 'error: ' + e).join("
");
};
input.addEventListener("input", apply);
sessions.addEventListener("change", apply);
document.body.addEventListener("click", function (e) {
if (e.target.closest(".sample-query")) {
e.preventDefault();
input.select();
// doesn't work in Firefox, oh well
if (!document.execCommand || !document.execCommand("insertText", false, e.target.textContent))
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_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"]) {
if (state["fac"]) {
if (state["crsn"])
new_ycq_s.course_facs[state["subj"] + state["crsn"]] = state["fac"];
new_ycq_s.subj_facs[state["subj"]] = state["fac"];
}
if (state["crsn"]) {
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;
}
};
link.addEventListener("click", save_defaults);
document.forms[0].addEventListener("submit", function (e) {
e.preventDefault();
if (linkContainer.style.display == "block")
link.click();
});
input.addEventListener("keydown", function (e) {
if (e.key == "Enter") {
e.preventDefault();
if (linkContainer.style.display == "block") {
// firefox silently ignores simulated link events with modifiers
// 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 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 {
link.click();
}
} else {
link.dispatchEvent(new MouseEvent("click", e));
}
}
}
});
apply();
}
if (document.readyState === "interactive" || document.readyState === "complete") {
ready();
} else {
document.addEventListener("DOMContentLoaded", ready);
}
}());