/* * This content is licensed according to the W3C Software License at * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document * * Supplemental JS for the disclosure menu keyboard behavior */ 'use strict'; class DisclosureNav { constructor(domNode) { this.rootNode = domNode; this.controlledNodes = []; this.openIndex = null; this.useArrowKeys = true; this.topLevelNodes = [ ...this.rootNode.querySelectorAll( 'li.dropdown > a' ), ]; this.topLevelNodes.forEach((node) => { // handle button + menu if ( node.hasAttribute('aria-haspopup') ) { const menu = node.parentNode.querySelector('ul'); if (menu) { // save ref controlled menu this.controlledNodes.push(menu); // collapse menus node.setAttribute('aria-expanded', 'false'); this.toggleMenu(menu, false); // attach event listeners menu.addEventListener('keydown', this.onMenuKeyDown.bind(this)); menu.addEventListener('keyup', function (event) { event.stopPropagation(); event.preventDefault(); return false; }); node.addEventListener('click', this.onButtonClick.bind(this)); node.addEventListener('keydown', this.onButtonKeyDown.bind(this)); node.addEventListener('keyup', function (event) { event.stopPropagation(); event.preventDefault(); return false; }) } } // handle links else { this.controlledNodes.push(null); node.addEventListener('keydown', this.onLinkKeyDown.bind(this)); } }); //this.rootNode.addEventListener('focusout', this.onBlur.bind(this)); } controlFocusByKey(keyboardEvent, nodeList, currentIndex) { switch (keyboardEvent.key) { case 'ArrowUp': case 'ArrowLeft': keyboardEvent.preventDefault(); if (currentIndex > -1) { var prevIndex = Math.max(0, currentIndex - 1); nodeList[prevIndex].focus(); } break; case 'ArrowDown': case 'ArrowRight': keyboardEvent.preventDefault(); if (currentIndex > -1) { var nextIndex = Math.min(nodeList.length - 1, currentIndex + 1); nodeList[nextIndex].focus(); } break; case 'Home': keyboardEvent.preventDefault(); nodeList[0].focus(); break; case 'End': keyboardEvent.preventDefault(); nodeList[nodeList.length - 1].focus(); break; } } // public function to close open menu close() { this.toggleExpand(this.openIndex, false); } onBlur(event) { var menuContainsFocus = this.rootNode.contains(event.relatedTarget); if (!menuContainsFocus && this.openIndex !== null) { this.toggleExpand(this.openIndex, false); } } onButtonClick(event) { event.preventDefault(); var button = event.target; if (button.nodeName != 'A') { button = button.parentNode; } var buttonIndex = this.topLevelNodes.indexOf(button); var buttonExpanded = button.getAttribute('aria-expanded') === 'true'; this.toggleExpand(buttonIndex, !buttonExpanded); } onButtonKeyDown(event) { var targetButtonIndex = this.topLevelNodes.indexOf(document.activeElement); // close on escape if (event.key === 'Escape') { event.stopPropagation(); event.preventDefault(); this.toggleExpand(this.openIndex, false); return false; } // move focus into the open menu if the current menu is open else if ( this.useArrowKeys && this.openIndex === targetButtonIndex && event.key === 'ArrowDown' ) { event.preventDefault(); this.controlledNodes[this.openIndex].querySelector('a').focus(); } // handle arrow key navigation between top-level buttons, if set else if (this.useArrowKeys) { this.controlFocusByKey(event, this.topLevelNodes, targetButtonIndex); } } onLinkKeyDown(event) { var targetLinkIndex = this.topLevelNodes.indexOf(document.activeElement); // handle arrow key navigation between top-level buttons, if set if (this.useArrowKeys) { this.controlFocusByKey(event, this.topLevelNodes, targetLinkIndex); } } onMenuKeyDown(event) { if (this.openIndex === null) { return; } var menuLinks = Array.prototype.slice.call( this.controlledNodes[this.openIndex].querySelectorAll('a') ); var currentIndex = menuLinks.indexOf(document.activeElement); // close on escape if (event.key === 'Escape') { event.stopPropagation(); event.preventDefault(); this.topLevelNodes[this.openIndex].focus(); this.toggleExpand(this.openIndex, false); return false; } // handle arrow key navigation within menu links, if set else if (this.useArrowKeys) { this.controlFocusByKey(event, menuLinks, currentIndex); } } toggleExpand(index, expanded) { // close open menu, if applicable if (this.openIndex !== index) { this.toggleExpand(this.openIndex, false); } // handle menu at called index if (this.topLevelNodes[index]) { this.openIndex = expanded ? index : null; this.topLevelNodes[index].setAttribute('aria-expanded', expanded); this.toggleMenu(this.controlledNodes[index], expanded); this.topLevelNodes[index].focus(); } } toggleMenu(domNode, show) { if (domNode) { domNode.style.display = show ? 'block' : 'none'; if (show) { domNode.parentNode.classList.add('open'); } else { domNode.parentNode.classList.remove('open'); } } } updateKeyControls(useArrowKeys) { this.useArrowKeys = useArrowKeys; } } /* Initialize Disclosure Menus */ window.addEventListener( 'load', function () { var menus = document.querySelectorAll('#global-menu .nav'); var disclosureMenus = []; for (var i = 0; i < menus.length; i++) { disclosureMenus[i] = new DisclosureNav(menus[i]); } }, false ); var ua = (function () { //Navigation toggle var $searchForm; var $nav; var $studentSele; var $footer; var is_touch_device = ("ontouchstart" in window) || window.DocumentTouch && document instanceof DocumentTouch; var init = function () { // Save selectors $searchForm = $('.wrap-search-form'); // save selector $nav = $('#wrap-navigation'); $footer = $("#stickyFooter"); $('.js-activated').dropdownHover().dropdown(); $('.col-eq').colequalizer(); $('.print').click(function () { window.focus(); window.print(); }); $('.callout').each(function () { var emptyhref = false; $(this).find('a').each(function (index, element) { if (element.textContent.trim() == '') { emptyhref = true; } }); if (emptyhref) { $(this).addClass('img-only-callout'); } }); }; var searchInit = function () { var $form = $('#search-form'); if ($form.length > 0) { var $q = $form.find('input[name=q]'); $form.on('submit', function (e) { return ($q.val() != ''); }); } }; var mobileNavigation = function () { $('.navbar-toggle').on('click', function (e) { if ($(this).hasClass('collapsed')) { $(this).find('span').html('Close Menu'); } else { $(this).find('span').html('Menu'); } }); $('#global-menu').on('shown.bs.collapse', function () { var $active = $('#global-menu .dropdown.active'); if ($active.length > 0) { $.scrollTo($active, { duration: 1000, interrupt: true, onAfter: function (anchor, settings) { var $toggle = $active.find('.dropdown-toggle'); if (!$active.hasClass('open')) { $toggle.dropdown('toggle'); } } }); } }); }; var desktopNavigation = function () { // remove handlers $('#global-menu').off('shown.bs.collapse'); $('.nav-toggle-search').on('click', function (e) { e.preventDefault(); $(this).toggleClass('fa-search fa-close'); $('.wrap-search-form').toggleClass('show-search'); }); resizeHeader(); $(window).on('resize', function () { resizeHeader(); }); }; var majorsTool = function () { Vue.filter('by-school', function (values, input) { var cleanInputs = []; if (input.length == 0) { return values; } for (var i in input) { cleanInputs.push(input[i].replace(/ /g,'')); } var result = []; for (var v in values) { var major = values[v]; if(_.intersection(major.Campuses, cleanInputs).length != 0) { result.push(major); } } return result; //console.log(value) }) Vue.filter('by-program', function (values, input) { var cleanInputs = []; console.log(input); if (input.length == 0) { return values; } for (var i in input) { cleanInputs.push(input[i].replace(/ /g, '')); } var result = []; for (var v in values) { var major = values[v]; if (_.intersection(major.Schools, cleanInputs).length != 0) { result.push(major); } } return result; //console.log(value) }) Vue.filter('by-program-degree-campus', function (values, program, degree, campus) { var cleanProgram = []; var cleanDegree = []; var cleanCampus = []; var checkProgram = (program.length === 0); var checkDegree = (degree.length === 0); var checkCampus = (campus.length === 0); if (checkProgram && checkDegree && checkCampus) { setTimeout(function () { $('.stacktable.small-only').remove(); $('.primary table').removeClass('stacktable large-only'); //Maybe a little much, but just to be on the safe side. $('.primary table').stacktable(); }, 100) return values; } for (var i in program) { cleanProgram.push(program[i].replace(/ /g, '')); } for (var i in degree) { cleanDegree.push(degree[i].replace(/ /g, '')); } for (var i in campus) { cleanCampus.push(campus[i].replace(/ /g, '')); } //double check programs for (var c in cleanProgram) { var item = cleanProgram[c]; var itemSplit = item.split(","); if (itemSplit.length == 2) { var index = cleanProgram.indexOf(item); if (index > -1) { cleanProgram.splice(index, 1); cleanProgram.push(itemSplit[1]); } } } var result = []; for (var v in values) { var major = values[v]; var matchProgram = _.intersection(major.Schools, cleanProgram).length != 0; var matchDegree = _.intersection(major.Degrees, cleanDegree).length != 0; var matchCampus = _.intersection(major.Campuses, cleanCampus).length != 0; if (!checkCampus && !checkDegree && !checkProgram) { if (matchProgram && matchDegree && matchCampus) { result.push(major); } } else if (!checkDegree && !checkCampus) { if (matchDegree && matchCampus) { result.push(major); } } else if (!checkDegree && !checkProgram) { if (matchProgram && matchDegree) { result.push(major); } } else if (!checkProgram && !checkCampus) { if (matchProgram && matchCampus) { result.push(major); } } else if (!checkProgram) { if (matchProgram) { result.push(major); } } else if (!checkCampus) { if (matchCampus) { result.push(major); } } else if (!checkDegree) { if (matchDegree) { result.push(major); } } } setTimeout(function() { $('.stacktable.small-only').remove(); $('.primary table') .removeClass('stacktable large-only'); //Maybe a little much, but just to be on the safe side. $('.primary table').stacktable(); }, 100); var allFilters = program.concat(degree, campus); $("#majorFilterUpdate").html("").append("Majors have been filtered to " + result.length + " with these filters applied " + allFilters.join(', ') + ". Press enter to get to results."); return result; }) Vue.filter('weighted-search', function (values, input) { if (input == "") { return values; } var result = []; var re = new RegExp(input, "gi"); for (var v in values) { var major = values[v]; var titleResult = major.Name.match(re); var previewResult = major.Preview.match(re); var keywordResult = null; if (major.Keyword != null) { keywordResult = major.Keyword.match(re); } if(titleResult != null || previewResult != null || keywordResult != null) { var weight = 0; if (titleResult != null) { weight += titleResult.length * 300; } if (previewResult != null) { weight += previewResult.length * 200; } if (keywordResult != null) { weight += keywordResult.length * 100; } major.weight = weight; result.push(major); } } result = _.sortBy(result, function (o) { return -o.weight }); $("#majorFilterUpdate").html("").append("Majors have been filtered to " + result.length + ". Press enter to get to results."); return result; }) new Vue({ el: '#majorsTool', data: function() { return { majors: null, campuses: null, programs: null, degrees: null, name: '', selectedCampuses: [], selectedPrograms: [], selectedDegrees: [], selectedLayout: 'block', url: majorToolUrl, programsOne: null, programsTwo: null }; }, events: { 'autocomplete:selected': function (name, data) { window.location = location.protocol + '//' + location.host + location.pathname + '/detail/' + data.Id; }, 'autocomplete:showAll': function (name, term) { window.location = this.url + "?search=" + term + "&showAll=true"; } }, ready: function () { //setup grid var showAll = this.getParameterByName("showAll"); var quickSearch = this.getParameterByName("search"); if (quickSearch == null || quickSearch == "") { this.name = ""; } else { this.name = quickSearch; } if (showAll) { // GET request this.$http({ url: '/api/majors/searchmajors/term/' + quickSearch + '/session/' +sessionId, method: 'GET' }).then(function (response) { // success callback this.$set('majors', response.data); setTimeout(function () { $('.primary table').stacktable(); }, 500); $('.grid').masonry({ // options itemSelector: '.grid-item', columnWidth: 200 }); //add here $("#majorFilterUpdate").html("").append("Majors have been filtered to " + response.data.length + ". Press enter to get to results."); }, function (response) { // error callback }); $('html, body').animate({ scrollTop: $(".grid").offset().top }, 500); } else { // GET request this.$http({ url: '/api/majors/getallmajorspreview/session/' + sessionId, method: 'GET' }).then(function (response) { // success callback this.$set('majors', response.data); setTimeout(function () { $('.primary table').stacktable(); }, 500); $('.grid').masonry({ // options itemSelector: '.grid-item', columnWidth: 200 }); }, function (response) { // error callback console.log(response.data) }); } this.$http({ url: '/api/majors/getallcampuses/session/' + sessionId, method: 'GET' }).then(function (response) { // success callback var campus = this.getParameterByName("campus"); this.$set('campuses', response.data) if (campus == "" || campus == null) { } else { this.$data.selectedCampuses.push(campus); } }, function (response) { }); this.$http({ url: '/api/majors/getallprograms/session/' + sessionId, method: 'GET' }).then(function (response) { // success callback var program = this.getParameterByName("program"); var half = Math.ceil(response.data.length / 2); this.$set('programs', response.data) this.$set('programsOne', response.data.splice(0, half)); this.$set('programsTwo', response.data); if (program == "" || program == null) { } else { this.$data.selectedPrograms.push(program); } }, function (response) { }); this.$http({ url: '/api/majors/getalldegrees/session/' + sessionId, method: 'GET' }).then(function (response) { // success callback var degree = this.getParameterByName("degree"); this.$set('degrees', response.data) if (degree == "" || degree == null) { /*for (var i in response.data) { this.$data.selectedPrograms.push(response.data[i].Name) }*/ } else { this.$data.selectedDegrees.push(degree); } }, function (response) { }); }, methods: { getParameterByName: function (name, url) { if (!url) url = window.location.href; name = name.replace(/[\[\]]/g, "\\$&"); var regex = new RegExp("[?&]" + name + "(=([^]*)|&|#|$)"), results = regex.exec(url); if (!results) return null; if (!results[2]) return ''; return decodeURIComponent(results[2].replace(/\+/g, " ")); }, goToResults: function () { $(".grid .grid-item:first-child a").focus(); } }, filters: { truncate: function (string, value) { //trim the string to the maximum length var trimmedString = string.substr(0, value); //re-trim if we are in the middle of a word trimmedString = trimmedString.substr(0, Math.min(trimmedString.length, trimmedString.lastIndexOf(" "))) return trimmedString + '...'; } } }); }; var majorQuickSearch = function () { new Vue({ el: '#major-quick-search', data: function() { return { programs: null, program: null, search: "", url: majorToolUrl, } }, events: { 'autocomplete:selected': function (name, data) { window.location = this.url + '/detail/' + data.Id; }, 'autocomplete:showAll': function (name, term) { window.location = this.url + "?search=" + term + "&showAll=true"; } }, ready: function () { this.$http({ url: '/api/majors/getallprograms/session/' + sessionId, method: 'GET' }).then(function (response) { // success callback this.$set('programs', response.data) }, function (response) { }); }, methods: { searchGo: function(){ if (this.search != "" || this.program != null) { window.location = this.url + "?search=" + this.search + "&program=" + this.program } } } }); }; var studentDropdown = function () { $("#student-type-change").change(function () { var route = $("#student-type-change").val(); if(route != "") { window.location = route; } }); }; var resizeHeader = function () { var $window = $(window); var targetWidth = 'auto'; if ($window.width() > 974) { targetWidth = $('#appmenu').width() - parseInt($('body').css('fontSize').replace(/[^-\d\.]/g, '')) - 4 + 'px'; } $('.header-left').width(targetWidth); $('.header-right').css('marginLeft', targetWidth); }; var stackTables = function () { $('.primary table').stacktable(); }; var popovers = function () { $('[data-toggle="popover"]').each(function () { $(this).attr('tabindex', 0).attr('data-placement', 'auto').attr('role', 'button'); $(this).keypress(function (event) { if (event.which == 13) { $(this).popover('toggle'); } }); }); $('[data-toggle="popover"]').popover({ trigger: 'click' }); }; var landingPageImages = function () { $('.landing .col-md-5, .feed').find('img').each(function () { var imgClass = (this.width / this.height > 1) ? 'wide' : 'tall'; $(this).addClass(imgClass); }) }; var fitvids = function () { $(".container").fitVids(); }; var showhideFooter = function () { if ($(window).height() < 210) { $footer.css({ position: "relative" }); } else { $footer.css({ position: "fixed" }); } }; return { init: init, searchInit: searchInit, mobileNavigation: mobileNavigation, desktopNavigation: desktopNavigation, majorsTool: majorsTool, studentDropdown: studentDropdown, majorQuickSearch: majorQuickSearch, stackTables: stackTables, popovers: popovers, landingPageImages: landingPageImages, fitvids: fitvids, showhideFooter: showhideFooter }; })(); (function () { ua.init(); var jRes = jRespond([ { label: 'mobile', enter: 0, exit: 767 }, { label: 'tablet', enter: 768, exit: 899 }, { label: 'desktop', enter: 900, exit: 10000 } ]); // register enter and exit functions for a single breakpoint jRes.addFunc([ { breakpoint: 'mobile', enter: function () { ua.mobileNavigation(); ua.landingPageImages(); }, exit: function () { } }, { breakpoint: ['tablet', 'desktop'], enter: function () { ua.desktopNavigation(); ua.landingPageImages(); }, exit: function () { } } ]); // Global init ua.searchInit(); if ($('#majorsTool').length == 0) { ua.stackTables(); } ua.popovers(); if ($('#majorsTool').length) { ua.majorsTool(); } if ($('#major-quick-search').length) { ua.majorQuickSearch(); } ua.studentDropdown(); ua.fitvids(); ua.showhideFooter(); $(window).scroll(ua.showhideFooter).resize(ua.showhideFooter); })(this); (function(a){a.fn.buckeyeAlert=function(e){var s=a.extend({url:"//www.osu.edu/feeds/emergency-alert.rss",callback:function(){},messageClass:null,animate:true},e);return this.each(function(){var r=a(this);r.attr("aria-live","polite");a.get(s.url,function(e){var t=a(e).find("item");if(t.length){var n=a('
').addClass(s.messageClass);t.each(function(){n.append(a(this).find("description").text())});r.removeAttr("hidden").prepend(n).prepend('