553 lines
20 KiB
JavaScript
553 lines
20 KiB
JavaScript
// ES6 feature detection
|
|
(function () {
|
|
window.isES6 = false;
|
|
try {
|
|
new Function([
|
|
"// Arrow functions",
|
|
"() => {};",
|
|
"",
|
|
"// Class support",
|
|
"class __ES6FeatureDetectionTest {}",
|
|
"",
|
|
"// Object initializer property and method shorthands",
|
|
"let es6a = true;",
|
|
"let es6b = {",
|
|
" es6a,",
|
|
" es6c() { return true; },",
|
|
" es6d: [1, 2, 3],",
|
|
"};",
|
|
"",
|
|
"// Object destructuring",
|
|
"let { es6c, es6d } = es6b;",
|
|
"",
|
|
"// Spread operator",
|
|
"let es6e = [...es6d, 4];",
|
|
"",
|
|
"// Ternary operator",
|
|
"let es6f = es6a ? 'ternary' : 'no ternary';",
|
|
"",
|
|
"// Nullish coalescing",
|
|
"es6a ??= 10;",
|
|
].join("\n"))();
|
|
window.isES6 = true;
|
|
} catch (e) {}
|
|
})();
|
|
|
|
// Display warning if ES6 detection failed
|
|
window.onload = function () {
|
|
if (window.isES6 == false) {
|
|
document.getElementById("obsolete_browser_alert").innerHTML =
|
|
'<div class="alert alert-danger" role="alert" style="text-align: center;"><strong>WARNING! Unsupported browser!</strong><br />It looks like you\'re using an old browser.<br />This website works best with modern browsers such as the latest versions of Chrome, Firefox, Safari, and Edge.<br />If you continue with this browser, many parts of this site will not work and you will see unexpected results.</div>';
|
|
}
|
|
};
|
|
|
|
const hamburgerComponent = {
|
|
template: `<div class="bigger-fancy-text">
|
|
<i v-bind:class="item.icon" aria-hidden="true"></i>
|
|
<strong>{{ item.description }}</strong>
|
|
</div>`,
|
|
props: ["item"],
|
|
};
|
|
|
|
const navigComponent = {
|
|
// Fixed: Removed invalid nested <a> elements (WCAG 4.1.1)
|
|
// Changed outer <a> to <div> and made dropdown-toggle a <button>
|
|
template: `<nav class="navbar navbar-expand navbar-light main-nav-container" aria-label="Main navigation">
|
|
<div class="container-fluid">
|
|
<ul class="nav navbar-nav" id="navbar-center">
|
|
<li v-for="(navmenu, navkey) in navlistofmenus"
|
|
v-bind:key="navmenu.id"
|
|
class="dropdown main-nav-dropdown"
|
|
>
|
|
<button class="dropdown-toggle ga-main-navbar"
|
|
type="button"
|
|
data-bs-toggle="dropdown"
|
|
aria-haspopup="true"
|
|
v-bind:aria-expanded="navmenu.isOpen ? 'true' : 'false'"
|
|
@click="toggleDropdown(navmenu)"
|
|
@keydown.escape="closeDropdown(navmenu)"
|
|
>
|
|
<span class="caret-text">{{ navkey }}</span>
|
|
<span class="fancy-caret"><i class="fas fa-angle-down" aria-hidden="true"></i></span>
|
|
</button>
|
|
<ul class="dropdown-menu fade dropdown-margin"
|
|
v-bind:aria-label="navkey + ' submenu'"
|
|
>
|
|
<li v-for="item in navmenu.data"
|
|
v-bind:key="item.id"
|
|
>
|
|
<a class="dropdown-item searchmenu"
|
|
v-bind:aria-label="item.description + (item.target_blank ? ' (opens in new tab)' : '')"
|
|
v-bind:href="item.link"
|
|
v-bind:target="item.target_blank"
|
|
>
|
|
<div class="bigger-fancy-text">
|
|
<i v-bind:class="item.icon" aria-hidden="true"></i>
|
|
<strong>{{ item.description }}</strong>
|
|
<i v-if="item.target_blank" class="fas fa-external-link-alt external-link-icon" aria-hidden="true"></i>
|
|
</div>
|
|
</a>
|
|
</li>
|
|
</ul>
|
|
</li>
|
|
</ul>
|
|
</div>
|
|
</nav>`,
|
|
props: ["navlistofmenus"],
|
|
methods: {
|
|
toggleDropdown(navmenu) {
|
|
// Toggle the isOpen state for aria-expanded
|
|
navmenu.isOpen = !navmenu.isOpen;
|
|
},
|
|
closeDropdown(navmenu) {
|
|
navmenu.isOpen = false;
|
|
}
|
|
}
|
|
};
|
|
|
|
const onesearchComponent = {
|
|
// Fixed: Added autocomplete="off" to search input (WCAG 1.3.5)
|
|
// Note: autocomplete="off" is appropriate here as this is a library search, not a standard web search
|
|
template: `<form class="onesearch-jumbotron"
|
|
name="searchPrimoForm1"
|
|
ref="oneSearchForm"
|
|
role="search"
|
|
method="get"
|
|
action="https://cuny-kb.primo.exlibrisgroup.com/discovery/search"
|
|
enctype="application/x-www-form-urlencoded; charset=utf-8"
|
|
aria-label="Search the library catalog"
|
|
>
|
|
<!-- default is "everything" option suggested from OLS widget builder -->
|
|
<input name="facet" :value="facet" type="hidden"/>
|
|
<input name="mfacet" :value="mfacet" type="hidden" />
|
|
<input name="vid" value="01CUNY_KB:CUNY_KB" type="hidden" />
|
|
<input name="tab" value="Everything" type="hidden" />
|
|
<input name="search_scope" value="IZ_CI_AW" type="hidden" />
|
|
<input name="mode" value="basic" type="hidden" />
|
|
<input name="highlight" value="true" type="hidden" />
|
|
<input name="displayMode" value="full" type="hidden" />
|
|
<input name="bulkSize" value="10" type="hidden" />
|
|
<input name="dum" value="true" type="hidden" />
|
|
<input name="displayField" value="all" type="hidden" />
|
|
<input name="pcAvailabiltyMode" value="false" type="hidden" />
|
|
<input name="query" ref="primoQueryString" type="hidden" />
|
|
<div id="onesearch-header">
|
|
<a href="https://cuny-kb.primo.exlibrisgroup.com/discovery/search?tab=Everything&vid=01CUNY_KB:CUNY_KB&lang=en">
|
|
<img class="image-fail onesearchsubmit" src="https://d2jv02qf7xgjwx.cloudfront.net/accounts/16298/images/onesearch_logo2.png" alt="OneSearch" />
|
|
</a>
|
|
</div>
|
|
<div class="form-group" id="flex-search-form">
|
|
<label class="visually-hidden" for="primoQueryTemp">Search terms</label>
|
|
<div class="input-group zero-margin form-width" id="blue-border2">
|
|
<input class="form-control inherit-height-from-flex"
|
|
name="queryTemp"
|
|
id="primoQueryTemp"
|
|
ref="primoQueryTempString"
|
|
type="search"
|
|
v-model="searchstring"
|
|
aria-label="Search terms"
|
|
placeholder="Enter search term here"
|
|
autocomplete="off"
|
|
/>
|
|
</div>
|
|
<div class="input-group zero-margin" id="blue-border3">
|
|
<input type="submit"
|
|
class="btn btn-light form-control onesearchsubmit inherit-height-from-flex"
|
|
value="Search"
|
|
@click.stop.prevent="submitSearch"
|
|
/>
|
|
</div>
|
|
</div>
|
|
<fieldset id="radios">
|
|
<legend class="visually-hidden">Limit search to</legend>
|
|
|
|
<input type="radio"
|
|
name="radio1"
|
|
id="booksradio"
|
|
@click="selectradio('rtype,include,books', '')"
|
|
>
|
|
<label for="booksradio">Books</label>
|
|
|
|
<div class="radiocontainer">
|
|
<input type="radio"
|
|
name="radio1"
|
|
id="articlesradio"
|
|
@click="selectradio('tlevel,include,peer_reviewed', 'rtype,include,articles,1')"
|
|
>
|
|
<label for="articlesradio">Articles (Peer reviewed)</label>
|
|
</div>
|
|
|
|
<div class="radiocontainer">
|
|
<input type="radio"
|
|
name="radio1"
|
|
id="everythingradio"
|
|
@click="selectradio('', '')"
|
|
>
|
|
<label for="everythingradio">Everything</label>
|
|
</div>
|
|
</fieldset>
|
|
<div id="advanced">
|
|
<strong>
|
|
<a href="https://cuny-kb.primo.exlibrisgroup.com/discovery/search?vid=01CUNY_KB:CUNY_KB&lang=en&mode=advanced">Advanced</a>
|
|
</strong>
|
|
</div>
|
|
</form>`,
|
|
methods: {
|
|
selectradio(radiooutputfacet, radiooutputmfacet) {
|
|
this.facet = radiooutputfacet; // store the data from the radio selection
|
|
this.mfacet = radiooutputmfacet;
|
|
},
|
|
submitSearch() {
|
|
this.$refs.primoQueryString.value = `any,contains,${this.$refs.primoQueryTempString.value.replace(
|
|
/[,]/g,
|
|
" "
|
|
)}`; // vueified OLS widget code
|
|
this.$refs.oneSearchForm.submit(); // submit the form
|
|
},
|
|
},
|
|
data() {
|
|
return {
|
|
facet: "", // initialize the data from the radio selection
|
|
mfacet: "",
|
|
};
|
|
},
|
|
};
|
|
|
|
const { createApp } = Vue;
|
|
|
|
const app1 = createApp({
|
|
components: {
|
|
"navig-component": navigComponent,
|
|
"hamburger-component": hamburgerComponent,
|
|
},
|
|
data() {
|
|
return {
|
|
isDark: false,
|
|
hamburger: [
|
|
{
|
|
link: "https://cuny-kb.primo.exlibrisgroup.com/discovery/search?tab=Everything&vid=01CUNY_KB:CUNY_KB&lang=en",
|
|
icon: "fas fa-search fa-fw bigger-icon",
|
|
description: "OneSearch",
|
|
target_blank: "",
|
|
id: 1,
|
|
},
|
|
{
|
|
link: "https://library.kbcc.cuny.edu/az.php",
|
|
icon: "fas fa-database fa-fw bigger-icon",
|
|
description: "Databases A to Z",
|
|
target_blank: "",
|
|
id: 2,
|
|
},
|
|
{
|
|
link: "https://library.kbcc.cuny.edu/guides",
|
|
icon: "fas fa-telescope fa-fw bigger-icon",
|
|
description: "Research Guides",
|
|
target_blank: "",
|
|
id: 3,
|
|
},
|
|
{
|
|
link: "https://library.kbcc.cuny.edu/faq",
|
|
icon: "fas fa-question-circle fa-fw bigger-icon",
|
|
description: "FAQ",
|
|
target_blank: "",
|
|
id: 4,
|
|
},
|
|
{
|
|
link: "https://library.kbcc.cuny.edu/calendar",
|
|
icon: "fas fa-clock fa-fw bigger-icon",
|
|
description: "Library Hours",
|
|
target_blank: "",
|
|
id: 5,
|
|
},
|
|
{
|
|
link: "https://library.kbcc.cuny.edu/sitemap",
|
|
icon: "fas fa-location-arrow fa-fw bigger-icon",
|
|
description: "Site Map",
|
|
target_blank: "",
|
|
id: 6,
|
|
},
|
|
],
|
|
navlistofmenus: {
|
|
"Find It": {
|
|
id: 1,
|
|
isOpen: false, // Added for dynamic aria-expanded (WCAG 4.1.2)
|
|
data: [
|
|
{
|
|
link: "https://library.kbcc.cuny.edu/az.php",
|
|
icon: "fas fa-database fa-fw bigger-icon",
|
|
description: "Databases A to Z",
|
|
target_blank: "",
|
|
id: 1,
|
|
},
|
|
{
|
|
link: "https://cuny-kb.primo.exlibrisgroup.com/discovery/npsearch?vid=01CUNY_KB:CUNY_KB&search_scope=all",
|
|
icon: "fas fa-newspaper fa-fw bigger-icon",
|
|
description: "Newspaper Search",
|
|
target_blank: "",
|
|
id: 2,
|
|
},
|
|
{
|
|
link: "https://cuny-kb.primo.exlibrisgroup.com/discovery/search?vid=01CUNY_KB:CUNY_KB&tab=CourseReserves&search_scope=CourseReserves",
|
|
icon: "fas fa-cloud-download-alt fa-fw bigger-icon",
|
|
description: "Course Reserves",
|
|
target_blank: "",
|
|
id: 3,
|
|
},
|
|
{
|
|
link: "https://cuny-kb.primo.exlibrisgroup.com/discovery/jsearch?vid=01CUNY_KB:CUNY_KB",
|
|
icon: "fas fa-book fa-fw bigger-icon",
|
|
description: "Search for Specific Journals",
|
|
target_blank: "",
|
|
id: 4,
|
|
},
|
|
{
|
|
link: "https://library.kbcc.cuny.edu/academicworks",
|
|
icon: "fas fa-archive fa-fw bigger-icon",
|
|
description: "CUNY Academic Works",
|
|
target_blank: "_blank",
|
|
id: 5,
|
|
},
|
|
{
|
|
link: "https://kbcc.textbookx.com/institutional/index.php",
|
|
icon: "fas fa-cash-register fa-fw bigger-icon",
|
|
description: "KBCC Bookstore",
|
|
target_blank: "_blank",
|
|
id: 6,
|
|
},
|
|
],
|
|
},
|
|
Services: {
|
|
id: 2,
|
|
isOpen: false, // Added for dynamic aria-expanded (WCAG 4.1.2)
|
|
data: [
|
|
{
|
|
link: "https://kbcc-cuny.illiad.oclc.org/illiad/logon.html",
|
|
icon: "fas fa-books fa-fw bigger-icon",
|
|
description: "Interlibrary Loan",
|
|
target_blank: "_blank",
|
|
id: 1,
|
|
},
|
|
{
|
|
link: "https://library.kbcc.cuny.edu/libraryservices/informationliteracy",
|
|
icon: "fas fa-chalkboard-teacher fa-fw bigger-icon",
|
|
description: "Book a Library Instruction Session",
|
|
target_blank: "",
|
|
id: 2,
|
|
},
|
|
{
|
|
link: "https://library.kbcc.cuny.edu/mediaservices",
|
|
icon: "fas fa-photo-video fa-fw bigger-icon",
|
|
description: "Media Services",
|
|
target_blank: "",
|
|
id: 3,
|
|
},
|
|
{
|
|
link: "https://kbcc-cuny.libanswers.com/form?queue_id=6967",
|
|
icon: "fas fa-shopping-basket fa-fw bigger-icon",
|
|
description: "Suggest a Book for Purchase",
|
|
target_blank: "",
|
|
id: 4,
|
|
},
|
|
{
|
|
link: "https://kbcc-cuny.libwizard.com/id/8cdb3f1a787de3c307a8cf5d75cad406",
|
|
icon: "fas fa-bookmark fa-fw bigger-icon",
|
|
description: "Suggest an Item to Add to Reserves",
|
|
target_blank: "",
|
|
id: 5,
|
|
},
|
|
],
|
|
},
|
|
"About Us": {
|
|
id: 3,
|
|
isOpen: false, // Added for dynamic aria-expanded (WCAG 4.1.2)
|
|
data: [
|
|
{
|
|
link: "https://library.kbcc.cuny.edu/about-us/directory",
|
|
icon: "fas fa-address-book fa-fw bigger-icon",
|
|
description: "Faculty & Staff Directory",
|
|
target_blank: "",
|
|
id: 1,
|
|
},
|
|
{
|
|
link: "https://library.kbcc.cuny.edu/newarrivals",
|
|
icon: "far fa-mail-bulk fa-fw bigger-icon",
|
|
description: "New Arrivals",
|
|
target_blank: "",
|
|
id: 2,
|
|
},
|
|
{
|
|
link: "https://library.kbcc.cuny.edu/about-us/liaisons",
|
|
icon: "fas fa-theater-masks fa-fw bigger-icon",
|
|
description: "Subject Liaisons",
|
|
target_blank: "",
|
|
id: 3,
|
|
},
|
|
{
|
|
link: "https://library.kbcc.cuny.edu/social",
|
|
icon: "far fa-hashtag fa-fw bigger-icon",
|
|
description: "Social Media",
|
|
target_blank: "",
|
|
id: 4,
|
|
},
|
|
{
|
|
link: "https://cuny-kb.alma.exlibrisgroup.com/discovery/collectionDiscovery?vid=01CUNY_KB:CUNY_KB",
|
|
icon: "fa-solid fa-star fa-fw bigger-icon",
|
|
description: "Featured Collections",
|
|
target_blank: "",
|
|
id: 5,
|
|
},
|
|
],
|
|
},
|
|
"Location & Hours": {
|
|
id: 4,
|
|
isOpen: false, // Added for dynamic aria-expanded (WCAG 4.1.2)
|
|
data: [
|
|
{
|
|
link: "https://tour.kingsborough.edu/",
|
|
icon: "fas fa-map-marked-alt fa-fw bigger-icon",
|
|
description: "Campus Map",
|
|
target_blank: "",
|
|
id: 1,
|
|
},
|
|
{
|
|
link: "https://library.kbcc.cuny.edu/calendar",
|
|
icon: "fas fa-clock fa-fw bigger-icon",
|
|
description: "Library Hours",
|
|
target_blank: "",
|
|
id: 2,
|
|
},
|
|
],
|
|
},
|
|
Help: {
|
|
id: 5,
|
|
isOpen: false, // Added for dynamic aria-expanded (WCAG 4.1.2)
|
|
data: [
|
|
{
|
|
link: "https://library.kbcc.cuny.edu/askalibrarian",
|
|
icon: "fas fa-book-reader fa-fw bigger-icon",
|
|
description: "Ask A Librarian",
|
|
target_blank: "",
|
|
id: 1,
|
|
},
|
|
{
|
|
link: "https://library.kbcc.cuny.edu/faq",
|
|
icon: "fas fa-question-circle fa-fw bigger-icon",
|
|
description: "FAQ",
|
|
target_blank: "",
|
|
id: 2,
|
|
},
|
|
{
|
|
link: "https://library.kbcc.cuny.edu/guides",
|
|
icon: "fas fa-telescope fa-fw bigger-icon",
|
|
description: "Research Guides and Tutorials",
|
|
target_blank: "",
|
|
id: 3,
|
|
},
|
|
{
|
|
link: "https://library.kbcc.cuny.edu/ENGLISH24",
|
|
icon: "fas fa-question fa-fw bigger-icon",
|
|
description: "How to Use the Library",
|
|
target_blank: "",
|
|
id: 4,
|
|
},
|
|
],
|
|
},
|
|
},
|
|
};
|
|
},
|
|
methods: {
|
|
toggleTheme() {
|
|
this.isDark = !this.isDark;
|
|
this.applyTheme(this.isDark);
|
|
localStorage.setItem("kbcc-theme", this.isDark ? "dark" : "light");
|
|
},
|
|
applyTheme(isDark) {
|
|
if (isDark) {
|
|
document.body.setAttribute("data-bs-theme", "dark");
|
|
} else {
|
|
document.body.removeAttribute("data-bs-theme");
|
|
}
|
|
this.updateBackgroundOverlay(isDark);
|
|
},
|
|
updateBackgroundOverlay(isDark) {
|
|
var el = document.querySelector(".kbcc-background-image");
|
|
if (el && el.style.backgroundImage) {
|
|
// Extract the url() part from the existing background-image
|
|
var match = el.style.backgroundImage.match(/url\([^)]+\)/);
|
|
if (match) {
|
|
var overlay = isDark
|
|
? "rgba(0,0,0,0.4)"
|
|
: "rgba(255,255,255,0.6)";
|
|
el.style.backgroundImage =
|
|
"linear-gradient(to bottom, " + overlay + " 0%, " + overlay + " 100%), " + match[0];
|
|
}
|
|
}
|
|
}
|
|
},
|
|
mounted() {
|
|
// Theme initialization
|
|
var stored = localStorage.getItem("kbcc-theme");
|
|
var prefersDark = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
|
|
if (stored) {
|
|
this.isDark = stored === "dark";
|
|
} else {
|
|
this.isDark = prefersDark;
|
|
}
|
|
this.applyTheme(this.isDark);
|
|
|
|
// Listen for OS preference changes (only applies when no manual override)
|
|
var self = this;
|
|
window.matchMedia("(prefers-color-scheme: dark)").addEventListener("change", function(e) {
|
|
if (!localStorage.getItem("kbcc-theme")) {
|
|
self.isDark = e.matches;
|
|
self.applyTheme(self.isDark);
|
|
}
|
|
});
|
|
|
|
// Dynamic aria-expanded for hamburger menu (WCAG 4.1.2)
|
|
const hamburger = document.getElementById('hamburger');
|
|
const hamburgerContainer = document.getElementById('hamburger-container');
|
|
|
|
if (hamburger && hamburgerContainer) {
|
|
// Update aria-expanded when dropdown opens/closes (BS5 native events)
|
|
hamburgerContainer.addEventListener('shown.bs.dropdown', function() {
|
|
hamburger.setAttribute('aria-expanded', 'true');
|
|
});
|
|
hamburgerContainer.addEventListener('hidden.bs.dropdown', function() {
|
|
hamburger.setAttribute('aria-expanded', 'false');
|
|
});
|
|
}
|
|
}
|
|
});
|
|
app1.mount("#app1");
|
|
|
|
const app2 = createApp({
|
|
components: {
|
|
"onesearch-component": onesearchComponent,
|
|
},
|
|
});
|
|
app2.mount("#app2");
|
|
|
|
// Randomly set the background image for .kbcc-background-image
|
|
(function () {
|
|
const images = [
|
|
"https://libapps.s3.amazonaws.com/accounts/16298/images/library_front_view.jpg",
|
|
"https://d2jv02qf7xgjwx.cloudfront.net/accounts/16298/images/copy_for_it.jpg",
|
|
"https://d2jv02qf7xgjwx.cloudfront.net/accounts/16298/images/Library_Website_Background_Images_005.jpg",
|
|
"https://d2jv02qf7xgjwx.cloudfront.net/accounts/16298/images/Library_Website_Background_Images_002.jpg",
|
|
];
|
|
var picked = images[Math.floor(Math.random() * images.length)];
|
|
var el = document.querySelector(".kbcc-background-image");
|
|
if (el) {
|
|
// Check theme for correct overlay color
|
|
var stored = localStorage.getItem("kbcc-theme");
|
|
var prefersDark = window.matchMedia && window.matchMedia("(prefers-color-scheme: dark)").matches;
|
|
var isDark = stored ? stored === "dark" : prefersDark;
|
|
var overlay = isDark ? "rgba(0,0,0,0.4)" : "rgba(255,255,255,0.6)";
|
|
el.style.backgroundImage =
|
|
"linear-gradient(to bottom, " + overlay + " 0%, " + overlay + " 100%), url('" + picked + "')";
|
|
}
|
|
})();
|
|
|