PageSourceSearch

https://www.brighton.ac.uk/_design/js/brighton.js?v=8

js brighton.ac.uk collected 2026-09-24 08:30:03 UTC 18,630 bytes, 545 lines download raw bytes

1(function($) {
2
3	$(function() {
4	
5	/* assign various parts of the DOM to variables to cache them and reduce script execution time */
6	$window = $(window);
7	var $docBody = $('body');
8	var $pageBodyDiv = $('#page-body');
9	
10	var $megaMenus = $('#header').find('div.sys_mega-menu');
11	var $megaMenuLinks = $('#header').find('a.sys_mega-menu-link');
12	var $megaMenuSubLinks = $('#mega-menu-study-here').find('.sys_groupheadnolink');
13	var $breadcrumbSubNavs = $('#header').find('ul.sys_subnav');
14	var $breadcrumbsTopLinks = $('#active-breadcrumbs').find('li.sys_toplink');
15	var $topNavListItems = $('#header').find('#top-nav li');
16	
17	var breadcrumbsExists = false;
18	if ($('#active-breadcrumbs').length) { 
19		breadcrumbsExists = true; 
20		$breadcrumbs = $('#active-breadcrumbs');
21		$('#section-nav').removeClass('sys_shadow');
22	}
23	/* end of caching variables */
24	
25	/* scripts for mega menu display */
26	$megaMenuLinks.click(function(e) {
27		e.preventDefault();
28		
29		// close any breadcrumb menus to prevent overlap 
30		$breadcrumbSubNavs.hide();
31		$breadcrumbsTopLinks.removeClass('sys_topselected');
32		$(this).blur();
33	
34		// get id of clicked on link
35		// var thisID = this.id;
36		// thisID = "#mega-menu-" + thisID;
37		
38		// select the mega menu to target, which is next to the clicked link
39		var targetMegaMenu = $(this).nextAll('.sys_mega-menu').first();
40		
41		if ( targetMegaMenu.is(":visible") ) {
42			// if chosen menu is already visible, hide all menus
43			if ($('#masthead .sys_mobile-nav-trigger').is(":visible")) {
44				$megaMenus.slideUp().promise().done(function() {
45					$('#mega-menu-study-here li').not(".sys_groupheadnolink, .sys_group-header-mobile-display").hide();
46				});
47			}
48			else {
49				$megaMenus.hide();
50			}
51			$topNavListItems.removeClass('sys_selected');
52			$megaMenuLinks.attr("aria-expanded", "false");
53			$(this).focus();
54		} else { 
55			// else hide them and then show the selected menu
56			$megaMenus.hide();
57			$megaMenuLinks.attr("aria-expanded", "false");
58			if ($('#masthead .sys_mobile-nav-trigger').is(":visible")) {
59				targetMegaMenu.slideDown();
60			} else {
61				targetMegaMenu.show().focus();
62			}
63			$topNavListItems.removeClass('sys_selected');
64			$(this).parent().addClass('sys_selected');
65			$(this).attr("aria-expanded", "true");
66		}
67	});
68	
69	// script to close the mega menu and other menus if you click elsewhere in the document
70	$('html').click(function() {
71		$megaMenus.hide();
72		$topNavListItems.removeClass('sys_selected');
73		
74		$breadcrumbSubNavs.hide();
75		$breadcrumbsTopLinks.removeClass('sys_topselected');
76	});
77	
78	$('#header').find('#top-nav div.sys_container').click(function(event){
79		 event.stopPropagation();
80	});
81	
82	$megaMenuSubLinks.click(function(e) {
83		if ($('#masthead .sys_mobile-nav-trigger').is(":visible")) {
84			e.preventDefault();
85			if ($(this).hasClass("sys_selected")) {
86				$('#mega-menu-study-here li').not(".sys_groupheadnolink, .sys_group-header-mobile-display").slideUp();
87				$megaMenuSubLinks.removeClass('sys_selected');
88			}
89			else {
90				$('#mega-menu-study-here li').not(".sys_groupheadnolink, .sys_group-header-mobile-display").hide();
91				$(this).siblings().slideDown();
92				$megaMenuSubLinks.removeClass('sys_selected');
93				$(this).addClass('sys_selected');
94			}
95		}
96	});
97	
98	if (breadcrumbsExists) {
99		$breadcrumbs.click(function(event){
100			 event.stopPropagation();
101		});
102	}
103	
104	if ($('#active-breadcrumbs .sys_subnav').length) {
105		$breadcrumbSubNavs.click(function(event){
106			 event.stopPropagation();
107		});
108	}
109	
110	// script to demonstrate video/image rollover state
111	// this has been replaced by the script below
112	/*$(".hover-state").hover(	
113		function () {
114			currentSrc = $(this).attr('src');
115			var parts = currentSrc.split('.');
116			var filenameOnly = parts[0];
117			var newSrc = filenameOnly + "-2." + parts[1];
118			$(this).attr('src', newSrc);
119			$(this).css('cursor', 'pointer');
120		},
121		function () {
122			$(this).attr('src', currentSrc);
123		}
124	);*/
125	
126	// script for video caption rollover state (replaces the above .hover-state function)
127	$(".sys_video-image").hover(	
128		function () {
129			$(this).find('.sys_play-arrow').addClass('sys_play-arrow-hover');
130			$(this).css('cursor', 'pointer');
131		},
132		function () {
133			$(this).find('.sys_play-arrow').removeClass('sys_play-arrow-hover');
134		}
135	);
136	
137	// script to move you back to the previous heading
138	
139	$('.sys_previous-heading-link').click(function(e) {
140		e.preventDefault();
141		
142		// get the parent section of this link
143		parentSection = $(this).parents('section');
144		// start a marker to track which section tag you're searching through
145		prevContentRow = parentSection;
146		// start a marker to flag when you've found a target heading to scroll to
147		foundTarget = false;
148		// start a marker to halt the search so it won't loop forever
149		searchComplete = false;
150		
151		while(!(searchComplete)) {
152			
153			// see if there is a section tag earlier on the page. If there is, move the marker to it
154			if (prevContentRow.prev('section').length) {
155				prevContentRow = prevContentRow.prev('section');
156			}
157			// if there isn't, end the search because you're at the top of the page already
158			else {
159				searchComplete = true;
160			}	
161			
162			if (!(searchComplete)) {
163				// search the currently marked content row
164				rowToSearch = prevContentRow;
165				// see if there are any h2 tags
166				if (rowToSearch.find('h2').length) {
167					targetHeading = rowToSearch.find('h2').first();
168					foundTarget = true;
169					searchComplete = true;
170				}
171				// if there aren't, see if there are any h3 tags
172				else if (rowToSearch.find('h3').length) {
173					targetHeading = rowToSearch.find('h3').first();
174					foundTarget = true;
175					searchComplete = true;
176				}
177				// if there still aren't, do nothing so the loop starts again
178				else {
179				
180				}
181			}
182		
183		}
184		// if you have found a target heading, scroll to it
185		if (foundTarget) {
186				//$.scrollTo(targetHeading, 750, {offset: -177} );
187				var scrollPosition = targetHeading.offset().top-177;
188				//var scrollPosition = 0;
189				 $('html, body').animate({ scrollTop: scrollPosition }, 750, 'swing');
190		}
191		
192	});
193	
194	// script for back to top button just above footer
195	$('.sys_back-to-top > a').click(function(e) {
196	
197		//$.scrollTo('#page-wrapper', 750);
198		
199		 e.preventDefault();
200		 var scrollPosition = 0;
201		 $('html, body').animate({ scrollTop: scrollPosition }, 750, 'swing');
202		
203	});
204	
205	
206	//Toggle select function
207	
208	$('.sys_toggle-select').not('.sys_toplink').click(function() {
209		if(!$(this).hasClass("sys_selected-element")){
210			$(this).addClass("sys_selected-element");
211		}
212		
213		else{
214			$(this).removeClass("sys_selected-element");
215		}
216	});
217	
218	
219	// script to make the panels alternate between grey and white - removed 30/03/17
220	/*if ($('section').length) {
221		$('section:odd').addClass('sys_grey');
222		
223		if ($('div.sys_back-to-top').length) {
224			
225			if ($('#page-body section').last().hasClass('sys_grey')) {
226				$('div.sys_back-to-top').addClass('sys_grey');
227			}
228		}
229	}*/
230	
231	// script to hide the last 'previous story' link on a page, so it doesn't sit next to the 'back to top' link
232	if ($('#page-body section .sys_previous-heading-link').length) {
233		$('#page-body section').last().find('.sys_previous-heading-link').hide();
234	}
235	
236	// mobile search bar
237	$('.sys_toggle-trigger').click(function(){
238		closeMobileNav();
239		selTog = $(this).attr('rel');
240		// added fix for Contensis stripping out rel tag on mobile search toggle
241		if ($(this).hasClass('sys_search-trigger')) { selTog = 'site-search'; }
242		if (!$(this).hasClass('sys_active-trig')) {
243			$(this).addClass('sys_active-trig');
244			$('body').addClass('sys_mobile-search-open');
245			$('.sys_' + selTog).addClass('sys_tog').show();
246		}	
247		else {
248			$(this).removeClass('sys_active-trig');
249			closeMobileSearch();
250		}
251		return false;
252	});
253	
254	function closeMobileNav() {
255		$('#top-nav .sys_site-search').hide();
256		$('#top-nav-menu').slideUp(400, function() {
257			$('body').removeClass('sys_mobile-nav-open');
258		  });
259	}
260
261	function closeMobileSearch() {
262		$('.sys_toggle-trigger').removeClass('sys_active-trig');
263        $('body').removeClass('sys_mobile-search-open');
264        $('.sys_site-search').hide();
265	}
266	
267	$('.sys_mobile-nav-trigger').click(function(){	
268		closeMobileSearch();
269		if(($('body').hasClass('sys_mobile-nav-open'))) {
270			closeMobileNav();
271			return false; 
272		}
273		else {
274			$('#top-nav-menu').slideDown(400);
275			$('body').addClass('sys_mobile-nav-open');
276			return false
277		}
278	}); 
279	/* copy section nav into mobile menu if present */
280	if ($('#section-menu').length) {
281		var sectionNav = $('#section-menu li').clone();
282		sectionNav.addClass('sys_sec-in-meg sys_hidden-desktop');
283		var navLis = $('<li class="sys_hidden-desktop sys_mobile-mega-header sys_sec-in-meg" id="mobile-section-nav">In this section...</li>')
284			.add(sectionNav)
285			.add('<li class="sys_hidden-desktop sys_mobile-mega-header sys_mobile-mega-header-main">Main site links</li>'); 
286		var targetLi = $('#top-nav .sys_close').first();
287		navLis.insertAfter(targetLi);
288	}
289	
290	$(window).bind('ready resize', function(){
291		var w = $(window).width();
292		if((w > 980) && ($('body').hasClass('sys_mobile-nav-open'))) {
293			closeMobileNav();
294			$('#top-nav-menu').show();
295		}
296		if(w > 990) { $('#top-nav-menu, .sys_footer-links ul').removeAttr("style"); }
297	});
298	
299	/* #Sigchange# */
300	
301	if (navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i)) {
302		var viewportmeta = document.querySelector('meta[name="viewport"]');
303		if (viewportmeta) {
304			viewportmeta.content = 'width=device-width, minimum-scale=1.0, maximum-scale=1.0, initial-scale=1.0';
305			document.body.addEventListener('gesturestart', function () {
306				viewportmeta.content = 'width=device-width, minimum-scale=0.25, maximum-scale=1.6';
307			}, false);
308		}
309	}
310	
311	//Remove date suffixes from Calendar listing (Events Module)
312	$("#Calendar__List.sys_datarepeatercontrol .sys_groupheader span").text(function () {
313		return $(this).text().replace(/(\d{1,2})(th|st|nd|rd)/, "$1");
314	});
315	
316	//Load Google Maps markers if a sys_gmap360_canvas exists on the page
317	if(jQuery(".sys_gmap360_canvas").length >
317 0) jQuery.getScript("//www.brighton.ac.uk/_design/js/360/gmap360v2.js?v=5");
318	
319	//Improve Zengenti's default FormModule datePicker implementation (use setTimeout to wait for .hasDatepicker classes to be assigned)
320	if(typeof jQuery.datepicker !== "undefined") setTimeout(function(){
321		jQuery(".hasDatepicker").datepicker( "option", "changeYear", true );
322		jQuery(".hasDatepicker").datepicker( "option", "changeMonth", true );
323		//Student datepicker
324		jQuery(".dobDatepicker .hasDatepicker").datepicker( "option", "yearRange", "c-40:+0" );
325		jQuery(".dobDatepicker .hasDatepicker").datepicker( "option", "defaultDate", "-18y -6m" );
326		//Alumni datepicker
327		jQuery(".aluDatepicker .hasDatepicker").datepicker( "option", "yearRange", "c-110:+0" );
328	}, 1000);
329	
330	
331	function scrollToPageAnchor(anchorName, topOffset) {
332		topOffset = typeof topOffset !== 'undefined' ? topOffset : 164;
333		var scrollTarget = anchorName;
334		// new campaign page template uses id #page-title instead of #page-heading
335		// use this to apply a different offset to the anchor link scrolling 
336		if ($('#page-title').length) {
337			topOffset = 16;
338		}
339		scrollPosition = $(scrollTarget).offset().top-topOffset;
340		$('html, body').animate({ scrollTop: scrollPosition }, 750, 'swing');	
341	}
342	
343	// anchor link scripts
344	// when an anchor link is clicked on a page
345	$('#page-body a[href^="#"]').click(function(e) {
346		var scrollTarget = $(this).attr('href');
347		if ($(scrollTarget).length && (scrollTarget !== "#app-pop") && (scrollTarget !== "#app-pop-pg")) { 
348			e.preventDefault();
349			scrollToPageAnchor(scrollTarget);
350		}
351	});
352	
353	$('.sys_skiplinks a[href^="#page-body"]').click(function(e) {
354		if ($('#page-body').length) { 
355			e.preventDefault();
356			scrollToPageAnchor('#page-body');
357			$('#page-body').attr('tabindex', -1).on('blur focusout', function () {
358				$(this).removeAttr('tabindex');
359			}).focus();
360		}
361	});
362	
363	
364	// SCRIPTS FROM TAB-CONTROLLER.JS FROM THIS POINT TO END OF JQUERY - MOVED HERE AS PART OF NEW TAB BEHAVIOUR ON MOBILES
365	
366	// script to build the set of headings for a group of tabs
367	// targets the element with the class 'tabHeading' on each tab and then builds them into a list
368	// first list item has the class 'selected' added to it.
369	tabsBuilt = false;
370	if ($('.sys_section-content').length) {
371	  var tabCounter = 1;
372	  $('.sys_section-content').each(function(){
373	
374		var setOfTabs = $(this).children('.sys_section-content-tab');
375		
376		if (setOfTabs.length > 1) {
377			buildList = '<ul class="sys_section-tabs" role="tablist">';
378			var firstPass = true;
379			
380			setOfTabs.each(function(){
381				// build desktop tabs
382				grabbedHeading = $(this).find('.sys_tabHeading').first().text();
383				cleanedHeading = grabbedHeading.replace(/[^a-zA-Z0-9]/g, '-');
384				var tabControllerId = cleanedHeading + '-' + tabCounter;
385				var tabId = tabControllerId + '-tab';
386				var openerId = tabControllerId + '-mob';
387	
388				$(this).attr('id', tabId);
389				$(this).attr('role', 'tabpanel');
390				$(this).attr('aria-labelledby', tabControllerId + ' ' + openerId);
391	
392				if (firstPass) {
393					liToAdd = '<li class="sys_selected sys_firstTabLi" role="presentation"><a id="' + tabControllerId + '" href="#" role="tab" aria-selected="true" aria-controls="'+ tabId +'">' + grabbedHeading + '</a></li>';
394				}
395				else {
396					liToAdd = '<li role="presentation"><a id="' + tabControllerId + '" href="#" role="tab" aria-selected="false" aria-controls="'+ tabId +'">' + grabbedHeading + '</a></li>';
397				}
398				
399				buildList = buildList + liToAdd;
400		
401				// build mobile expanders
402				var linkDiv = '<div class="sys_tabs-opener" style="">';
403				if (firstPass) {
404					linkDiv = linkDiv +  '<a id="' + openerId + '" href="#" class="sys_opener-open" role="button" aria-expanded="true" aria-controls="'+ tabId +'">' + grabbedHeading + '</a></div>';
405				}
406				else {
407					linkDiv = linkDiv +  '<a id="' + openerId + '" href="#" role="button" aria-expanded="false" aria-controls="'+ tabId +'">' + grabbedHeading + '</a></div>';
408				}
409				$(this).before(linkDiv);
410	
411				tabCounter++;
412				firstPass = false;
413	
414			});
415		
416			buildList = buildList + '</ul>';
417			$(this).before(buildList);
418			// display only the first tab in the group
419			setOfTabs.hide();
420			// this class helps reset the page when changing from mobile to desktop layouts
421			setOfTabs.first().show().addClass('sys_firstTab');
422		
423		}
424		else if ( setOfTabs.length == 1 ) {
425			// this class helps reset the page when changing from mobile to desktop layouts
426			setOfTabs.first().addClass('sys_firstTab');
427		}
428		tabsBuilt = true;
429	  });
430	}
431	
432	
433		
434	// scripts to control the display of sets of tabs within content areas, e.g. course in detail
435	// all the multiple parents could probably be simplified
436	$('.sys_section-tabs li a').click(function(e) {
437		e.preventDefault();
438		
439		// get id of clicked on link
440		var thisID = $(this).attr('id');
441		targetID = "#" + thisID + "-tab";
442		$(this).parent().parent().parent().children('.sys_section-content').children('div.sys_section-content-tab').hide();
443		$(this).blur();
444		$(targetID).show();
445	
446		// set selected class on correct tab link only
447		$(this).parent().parent().children('li').removeClass('sys_selected').children('a').attr('aria-selected', 'false');
448		$(this).parent().addClass('sys_selected').children('a').attr('aria-selected', 'true');
449	
450		//refresh Google Maps if there are any in the target tab
451		if ($(targetID + ' .sys_gmap360_canvas').length) {
452			initializeMaps();
453		}
454		//refresh Leaflet Maps if there are any on page in case they were initiaised in a hidden tab
455		if(typeof maps != 'undefined' && maps.length){
456			var len = maps.length;
457			for(var i=0; i<len; i++){
458				if(typeof maps[i].invalidateSize == 'function'){
459					maps[i].invalidateSize();
460				} 
461			}
462		}	
463		
464	});
465	
466	// script to control opening and closing of mobile tab expanders
467	$('.sys_tabs-opener a').click(function(e) {
468		e.preventDefault();
469		
470		// get id of clicked on link
471		var thisID = $(this).attr('id');
472		targetID = "#" + thisID.replace("-mob", "-tab");
473		$(targetID).slideToggle();
474		$(this).blur()
475		if ($(this).hasClass('sys_opener-open')) {
476			$(this).removeClass('sys_opener-open').attr('aria-expanded', 'false');
477		}
478		else {
479			$(this).addClass('sys_opener-open').attr('aria-expanded', 'true');
480		}
481	
482		//refresh Google Maps if there are any in the target tab
483		if ($(targetID + ' .sys_gmap360_canvas').length) {
484			initializeMaps();
485		}
486		//refresh Leaflet Maps if there are any on page in case they were initiaised in a hidden tab
487		if(typeof maps != 'undefined' && maps.length){
488			var len = maps.length;
489			for(var i=0; i<len; i++){
490				if(typeof maps[i].invalidateSize == 'function'){
491					maps[i].invalidateSize();
492				} 
493			}
494		}	
495		
496	});
497	
498	// scripts for page rating form
499	$('.sys_rating-form .sys_hiddenfield input').slice(1).attr('value', window.location.href);
500	$('.sys_rating-form-title').click(function(e) { 
501		if ($('.sys_rating-form').hasClass('sys_flyout-open')) { 
502			$('.sys_rating-form').slideUp().removeClass('sys_flyout-open'); 
503			$('.sys_back-to-top > a').css('z-index', '40');  
504		} 
505		else { 
506			$('.sys_rating-form').slideDown().addClass('sys_flyout-open'); 
507			$('.sys_back-to-top > a').css('z-index', '5');  
508			} 
509	}); 
510	$('.sys_star-rating span').hover(function() {$(this).prevAll('span').find('label').toggleClass('hovered'); });  
511	$('.sys_star-rating label').each(function() {$(this).attr('title', $(this).text()); });  
512	$('.sys_star-rating label').click(function() {
513		var labelsToStar= $(this).parent().prevAll('span').find('label'); 
514		$('.sys_star-rating label').removeClass('hovered-sel'); 
515		labelsToStar.addClass('hovered-sel'); 
516	});
517	
518	
519	// footer menus behaviour for mobile layout
520	$('.sys_footer-links h2').click(function(e) {
521		e.preventDefault();
522		if ($(window).width() < 990) {
523			$(this).siblings('ul').first().slideToggle();
524		}
525	});	
526
527	// fix to open Cookiebot preference centre from old links
528	if ($('.optanon-toggle-display').length) {
529		$('.optanon-toggle-display').click(function(e){ e.preventDefault; window.Cookiebot.show(); }).css('cursor', 'pointer');
530	}
531		
532	}); //close $(function() {
533})(jQuery); //END brighton.js
534
535function initialAnchorScroll(topOffset) {
536	topOffset = typeof topOffset !== 'undefined' ? topOffset : 164;
537	if (window.location.hash) {
538		var scrollTarget = window.location.hash;
539		scrollTarget = scrollTarget.replace(/[&=]/g, '');
540		if (jQuery(scrollTarget).length) {
541			var scrollPosition = jQuery(scrollTarget).offset().top-topOffset;
542			jQuery('html, body').animate({ scrollTop: scrollPosition }, 0);
543		}
544	}
545} // end of initialAnchorScroll function

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.