(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)); }); 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]$/; 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 || ""; 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 (ycq_storage.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/subject", "crsn": "course number", "cred": "credit number", "sess": "session (pick on the right)"}; 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 (DEPTS.has(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 && ycq_storage.course_subjs[state.crsn]) { state.subj = ycq_storage.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; warn.push(`using saved default subject: ${state.subj}`); } if (!state.fac && state.subj) { state.fac = DEPTS.get(state.subj); if (!state.fac) 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]; 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 r_sess = document.getElementById("sessions").value; let sess = r_sess.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})`; 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})`; 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("
"); 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") { 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(); } }); 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; } if (state.subj) { ycq_storage.course_subjs[state.crsn] = state.subj; ycq_storage.default_subj = state.subj; modified = true; } } if (modified) localStorage.ycq = JSON.stringify(ycq_storage); }; link.addEventListener("click", save_crsn); 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 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(); 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); } }());