diff options
author | Alex Xu (Hello71) <alex_y_xu@yahoo.ca> | 2018-10-29 14:50:35 -0400 |
---|---|---|
committer | Alex Xu (Hello71) <alex_y_xu@yahoo.ca> | 2018-10-29 14:50:35 -0400 |
commit | e40e9d03c169ce6228ad87373f57002e1c1b26c2 (patch) | |
tree | e26ef1a7f06f96781c1eff4d4da96af62112b9af | |
parent | b8d340c3c08a6b45a50d846577543ba97df8d73a (diff) | |
download | yorku-course-query-e40e9d03c169ce6228ad87373f57002e1c1b26c2.tar.xz yorku-course-query-e40e9d03c169ce6228ad87373f57002e1c1b26c2.zip |
update
-rw-r--r-- | index.html | 5 | ||||
-rw-r--r-- | script.js | 101 | ||||
-rw-r--r-- | style.css | 2 |
3 files changed, 51 insertions, 57 deletions
@@ -20,7 +20,7 @@ <a href="#" class="sample-query">biol</a>, <a href="#" class="sample-query">SB/ACTG 2010 3.00</a>, <a href="#" class="sample-query">adms 1000 3</a>, - <a href="#" class="sample-query">LE EECS 3000 Cr=3.00 A Term:F Professional Practice in Computing</a> + <a href="#" class="sample-query">LE EECS 1012 Cr=3.00 A Term:F Net-centric Introduction to Computing</a> </span> </div> <div> @@ -47,6 +47,9 @@ <hr style="margin: 2em auto; width: 80%;"> <div> <p> + This is an unofficial York University Course Query URL generator. Put in course numbers or subjects and it will spit out a persistent link (none of that "You have exceeded the maximum time limit" after 30 minutes or whatever it is). Despite the word "search" appearing sometimes, <strong>this does not search course names</strong>. Sorry, there's no public API for that. Please send complaints about the non-existence of useful APIs to the Registrar's Office. If <em>this</em> page is broken, please send mail to alex at this domain (alxu dot ca). + </p> + <p> Tips: <ul> <li id="ywh-ad">it is highly recommended to install YorkU Web Helper, available <a href="">for Firefox</a> and <a href="">for Chrome</a>.</li> @@ -197,7 +197,6 @@ 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-Za-z]$/; // note: this has to be lowercase, otherwise "ignored search terms" will incorrectly uppercase the input function parse_ycq_s(str) { let ycq_s = JSON.parse(str || "{}"); @@ -240,15 +239,21 @@ switch (cached_ycq_s.sess) { fw_sess.selected = true; } -let ENGLISH_TYPES = {"fac": "faculty", "subj": "subject", "crsn": "course number", "cred": "credit number"}; +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"; + // when embedded in the webextension, the protocol will be moz-extension:// + // or chrome:// or something like that + if (!/^(?:https?|file):$/.test(location.protocol)) { + document.getElementById("ywh-ad").style.display = "none"; } - let sessions = document.querySelector("#sessions"); + let sessions = document.getElementById("sessions"); sessions.appendChild(fw_sess); sessions.appendChild(s_sess); @@ -258,19 +263,19 @@ function ready() { let state; - let apply_list = function (n, l) { - if (l.length) { - document.getElementById(n).style.display = "block"; - document.getElementById(n + "-list").innerHTML = l.map(s => `<li>${s}</li>`).join(''); - } else { - document.getElementById(n).style.display = "none"; - } + let add_li = function (l, t) { + var e = document.createElement("li"); + e.innerHTML = t; + l.appendChild(e); }; let apply = function () { state = {subj: "", fac: "", crsn: "", cred: ""}; let multiple = new Set(); - let warn = [], error = []; + let curWarn = document.getElementById("warning-list"); + let warn = curWarn.cloneNode(false); + let curError = document.getElementById("error-list"); + let error = curError.cloneNode(false); let got = function (type, token) { if (state[type]) @@ -278,8 +283,6 @@ function ready() { state[type] = token; }; - let ignored_tokens = []; - let tryParse = function (token) { let subjcrsn, cred; if (SUBJS.hasOwnProperty(token)) { @@ -295,11 +298,9 @@ function ready() { 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`); + add_li(warn, `assuming ${token} is the number of credits`); } else if (MAYBE_DEPT_RE.test(token)) { state["maybeSubj"] = token; - } else if (IGNORE_RE.test(token)) { - ignored_tokens.push(token); } else { return false; } @@ -312,29 +313,20 @@ function ready() { return; unk_tokens.push(token); }); - if (unk_tokens.length) { - let dont_understand = unk_tokens.map(t => `"${t}"`).join(', '); - warn.push(`don't understand search terms: ${dont_understand}.`); - } - - if (ignored_tokens.length) { - let ignored_terms = ignored_tokens.map(t => `"${t}"`).join(', '); - warn.push(`ignored search terms: ${ignored_terms}.`); - } if (!state["subj"] && state["maybeSubj"]) { state["subj"] = state["maybeSubj"]; - warn.push(`guessing subject is "${state["maybeSubj"]}".`); + add_li(warn, `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(`assuming ${state["crsn"]} means ${state["subj"]} ${state["crsn"]}, because you last used ${state["subj"]} for ${state["crsn"]}.`); + add_li(warn, `assuming ${state["crsn"]} means ${state["subj"]} ${state["crsn"]}, because you last used ${state["subj"]} for ${state["crsn"]}.`); } if (!state["subj"] && cached_ycq_s.default_subj) { state["subj"] = cached_ycq_s.default_subj; - warn.push(`using ${state["subj"]}, because that was your most recently searched subject.`); + add_li(warn, `using ${state["subj"]}, because that was your most recently queried subject.`); } if (!state["fac"] && state["subj"]) { @@ -350,7 +342,7 @@ function ready() { if (compat_facs) { let other_facs = compat_facs .filter(f => f != state["fac"]) - .map(f => `<a href="#" class="prepend-query">${f}</a>`) + .map(f => `<a href="#" class="prepend-query">${f}/${state["subj"]}</a>`) .join(", "); if (other_facs.length) return "other options: " + other_facs; @@ -361,11 +353,11 @@ function ready() { // 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(`assuming ${state["subj"]} ${state["crsn"]} is ${state["fac"]}/${state["subj"]}, because you last used ${state["fac"]} for ${state["subj"]} ${state["crsn"]}. ${other_options()}`); + add_li(warn, `assuming ${state["subj"]} ${state["crsn"]} is ${state["fac"]}/${state["subj"]}, because you last used ${state["fac"]} for ${state["subj"]} ${state["crsn"]}. ${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(`assuming ${state["subj"]} means ${state["fac"]}/${state["subj"]}, because you last used ${state["fac"]} for ${state["subj"]}. ${other_options()}`); + add_li(warn, `assuming ${state["subj"]} means ${state["fac"]}/${state["subj"]}, because you last used ${state["fac"]} for ${state["subj"]}. ${other_options()}`); } else if (compat_facs) { // 3. most recent compatible faculty if (cached_ycq_s.default_facs) @@ -374,24 +366,27 @@ function ready() { state["fac"] = cached_ycq_s.default_facs[i]; if (state["fac"]) { - warn.push(`assuming ${state["subj"]} means ${state["fac"]} ${state["subj"]}, because you recently used ${state["fac"]}. ${other_options()}`); + add_li(warn, `assuming ${state["subj"]} means ${state["fac"]}/${state["subj"]}, because you recently used ${state["fac"]}. ${other_options()}`); } else { // 4. first compatible faculty state["fac"] = compat_facs[0]; - warn.push(`assuming ${state["subj"]} means ${state["fac"]} ${state["subj"]}, because ${state["fac"]} is the default for ${state["subj"]}. ${other_options()}`); + if (compat_facs.length > 1) + add_li(warn, `assuming ${state["subj"]} means ${state["fac"]}/${state["subj"]}, because we set that as the default for ${state["subj"]}. ${other_options()}`); + else + add_li(warn, `assuming ${state["subj"]} means ${state["fac"]}/${state["subj"]}, because we only know ${state["fac"]} for ${state["subj"]}.`); } } else { - error.push("no faculty provided and unknown subject"); + add_li(error, "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(`assuming ${state["subj"]} ${state["crsn"]} is ${state["cred"]} credits, because you last used ${state["cred"]} for ${state["subj"]} ${state["crsn"]}.`); + add_li(warn, `assuming ${state["subj"]} ${state["crsn"]} is ${state["cred"]} credits, because you last used ${state["cred"]} for ${state["subj"]} ${state["crsn"]}.`); } else { state["cred"] = "3.00"; - warn.push("assuming the number of credits is 3.00, because that's the most common number."); + add_li(warn, "assuming the number of credits is 3.00, because that's the most common number."); } } @@ -409,14 +404,16 @@ function ready() { linkContainer.style.display = "block"; } else { linkContainer.style.display = "none"; - error.push("need at least subject. see examples above"); + add_li(error, "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"); + add_li(warn, "multiple terms for " + Array.from(multiple.values()).join(", ") + ", using last occurrence for each"); - apply_list("warning", warn); - apply_list("error", error); + curWarn.parentNode.replaceChild(warn, curWarn); + curError.parentNode.replaceChild(error, curError); + document.getElementById("warning").style.display = warn.children.length ? "block" : "none"; + document.getElementById("error").style.display = error.children.length ? "block" : "none"; }; input.addEventListener("input", apply); sessions.addEventListener("change", apply); @@ -462,17 +459,13 @@ function ready() { 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"]; } @@ -490,25 +483,23 @@ function ready() { if (linkContainer.style.display == "block") link.click(); }); - input.addEventListener("blur", save_defaults); 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)) { + // firefox silently ignores simulated link events with keyboard modifiers + // this way triggers popup blocker but nothing we can do about it + if (navigator.userAgent.indexOf("Firefox/") > -1 && (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 + // note: other methods save by link click listener // for efficiency, don't save twice save_defaults(); - window.open(link.href, "_blank", - "noopener,width=625,resizable,menubar,toolbar,location,personalbar,status,scrollbars"); - } else { + window.open(link.href, "_blank", "noopener,width=625,resizable,menubar,toolbar,location,personalbar,status,scrollbars"); + } else { // dunno what to do link.click(); } } else { @@ -40,7 +40,7 @@ select { } #link { - font-size: 120%; + font-size: 1.4em; } #error { |