PageSourceSearch

https://darwinproject.ac.uk/sites/all/themes/drupal-cambridge-theme-master/js/custom.js?s7csui

js darwinproject.ac.uk collected 2026-09-24 09:18:33 UTC 45,068 bytes, 1,179 lines download raw bytes

1(function($) {
2
3//create singleton to namespace js
4if (!projectlight) {
5  var projectlight = {};
6}
7
8//set up initial page variables - cached Jquery variables
9projectlight.init = function(){
10	
11	//temporary debugging element to allow developer to see exact screen width during development
12	$("body").append("<p style='color:red;z-index:100;position:absolute;top:5px;left:5px' id='pagewidth'></p>")
13	
14	//caching variables to refer to DOM elements in code
15	projectlight.$window = $(window);
16	projectlight.$wrap = $(".campl-wrap");
17	projectlight.$rows = $(".campl-row");
18
19	//header items
20	projectlight.$globalHdrCtrl = $("#global-header-controls");
21	projectlight.$siteSearchBtn = $("#site-search-btn");
22	projectlight.$quicklinks = $(".campl-quicklinks");
23
24	//navigation items
25	projectlight.$globalNavOuter = $(".campl-global-navigation-outer");
26	projectlight.$globalNavLI = $(".campl-global-navigation li");
27	
28	//instantiate footer columns on page load
29	projectlight.$localFooter = $('.campl-local-footer');
30	projectlight.$globalFooter = $('.campl-global-footer');
31
32	projectlight.$localFooterColumns = projectlight.$localFooter.find('.campl-column3');
33	projectlight.$globalFooterColumns = projectlight.$globalFooter.find('.campl-column3');
34		
35	//set namespaced variable to determine layout of menu
36	//using modernizr to detect if media query is valid and has been triggered
37	if(Modernizr.mq('only screen and (max-width: 767px)')){
38		projectlight.mobileLayout  = true;
39		
40		//call function to remove uniform column height in footers for mobile layout
41		projectlight.removeGlobalNavigationColumnHeight();
42		projectlight.removeNavigationColumnHeight();
43		projectlight.removeSectionListChildrenColumnHeight();
44		projectlight.removeContentColumnHeight();
45		projectlight.removeFooterColumnsHeight();
46	
47	}else{
48		projectlight.mobileLayout  = false;	
49		
50		//call function to create uniform column height in footers for desktop/tablet users
51		projectlight.setGlobalNavigationColumnHeight();
52		projectlight.setNavigationColumnHeight();
53		projectlight.setSectionListChildrenColumnHeight();
54		projectlight.setContentColumnHeight();
55		projectlight.setFooterColumnsHeight();
56	}
57	
58	//if media queries are not supported set a fixed width container to prevent fluid layout breaking in IE and other browsers which do no support MQ
59	if(!Modernizr.mq('only all')){ 
60		projectlight.$wrap.addClass("campl-fixed-container");
61	}
62
63	//dynamically append Global navigation controls for javascript
64	projectlight.$globalHdrCtrl.prepend('<a href="" class="campl-open-menu ir" id="open-menu">View menu</a>');
65	projectlight.$siteSearchBtn.prepend('<a href="#" class="campl-icon-search-btn ir" id="open-search">Search</a>');
66	projectlight.$quicklinks.prepend('<a href="#" class="campl-open-quicklinks clearfix"><span class="campl-quicklinks-txt">Quick links</span><span class="campl-icon-dropdown ir"></span></a>')
67	projectlight.$globalNavOuter.append('<a href="#" class="campl-close-menu" >Close</a>')
68	
69	//cache variables for DOM elements
70	projectlight.$searchDrawer = $('.campl-search-drawer')
71	projectlight.$navigationDrawer = $('.campl-global-navigation-drawer')
72	
73	//INSTANTIATE QUICKLINKS DROP DOWN MENU
74	// header quicklinks
75	projectlight.$quicklinks.find('ul').hide();
76	
77	//get campl-quicklinks-list from page and clone into new container underneath the button inside quicklinks container
78	$('.campl-quicklinks-list').clone().appendTo(projectlight.$quicklinks).addClass("column12 clearfix");
79	
80	$(".campl-open-quicklinks").bind('click', function(e){
81		//shut other open panels nav and search
82		projectlight.$searchDrawer.removeClass("campl-search-open");
83		projectlight.$navigationDrawer.removeClass("campl-navigation-open");
84		projectlight.$globalNavOuter.removeClass("campl-drawer-open");
85		//deselect any previously clicked links
86		projectlight.$globalNavLI.removeClass("campl-selected");
87		
88		projectlight.$quicklinks.toggleClass("campl-quicklinks-open");
89		e.preventDefault();
90	})
91	
92	
93	//open search bound click event to open search bar drawer in page
94	$("#open-search").bind('click', function(e){
95		//shut other open panels nav and quicklinks
96		projectlight.$navigationDrawer.removeClass("campl-navigation-open");
97		projectlight.$globalNavOuter.removeClass("campl-drawer-open");
98		projectlight.$quicklinks.removeClass("campl-quicklinks-open");
99		$("body").removeClass("campl-navigation-open");
100		projectlight.localNav.hideMenu();
101		//deselect any previously clicked links
102		projectlight.$globalNavLI.removeClass("campl-selected");
103		
104		projectlight.$searchDrawer.toggleClass("campl-search-open");
105		e.preventDefault();
106	})
107	
108	//ensure drop down closes if you click outside of it. Binding click event to entire page
109	$('html').bind('click', function(e){
110		if(!$(e.target).hasClass("campl-open-quicklinks") && !$(e.target).hasClass("campl-icon-dropdown") && !$(e.target).hasClass("campl-quicklinks-txt")){
111			projectlight.$quicklinks.removeClass("campl-quicklinks-open");
112		}
113	})
114	
115	//Bound click event to global nav button for mobile users to allow them to open the navigation in side drawer
116	$("#open-menu").bind('click', function(e){
117		//shut other open panels search and quicklinks
118		projectlight.$searchDrawer.removeClass("campl-search-open");
119		projectlight.$quicklinks.removeClass("campl-quicklinks-open");
120		projectlight.localNav.hideMenu();
121		//close main navigation drawer 
122		projectlight.$globalNavOuter.removeClass("campl-drawer-open");
123		//deselect any previously clicked links
124		projectlight.$globalNavLI.removeClass("campl-selected");
125		
126		$("body").toggleClass("campl-navigation-open"); //added class to body instead so whole page can be moved to the right
127		e.preventDefault();
128	})
129	
130	$(".campl-close-menu").bind('click', function(e){
131		//close main navigation drawer 
132		$(e.target).parent().removeClass("campl-drawer-open");
133		//remove selected class from nav item clicked
134		$(".campl-global-navigation li").removeClass("campl-selected")
135		e.preventDefault();
136		
137	})
138	
139	
140	//bound click event to primary navigation items for desktop view to allow users to browse the navigation in a megadropdown
141	//the campl-no-drawer items are links that click straight through to a page instead of opening a mega dropdown
142	$(".campl-global-navigation a").not(".campl-no-drawer").bind('click', function(e){
143		var linkClicked = $(e.target);
144		linkClicked.parent().addClass("campl-selected");
145		var $drawer = $(linkClicked.attr('href'));
146		
147		//shut other open panels search and quicklinks
148		projectlight.$searchDrawer.removeClass("campl-search-open");
149		projectlight.$quicklinks.removeClass("campl-quicklinks-open");
150
151		//if the navigation is open, and the drawer showing is the same as the link clicked then close drawer and close navigation container
152		if($drawer.hasClass("campl-drawer-open")){
153			projectlight.$globalNavLI.removeClass("campl-selected");
154			projectlight.$navigationDrawer.removeClass("campl-navigation-open");
155			projectlight.$globalNavOuter.removeClass("campl-drawer-open");
156		}else{
157			//else show close existing drawer and show new drawer, keep open navigation container
158			
159			//close any other drawers that are open
160			projectlight.$globalNavOuter.not($drawer).removeClass("campl-drawer-open");
161			//deselect any previously clicked links
162			projectlight.$globalNavLI.not(linkClicked.parent()).removeClass("campl-selected");
163			
164			//toggle the open drawer class
165			projectlight.$navigationDrawer.addClass("campl-navigation-open");
166			$drawer.toggleClass("campl-drawer-open");
167		}		
168
169		e.preventDefault();
170	})
171	
172	//Show page elements which have been hidden to handle FOUC
173	projectlight.$globalHdrCtrl.show();
174
175	//fake last psuedo class to help layout in IE8. This removes the double borders from nested LI
176	//which was visually confusing
177	$(".campl-section-list-children ul").each(function(){
178		$(this).find("li").last().addClass("campl-last")
179	})
180	
181}
182
183
184projectlight.setGlobalNavigationColumnHeight = function(){
185	//for each section, get children, measure height of each, set height of each child
186	$(".campl-global-navigation-outer").each(function(){
187		var $childrenOfList = $(this).find(".campl-global-navigation-container");
188		var maxColumnHeight = Math.max($childrenOfList.eq(0).height(), $childrenOfList.eq(1).height(), $childrenOfList.eq(2).height());
189		
190		//why is the col height 0 here?
191		// console.log(maxColumnHeight)
192		//hardcoded to 300 for time being
193		$childrenOfList.css({'min-height':300} )
194	})
195}
196
197projectlight.removeGlobalNavigationColumnHeight = function(){
198	$('.campl-global-navigation-container').removeAttr("style");
199}
200
201projectlight.setSectionListChildrenColumnHeight = function(){
202	//for each section list, get section-list-children, measure height of each, set height of each child
203	$(".campl-section-list-row").each(function(){
204		var $childrenOfList = $(this).find(".campl-section-list-children");
205		var maxColumnHeight = Math.max($childrenOfList.eq(0).height(), $childrenOfList.eq(1).height(), $childrenOfList.eq(2).height());
206		$childrenOfList.css({'min-height':maxColumnHeight} )
207	})
208}
209
210projectlight.removeSectionListChildrenColumnHeight = function(){
211	$('.campl-section-list-children').removeAttr("style");
212}
213
214projectlight.setNavigationColumnHeight = function(){
215	//reset all values to begin with to ensure layout is changing on ipad orientation change
216	$('.campl-global-navigation li a').removeAttr("style");
217
218	var maxColumnHeight = Math.max($('.campl-global-navigation li a').eq(0).height(), $('.campl-global-navigation li a').eq(1).height(), $('.campl-global-navigation li a').eq(2).height());
219	$('.campl-global-navigation li a').css({'min-height':maxColumnHeight} )
220};
221
222//force main content column min-height to the same height as the navigation column	
223projectlight.setContentColumnHeight = function(){
224	
225	//reset before adding further height
226	$('.campl-tertiary-navigation, .campl-secondary-content, .campl-main-content').removeAttr("style");
227
228	var secondaryContentRecessedHeight = 0;
229
230	if($('.campl-secondary-content').hasClass("campl-recessed-secondary-content")) {
231		secondaryContentRecessedHeight = ($('.campl-secondary-content').parent().width() / 100) * 36.6;
232	}
233
234	var maxColumnHeight = Math.max($('.campl-secondary-content').height() - secondaryContentRecessedHeight, $('.campl-tertiary-navigation').height(), $(".campl-main-content").height());
235
236	if($('.campl-tertiary-navigation').length > 0){
237		$('.campl-tertiary-navigation, .campl-secondary-content, .campl-main-content').css({'min-height':maxColumnHeight+50} )
238		//uneven height distribution on nav and sec columns
239	}else{
240		$('.campl-tertiary-navigation, .campl-secondary-content, .campl-main-content').css({'min-height':maxColumnHeight} )
241		$('.campl-secondary-content').css({'min-height':maxColumnHeight +50} 	)
242	}
243
244
245	if($('.campl-secondary-content').hasClass("campl-recessed-secondary-content")){
246		$('.campl-secondary-content').css({'min-height':maxColumnHeight + secondaryContentRecessedHeight } 	)
247	}
248	
249	
250	$('.campl-secondary-content').show();
251};
252
253projectlight.removeNavigationColumnHeight = function(){
254	//had to remove style attribute, as setting height back to auto would not work
255	$('.campl-global-navigation li a').removeAttr("style");
256};
257
258projectlight.removeContentColumnHeight = function(){
259	//had to remove style attribute, as setting height back to auto would not work
260	$('.campl-tertiary-navigation, .campl-secondary-content, .campl-main-content').removeAttr("style");
261	$('.campl-secondary-content, .campl-main-content').show();
262};
263
264projectlight.setFooterColumnsHeight = function(){
265	var highestglobalFooter = Math.max(projectlight.$globalFooterColumns.eq(0).height(), projectlight.$globalFooterColumns.eq(1).height(),projectlight.$globalFooterColumns.eq(2).height(),projectlight.$globalFooterColumns.eq(3).height())
266	var highestLocalFooter = Math.max(projectlight.$localFooterColumns.eq(0).height(), projectlight.$localFooterColumns.eq(1).height(),projectlight.$localFooterColumns.eq(2).height(),projectlight.$localFooterColumns.eq(3).height())
267	
268	projectlight.$localFooterColumns.height(highestLocalFooter);
269	projectlight.$globalFooterColumns.height(highestglobalFooter);
270};
271
272projectlight.removeFooterColumnsHeight = function(){
273	projectlight.$localFooter.height("auto");
274	projectlight.$localFooterColumns.height("auto");
275	projectlight.$globalFooterColumns.height("auto");
276};			
277
278
279
280
281projectlight.initTables = function(){
282	/* FULLY EXPANDED RESPONSIVE TABLE SOLUTION */
283	//responsive table solution
284	var $tableContainer = $(".campl-responsive-table");
285	
286	//cycle through all responsive tables on page to instantiate open link
287	$tableContainer.each(function (i) {
288		var $table = $(this).find("table");
289		var summary = "";
290		
291		//hide table
292		$table.hide(); //might have to use positioning to prevent it being hidden from screen readers
293		
294		//suck out caption and summary to display above link
295		var openTable = "<div class='campl-open-responsive-table'><a href='#' class='campl-open-responsive-table-link'>Click to open table " + $table.find("caption").text() + "</a>"+ summary + "</div>"
296
297		//insert button to open table in page
298		$(this).prepend(openTable);
299		
300		//create collapse button and hide until table is opened
301		$(this).find('.campl-open-responsive-table').append("<a href='#' class='campl-collapse-table'>Collapse table</a>");
302		
303		$('.campl-collapse-table').hide();
304		
305		//collapse table and restore open link to user
306		$(this).find('.campl-collapse-table').bind("click", function(e){
307			var $tableContainer = $(e.target).parent().parent();
308			$tableContainer.removeClass("campl-expanded-table");
309			$table.removeClass("campl-full-width-table").hide();
310			//show appropriate open link
311			$(e.target).parent().find('.campl-open-responsive-table-link').show();
312			//hide collapse link 
313			$(e.target).hide();
314			e.preventDefault();
315		})
316		
317
318		//open table on bind click event
319		$(this).find(".campl-open-responsive-table-link").bind("click", function(e){
320			$(e.target).parent().parent().addClass("campl-expanded-table");
321			$table.addClass("campl-full-width-table");
322			$table.show();
323			//show appropriate close link
324			$(e.target).parent().find('.campl-collapse-table').show();
325			//hide open link 
326			$(e.target).hide();
327			e.preventDefault();	
328		});
329		
330	})
331
332	/* VERTICAL STACKING TABLE */
333	var $verticalTable = $(".campl-vertical-stacking-table");
334	
335	//cycle through every vertical table on the page and insert table headers into table cells for mobile layout 
336	$verticalTable.each(function (i) {
337		//for vertical stacking tables need to read the text value of each TH in turn and assign to the headers array
338		var $tableHeaders = $(this).find('thead').find("th");
339		
340		var headerTextArray = [];
341		//insert th value into every data set row in order
342		//each loop to push into data array
343		$tableHeaders.each(function (i) {
344			headerTextArray.push($(this).text());
345		});
346		
347		//for every row, insert into td append before text in td insert span to handle styling of header and data
348		var $verticalTableRows = $(this).find("tr");
349		
350		$verticalTableRows.each(function (i) {
351			//need to find all children of the table rows, (and not just table data cells)
352			var $tableCells = $(this).children();
353			$tableCells.each(function (i) {
354				if(headerTextArray[i]) {
355					$(this).prepend("<span class='campl-table-heading'>"+headerTextArray[i]+"</span>")
356				}
357			})
358
359		})
360		
361	})
362	
363}	
364
365/**  LOCAL NAVIGATION CONTROLS updated code taken from sony.com **/
366//this controls both the dropdowns and graphical style of the desktop navigation and the sliding panels of the mobile navigation
367projectlight.localNav=(function(){
368	var $openMenu,$navigation,$navContainer,$topUL,$topListItems,$allListItems,$links,$secondLevelListitems,$allMenuLists,n,$allNavLinks,menuPosition=0,m;
369	return{
370		init:function(u){
371			$navigation = $(".campl-local-navigation");
372			
373			//only run if there is navigation available in the page 
374			if($navigation.length > 0){
375				//need to remove btn from IE7 and IE8 - feature detection for media queries
376				if(Modernizr.mq('only all')){
377					$navigation.prepend('<p class="campl-closed campl-menu-btn" id="menu-btn"><a href="#"><span>Menu</span> <span class="campl-menu-btn-arrow"></span></a></p>')	
378					$openMenu = $("#menu-btn a");
379
380					//bind click event to button to open menu for mobile
381					$openMenu.click(function(){
382						var $linkClicked = $(this);
383
384						//close main nav drawer or search panel if open
385						$("body").removeClass("campl-navigation-open");
386						projectlight.$searchDrawer.removeClass("campl-search-open");
387
388						if($linkClicked.parent().hasClass("campl-closed")){
389							displayMenu("show")
390						}else{
391							displayMenu("hide")
392						}
393						return false
394					});
395				}
396				//call function to instantiate children and title structure
397				setupNavigation();
398			}
399		},
400		hideMenu:function(){
401			$openMenu = $("#menu-btn a");
402			$navContainer = $(".campl-local-navigation-container");
403			$openMenu.parent().removeClass("campl-open").addClass("campl-closed");
404			$navContainer.css({left:-9999});
405		},
406		resetLocalNavigation:function(){
407			//remove all sub classes
408			$navContainer = $(".campl-local-navigation-container"),
409			$allListItems = $navContainer.find("li");
410			$allListItems.removeClass("campl-sub");
411		
412			//reset sub classes onto correct items
413			if(projectlight.mobileLayout){
414				$allListItems.has('ul').addClass("campl-sub");
415			}else{
416				$allListItems.not($allListItems.find("li")).has('ul').addClass("campl-sub");
417			}
418		}
419	};
420	function setupNavigation(){
421		
422		$navContainer = $navigation.children(".campl-local-navigation-container"),
423		$topUL = $navContainer.children("ul");
424		$topListItems = $topUL.children("li");
425		$allListItems = $topUL.find("li");
426		
427		$secondLevelListitems = $topListItems.children("li");
428		$allMenuLists = $topListItems.find("ul");
429		$dropdownListItems = $topListItems.find("li");
430		$allNavLinks = $allMenuLists.find("a");
431		
432		$currentPageListitem = $navigation.find(".campl-current-page");
433		currentSectionNo = 0;
434		
435		m=$topUL.height();
436		
437		//need to dynamically append sub class to elements that have children
438		$allListItems.has('ul').addClass("campl-sub")
439		
440		//this needs to be added to browsers with media queries only to prevent IE7 adding gap above items with children in desktop layout
441		//for all the list items that have children append forward indicator arrow
442		if(Modernizr.mq('only all')){
443			$('.campl-sub').children("a").css({"position":"relative"}
443).append("<span class='campl-menu-indicator campl-fwd-btn'></span>")
444		}
445		//dynamically mark top level list items
446		$topListItems.addClass("campl-top")
447		
448
449		//for each list item with a class of sub, clone the link and prepend it to the top of the nested UL beneath
450		//this will act as the overview link in the top level and the UL title in the mobile navigation
451		
452		//for each UL walk up the DOM to find the title of the UL in the section above, prepend this link as the back button to the section before for
453		//the mobile navigation
454		$navigation.find(".campl-sub").each(function(){
455			var $childUl = $(this).children("ul");
456				$childUl.prepend('<li class="campl-title"><a href="'+ $(this).children("a").attr('href') +'">'+$(this).children("a").text()+'</a></li>');	
457			if($(this).hasClass('campl-top')){
458				$childUl.prepend('<li class="campl-back-link"><a href="#"><span class="campl-back-btn campl-menu-indicator"></span>Back to section home</a></li>');
459			}else{
460				
461				$childUl.prepend('<li class="campl-back-link"><a href="#"><span class="campl-back-btn campl-menu-indicator"></span>'+ $(this).parent().children(".campl-title").children("a").html()  +'</a></li>');
462			}	
463
464		})
465		
466	
467		//reset menu structure after title links have been appended to ensure they are always created for full mobile structure
468		//desktop menu only needs to go one level deep
469		$allListItems.removeClass("campl-sub");
470		if(projectlight.mobileLayout){
471			$allListItems.has('ul').addClass("campl-sub");
472		}else{
473			$allListItems.not($allListItems.find("li")).has('ul').addClass("campl-sub");
474		}
475		
476		//declare array of links after title link has been created
477		$links = $topListItems.find("a");
478
479		//set current class to first level navigation so mobile menu can always open at least
480		//one level of menu. This style makes the UL visible
481		$topUL.addClass("campl-current");
482		
483
484	//hover classes not required for mobile and tablet layouts
485	//hover event should only trigger from top level items not children of top level
486	$topListItems.hover(
487			function(){
488			if(!projectlight.mobileLayout){ 
489				$(this).addClass("campl-hover")
490			}
491		},function(){
492			if(!projectlight.mobileLayout){
493				$(this).removeClass("campl-hover")
494			}
495		});
496	
497		
498		//Bound click event for all links inside the local navigation. 
499		//handles moving forwards and backwards through pages or opening dropdown menu
500		$links.click(function(e){
501			var $linkClicked = $(this),
502			$listItemClicked = $linkClicked.parent();
503			
504			if($listItemClicked.hasClass("campl-title") && Modernizr.mq('only screen and (max-width: 767px)')){
505				e.preventDefault();	
506			}else{
507				if($listItemClicked.hasClass("campl-sub")){
508					//slide mobile or tablet menu forward 
509					if(projectlight.mobileLayout){
510						slideMenu("forward");
511						$listItemClicked.addClass("campl-current")
512					}else{
513						if($listItemClicked.hasClass("campl-top") && $linkClicked.hasClass("campl-clicked")){
514							//toggle open navigation if top level without sub level link clicked
515							closeSubNavigation();
516						}else{
517							//display sub menu for the desktop view for the item clicked
518							showSubNavigation($linkClicked, e)
519						}
520					}
521				e.preventDefault();	
522				}else{
523					if($listItemClicked.hasClass("campl-back-link")){
524						slideMenu("back");
525						$linkClicked.parent().parent().parent().addClass("campl-previous");
526						$linkClicked.parent().parent().addClass("campl-previous");
527						return false
528					}
529				}
530			}
531			
532		});
533		
534		//ensure dropdown or sliding panels are set to the correct width if the page changes and also on first load
535		$(window).resize(function(){
536			setMenuWidth();
537		});
538		if(projectlight.mobileLayout){
539			setMenuWidth();
540		}
541	}
542	
543	//sets the width of the sub menus, for either the desktop dropdown, 
544	//or to ensure the mobile sliding panels stretch to fill the whole screen
545	function setMenuWidth(){
546		
547		var widthOfMenu = 480;
548
549		if(Modernizr.mq('only screen and (max-width: 767px)')){	
550			widthOfMenu = $(window).width()
551
552			$topUL.width(widthOfMenu);
553			$allMenuLists.width(widthOfMenu).css("left",widthOfMenu);
554			if($openMenu.parent().hasClass("campl-open")){
555				$navContainer.css("left",-(menuPosition*widthOfMenu))
556			}
557			//should be adding mobile state to dom elem
558			$navContainer.addClass("campl-mobile");
559		}else{
560			
561			//this resets the mobile structure by removing all the unwanted classes 
562			//so the show/hide will work for the desktop dropdown menu
563			if($navContainer.hasClass("campl-mobile")){
564				$openMenu.parent().removeClass("campl-open").addClass("campl-closed");
565				$navContainer.find(".campl-current").removeClass("campl-current");
566				$navContainer.attr("style","").removeAttr("style");
567				$topUL.attr("style","").removeAttr("style");
568				$allMenuLists.attr("style","").removeAttr("style")
569			}
570		}
571	}
572	//shows the desktop dropdown menus by positioning them on or off screen
573	function displayMenu(actionSent){
574		if(actionSent == "show"){
575
576			//Walk up through DOM to determine nested level
577			var $currentUL = $currentPageListitem.parent();
578			currentSectionNo = 0;
579			if($currentPageListitem.length > 0){
580				if($currentPageListitem.parent().length > 0){
581					//do while this is UL
582					while ($currentUL[0].tagName === "UL")
583					{
584						$currentUL.addClass("campl-current")// this displays hidden nav sections
585						if($currentUL.parent()[0].tagName === "LI" ){
586							$currentUL.parent().addClass("campl-current") //need to add current to full path, UL and LI 	
587						}
588						$currentUL = $currentUL.parent().parent();
589						currentSectionNo ++;
590					}
591					//set current menu position depending on which nested level the active page is on		
592					menuPosition = currentSectionNo-1;
593					$navContainer.children("ul").removeClass("campl-current")
594				}
595			}else{
596				menuPosition = 0
597			}
598
599			//get current menu width
600			if(Modernizr.mq('only screen and (min-width: 768px)')){
601				widthOfMenu=480;
602			}else{
603				widthOfMenu=$(window).width();
604			}
605
606			//set left position depending which level to open menu at
607			$navContainer.css({left:-(menuPosition*widthOfMenu)});
608		
609			$openMenu.parent().removeClass("campl-closed").addClass("campl-open");
610		}else{
611			if(actionSent == "hide"){
612				$openMenu.parent().removeClass("campl-open").addClass("campl-closed");
613				$navContainer.css({left:-9999});
614				
615				//need to force top container to go away. Ghost block seemed to be staying on screen even
616				//though CSS should have removed it, this hack forces it to be hidden then removes the display
617				//style to allow it to be controlled by the CSS again
618				$navContainer.find(".campl-current").removeClass("campl-current").hide();
619				$navContainer.find(':hidden').css("display", "")
620				
621				//reset menu back to opening position
622				menuPosition = currentSectionNo-1;
623			}
624		}
625	}
626	//shows the sliding menus for the mobile navigation
627	function slideMenu(directionToSlide){
628		var widthOfMenu,
629		currentLeftPos=$navContainer.css("left");
630		currentLeftPos=parseInt(currentLeftPos.replace("px",""));
631		
632		if(Modernizr.mq('only screen and (min-width: 768px)')){
633			widthOfMenu=480;
634		}else{
635			widthOfMenu=$(window).width()
636		}			
637		
638		if(directionToSlide === "forward"){
639			menuPosition++;
640			$navContainer.stop().animate({left:currentLeftPos-widthOfMenu},300,function(){})
641		}else{
642			if(directionToSlide === "back"){
643				menuPosition--;
644				$navContainer.stop().animate({left:currentLeftPos+widthOfMenu},300,function(){
645					$navContainer.find(".campl-previous").removeClass("campl-previous").removeClass("campl-current");
646				})
647			}
648		}
649	}
650	//controls mulitple levels of dropdown navigation depending on hover and clicked classes being set
651	//nb: we have altered from the original sony code by only allowing users to open one level or
652	//dropdown menu in the desktop view
653	function showSubNavigation(linkClicked, event){
654		var $linkClicked = $(linkClicked),
655		$listItemClicked = $linkClicked.parent(),
656		$ListItemSiblings = $listItemClicked.siblings(),
657		y;
658		
659		if($linkClicked.hasClass("campl-clicked")){
660			$listItemClicked.removeClass("campl-hover");
661			$linkClicked.removeClass("campl-clicked");
662			
663			//list items beneath current with hover set
664			y = $listItemClicked.find(".campl-hover");
665			$clickedChildren = x.find(".clicked");
666			y.removeClass("campl-hover");
667			$clickedChildren.removeClass("campl-clicked")
668		}else{
669			$listItemClicked.addClass("campl-hover");
670			$linkClicked.addClass("campl-clicked");
671			
672			//for each of the list items siblings remove hover and clicked classes
673			$ListItemSiblings.each(function(){
674				var $sibling = $(this);
675				if($sibling.children("a").hasClass("campl-clicked")){
676					y = $sibling.find(".campl-hover");
677					$clickedChildren = $sibling.find(".campl-clicked");
678					$sibling.removeClass("campl-hover");
679					y.removeClass("campl-hover");
680					$clickedChildren.removeClass("campl-clicked")
681				}
682			})
683		}
684		event.preventDefault();
685	}
686	
687	//close button resets all open classes and returns the navigation back to a full closed state		
688	function closeSubNavigation(){
689		var $hoveredListItems  =$topUL.find(".campl-hover"),
690		$linksClicked = $topUL.find(".campl-clicked");
691	
692		$hoveredListItems.removeClass("campl-hover");
693		$linksClicked.removeClass("campl-clicked");
694		$secondLevelListitems.css("left",-9999)
695	}
696
697})(); //end of nav - self calling function
698
699
700//carousel instantiation
701projectlight.createCarousel = function(){
702	var carousel = {};
703
704	// set up initial carousel values and autoplay, hide other slides
705	carousel.init = function(){
706		this.carouselContainer = $(".campl-carousel").first();
707		this.slides = this.carouselContainer.find("ul.campl-slides");
708		this.currentSlide = 1;
709		this.maxSlides = this.slides.children().length;
710		this.animating = false;
711		this.endPos = 0;
712		
713		// need to determine width of carousel, container and slide item depending on screen size
714		this.carouselWidth = this.carouselContainer.width();
715
716		// need to dynamically set width of slides Ul (length of all slides plus the cloned item) and left position (length off each side * currentSlide)
717		if (this.maxSlides > 1) {
718			this.slides.css({'width': (this.carouselWidth*(this.maxSlides+2))+this.carouselWidth+'px', 'left': '-' + (this.carouselWidth * this.currentSlide)+'px'});
719		}	
720		
721	
722		// calculate lookup position table
723		this.lookupPos = [];
724
725		for(var cc = 0; cc < this.maxSlides; cc++){
726			this.lookupPos.push(-cc * parseInt(this.carouselContainer.innerWidth(), 10));
727		}
728
729		if (this.maxSlides > 1) {
730			this.carouselContainer.removeClass('campl-banner')
731			//create next and back buttons for carousel
732			this.createCarouselControls();
733
734			//append pagination indicator
735			this.createPaginationIndicator();
736			
737			// Clone first and last slides and append it to the slideshow to mimic infinite carousel functionality
738			var clonedFirstSlide = this.slides.children('li:first-child').clone();
739			this.slides.append(clonedFirstSlide);
740			var clonedLastSlide = this.slides.children('li:nth-child('+this.maxSlides+')').clone();
741			this.slides.prepend(clonedLastSlide);	
742			
743			this.slide = this.slides.find("li")
744
745			// click event on carousel direction controls
746			this.carouselControls.bind('click', this.activateDirectionButtons)
747	
748			//set width of each slide to ensure image is scaling to match fluid grid
749			this.slides.children().css({width:this.carouselWidth})
750			
751			projectlight.resetCarousel();
752
753			this.autoPlaying = true;
754			this.startAutoPlay();
755			
756			
757			
758		}else{
759			this.carouselContainer.addClass('campl-banner')
760		}
761		
762		this.carouselContainer.find("li").show();
763		
764		//instantiate caption and content text variables for handling truncation across all slides and cloned slides 
765		//has to happen after cloning so all slides are properly controlled by the truncation during resize event
766		projectlight.$slideCaption = $(".campl-slide-caption-txt");
767		projectlight.$carouselContent = $(".campl-carousel-content p");
768
769		projectlight.carouselContentItems = [];
770		projectlight.slideCaptionItems = [];
771		
772		//store array of original strings to replace when at full size
773		projectlight.$slideCaption.each(function(){
774			projectlight.slideCaptionItems.push($(this).text())
775		})
776
777		projectlight.$carouselContent.each(function(){
778			projectlight.carouselContentItems.push($(this).text())
779		})
780
781		//truncate homepage carousel content if page is thinner than tablet view but not on mobile view
782		if(Modernizr.mq('only screen and (min-width: 768px) and (max-width: 1000px)')){	
783			projectlight.$slideCaption.each(function(){
784        if($.trim($(this).text()).length>51) {
785					$(this).text($.trim($(this).text()).substring(0, 50).split(" ").slice(0, -1).join(" ") + "...")
786				}
787			})
788
789			projectlight.$carouselContent.each(function(){
790				if($.trim($(this).text()).length>36) {
791					$(this).text($.trim($(this).text()).substring(0, 35).split(" ").slice(0, -1).join(" ") + "...")
792				}
793			})
794
795		}
796	}
797
798	carousel.createPaginationIndicator = function(){
799		carousel.slides.children().each(function(i){
800			var slideNo = i+1
801			$(this).find(".campl-slide-caption").append("<span class='campl-carousel-pagination'>"+ slideNo + " of " + carousel.maxSlides + "</span>")
802		})
803	}
804	
805	//append control buttons unobtrusively if there is more than one slide in carousel
806	carousel.createCarouselControls = function(){
807		
808		var carouselControls = document.createElement('ul');
809		carouselControls.className = 'campl-unstyled-list clearfix campl-carousel-control
809s';
810		carouselControls.id = 'carousel-controls';
811	
812		var previouslistItem = document.createElement('li');
813		previouslistItem.className = "campl-previous-li";
814		var previouslink = document.createElement('a');
815		var previousArrowSpan = document.createElement('span');
816		previousArrowSpan.className = "campl-arrow-span";
817		previouslink.className = "ir campl-carousel-control-btn campl-previous";
818		var previouslinkText = document.createTextNode('previous slide');
819		previouslink.setAttribute('href', '#');
820		previouslink.appendChild(previousArrowSpan);
821		previouslink.appendChild(previouslinkText);
822		previouslistItem.appendChild(previouslink);
823		carouselControls.appendChild(previouslistItem);
824	
825		var nextlistItem = document.createElement('li');
826		nextlistItem.className = "campl-next-li";
827		var nextlink = document.createElement('a');
828		var nextArrowSpan = document.createElement('span');
829		nextArrowSpan.className = "campl-arrow-span";
830		nextlink.className = "ir campl-carousel-control-btn campl-next";
831		var nextlinkText = document.createTextNode('next slide');
832		nextlink.setAttribute('href', '#');
833		nextlink.appendChild(nextArrowSpan);
834		nextlink.appendChild(nextlinkText);
835		nextlistItem.appendChild(nextlink);
836		carouselControls.appendChild(nextlistItem);
837
838		this.carouselContainer.append(carouselControls);
839		this.carouselControls = $('#carousel-controls a');
840		this.prev = this.carouselControls.eq(0);
841		this.next = this.carouselControls.eq(1);
842		
843	};
844
845	//bound click event for carousel navigation controls
846	carousel.activateDirectionButtons = function(e){
847		carousel.stopAutoPlay();
848		var buttonClicked;
849		if(e.target.tagName === "SPAN"){
850			buttonClicked = $(e.target.parentNode);
851		}else{
852			buttonClicked = $(e.target.parentNode).find("a");
853		}
854
855		// detect which button has been clicked from event delegation + call animate slides and pass direction val
856		if(buttonClicked.hasClass('campl-previous')){
857			carousel.animateSlides('left');
858		}
859		if(buttonClicked.hasClass('campl-next')){
860			carousel.animateSlides('right');
861		}
862		e.preventDefault();
863	};
864
865
866	//autplay function sets time out which is called repeatedly from the animation completed call back
867	carousel.startAutoPlay = function(){
868		this.slides.queue(function() {
869			carousel.timer = window.setTimeout(function() {
870				carousel.animateSlides('right');
871			}, 6000);
872		})
873		carousel.slides.dequeue();
874	};
875
876	// stops play for reset purposes
877	carousel.stopAutoPlay = function(){
878		this.autoPlaying = false;
879		window.clearTimeout(this.timer);
880		this.slides.queue("fx", []);
881	};
882
883	//controls the slide number of the current slide, distance to scroll and animation function with callback
884	carousel.animateSlides = function(directionToScroll){
885		// check to see if gallery is not currently being animated
886		if(this.slides.filter(':animated').length === 0){
887			var endPos = 0;
888			// get current left position of slides and remove measurement notation
889			var startPos = parseInt(this.slides.css('left'));
890
891
892			if(directionToScroll !== undefined){
893				if(directionToScroll === 'left'){
894					if(carousel.currentSlide <= 1){
895						carousel.currentSlide = carousel.maxSlides;
896					}else{
897						carousel.currentSlide = carousel.currentSlide - 1;
898					}
899					endPos = startPos + carousel.carouselContainer.innerWidth();
900				}else{
901					if(carousel.currentSlide >= carousel.maxSlides){
902						carousel.currentSlide = 1;
903						endPos = 0;
904					}else{
905						carousel.currentSlide = carousel.currentSlide + 1;
906					}
907					endPos = startPos - carousel.carouselContainer.innerWidth();
908				}
909			}
910
911			this.slides.animate({left: endPos}, 2500, function(){
912				//after carousel has finished moving 
913				if(carousel.currentSlide === carousel.maxSlides){	
914					carousel.slides.css({left:(-carousel.maxSlides * carousel.carouselContainer.innerWidth())+'px'});
915				}else if(carousel.currentSlide === 1){
916					//set the position of the slides to be back to the beginning
917					carousel.slides.css({left: -carousel.carouselContainer.innerWidth()+'px'});
918
919				}
920				if(carousel.autoPlaying === true){
921					carousel.startAutoPlay();
922				}
923			});
924			
925		}
926		
927	}
928	
929	
930	
931	// Reset carousel
932	projectlight.resetCarousel = function(){
933
934		carousel.stopAutoPlay();
935
936		// need to determine width of carousel, container and slide item depending on screen size
937		carousel.carouselWidth = carousel.carouselContainer.width();
938		
939		// reset width and position of slides when page is changed
940		// need to dynamically set width of slides Ul (length of all slides plus the cloned item) and left position (length off each side * currentSlide)
941		if (carousel.maxSlides > 1) {
942			carousel.slides.css({'width': (carousel.carouselWidth*(carousel.maxSlides+2))+carousel.carouselWidth+'px', 'left': '-' + (carousel.carouselWidth * carousel.currentSlide)+'px'});
943		}	
944
945		// reset width and position of slides when page is changed
946		carousel.slides.children().css({width:carousel.carouselWidth}
946)
947	
948		// calculate lookup position table
949		carousel.lookupPos = [];
950
951		for(var cc = 0; cc < carousel.maxSlides; cc++){
952			carousel.lookupPos.push(-cc * parseInt(carousel.carouselContainer.innerWidth(), 10));
953		}
954
955		//carousel.updateControlActivation();
956		// carousel.startAutoPlay();
957
958	}
959	
960	projectlight.stopCarousel = function(){
961		carousel.stopAutoPlay();
962	};
963
964	projectlight.startCarousel = function(){
965		carousel.stopAutoPlay();
966		carousel.startAutoPlay();
967	};
968	
969	
970	carousel.init();
971	
972}
973
974//only mark external links inside of the main content area as denoted by the campl-skipTo ID
975projectlight.markExternalLinks = function(){
976	if (jQuery.browser.msie) {
977		$("#content a[href*='cam.ac.uk']").not(".campl-carousel a[href*='http://']").addClass("campl-external").attr({
978			"title": $(this).attr("title")+" (Link to an external website)"
979		})	
980	}else{
981		$('#content a').not(".campl-carousel a").filter(function(){
982			return this.hostname && !this.hostname.match(/cam.ac.uk/gi);
983		}).addClass("campl-external").attr({
984			"title": $(this).attr("title")+" (Link to an external website)"
985		})
986	}
987}
988
989//DOM ready 
990$(function() {
991
992	//instantiate all the DOM elements which require javascript rendering
993	projectlight.init();
994	projectlight.initTables();
995	projectlight.localNav.init();
996	projectlight.markExternalLinks();
997	
998	//remove click event from local nav children selected items
999	
1000	$(".campl-vertical-breadcrumb-children .campl-selected a").bind("click", function(e){
1001		e.preventDefault()
1002	})
1003
1004	//instantiate calendar
1005	if(document.getElementById('calendar')){
1006		$("#calendar").Zebra_DatePicker({
1007		    always_visible: $('.calendar-container'),
1008			format: 'dd mm yyyy',
1009			direction: true,
1010			always_show_clear:false,
1011			disabled_dates: ['15 09 2012']
1012		});
1013	}
1014	
1015	//Change event for mobile navigation list selector
1016	if(document.getElementById('navigation-select')){
1017		$("#navigation-select").bind("change", function(e){
1018			window.location = $(this).val()
1019		})
1020	}
1021	
1022	
1023	$(".campl-notifications-panel").each(function(){
1024		var $thisElem = $(this);
1025		$thisElem.append("<a href='#' class='ir campl-close-panel'>Close panel</a>");
1026		$thisElem.find('.campl-close-panel').bind("click", function(e){
1027			$(e.target).parent().remove();
1028			e.preventDefault();
1029		})
1030	})
1031	
1032	
1033	//bound click events for twitter bootstrap pills and tab elements
1034	$('#navTabs a').click(function (e) {
1035	  e.preventDefault();
1036	  $(this).tab('show');
1037	})
1038	
1039	$('#navPills a').click(function (e) {
1040	  e.preventDefault();
1041	  $(this).tab('show');
1042	})
1043	
1044	$('#searchTabs a').click(function (e) {
1045	  e.preventDefault();
1046	  $(this).tab('show');
1047	})
1048	
1049	/*$("#block-cudl-related-letters h3 a").click(function(e) {
1050		e.preventDefault();
1051		let url = $(e.target).attr("href");
1052		if (confirm("The letters contained on the Darwin Correspondence Project website may include content and language that is upsetting or offensive. The contents reflect the attitudes of the historical period in which they were created. This can include language that is racist, sexist, ableist, homophobic, and otherwise discriminatory and unacceptable today.")) {
1053			window.open(url);
1054		}
1055	});*/
1056	
1057	
1058	//instantiate height of buttons for mobile users, on carousel object
1059	if($(".campl-carousel").length){
1060		projectlight.createCarousel();
1061		//wait for DOM ready to resize buttons for mobile
1062		if(Modernizr.mq('only screen and (max-width: 767px)')){
1063			$(".campl-carousel-controls a").height($(".image-container").height())	
1064		}else{
1065			$(".campl-carousel-controls a").attr("style", "")
1066		}
1067	}
1068
1069
1070	//resize event handles changing flag layout to determine if user mode is mobile or not 
1071	//If the mode has changed the re-rendering or reset functions will be called to change the page layout
1072	projectlight.$window.resize(function() {
1073		
1074		if($(".campl-carousel").length){
1075			projectlight.resetCarousel();
1076
1077			//truncate homepage carousel content if page is thinner
1078			if(Modernizr.mq('only screen and (min-width: 768px) and (max-width: 1000px)')){	
1079				
1080				//carousel height is remaining as if text isn't being truncated
1081
1082				projectlight.$slideCaption.each(function(i){
1083						if(($.trim(projectlight.slideCaptionItems[i]).length>51)) {
1084							$(this).text($.trim(projectlight.slideCaptionItems[i]).substring(0, 50).split(" ").slice(0, -1).join(" ") + "...")
1085						}
1086					})
1087					
1088					projectlight.$carouselContent.each(function(i){
1089						if(($.trim(projectlight.slideCaptionItems[i]).length>36)) {
1090							$(this).text($.trim(projectlight.carouselContentItems[i]).substring(0, 35).split(" ").slice(0, -1).join(" ") + "...")
1091						}
1092					})
1093			}else{
1094				
1095				projectlight.$slideCaption.each(function(i){
1096					$(this).text(projectlight.slideCaptionItems[i]);
1097				})
1098			
1099				projectlight.$carouselContent.each(function(i){
1100					$(this).text(projectlight.carouselContentItems[i]);
1101				})
1102			}
1103			
1104		}
1105		
1106		//commented out debugging to help developers see page width during development
1107		//$("#pagewidth").html($(window).width());
1108		
1109
1110		//check size of columns on resize event and remove incase of mobile layout
1111		if(Modernizr.mq('only all')){
1112			//if mobile layout is triggered in media queries
1113			if(Modernizr.mq('only screen and (max-width: 767px)')){
1114				//if layout moves from desktop to mobile layout
1115				if(!projectlight.mobileLayout){
1116					//set current state flag
1117					projectlight.mobileLayout  = true;
1118					//reset main nav to un-open state
1119					projectlight.$navigationDrawer.removeClass("campl-navigation-open");
1120					projectlight.$globalNavOuter.removeClass("campl-drawer-open");
1121					projectlight.$searchDrawer.removeClass("campl-search-open");
1122					//deselect any previously clicked links
1123					projectlight.$globalNavLI.removeClass("campl-selected");
1124				
1125					//reset nav menus
1126					projectlight.localNav.resetLocalNavigation();
1127					projectlight.localNav.hideMenu();
1128				}
1129			
1130				// if media queries are supported then remove columns on mobile layout
1131				projectlight.removeGlobalNavigationColumnHeight();
1132				projectlight.removeNavigationColumnHeight();
1133				projectlight.removeContentColumnHeight();
1134				projectlight.removeSectionListChildrenColumnHeight();
1135				projectlight.removeFooterColumnsHeight();
1136				
1137				//set height of carousel buttons
1138				$(".campl-carousel-controls a").height($(".image-container").height())	
1139
1140				projectlight.mobileLayout  = true;
1141			}else{ //desktop layout code 
1142				//if page width moves from mobile layout to desktop
1143				if(projectlight.mobileLayout){
1144					//set current state flag
1145					projectlight.mobileLayout  = false;
1146
1147					//reset nav menus
1148					//hide dropdowns if open
1149					projectlight.localNav.resetLocalNavigation();
1150					projectlight.localNav.hideMenu();
1151					//close global nav drawer
1152					$("body").removeClass("campl-navigation-open");
1153				}
1154				projectlight.setGlobalNavigationColumnHeight();
1155				projectlight.setNavigationColumnHeight();
1156				projectlight.setContentColumnHeight();
1157				projectlight.setSectionListChildrenColumnHeight();
1158				projectlight.setFooterColumnsHeight();
1159				
1160				//remove fixed height on carousel buttons
1161				//set height of carousel buttons
1162				$(".campl-carousel-controls a").attr("style", "")
1163				
1164				projectlight.mobileLayout  = false;
1165			}
1166		}
1167	})
1168	
1169
1170	
1171})
1172
1173})(jQuery);
1174
1175
1176
1177
1178
1179

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.