PageSourceSearch

https://www.baptist.org.uk/Images/Content/2019/Templates/54496/js/script.js?V=17dec2024

js baptist.org.uk collected 2026-10-01 10:42:58 UTC 53,695 bytes, 1,250 lines download raw bytes

1/*
2	Main ChurchInsight template Javascript/JQuery file.
3	WARNING - do not edit this file unless you know exactly what you are doing.
4	Better to use the scriptOverRide.js file to add local changes to a template.
5	If you need advice, contact ChurchInsight Support.
6*/
7
8// This file runs after the web-page has loaded, as there is a "defer" attribute on the <script> tag in the HTML header.
9// The preloaded JQuery version is V1.10.2.
10
11$(document).ready(function ()
12{ 'use strict';
13
14var UA = navigator.userAgent;
15// IE is deprecated, but lots of people still use it. So we have to make some effort to support it for now.
16// IE works well with a mouse.
17var bOnIE = (UA.indexOf('Trident/') !== -1); // Trident is the rendering engine of IE. 
18 
19// Custom values set here. Change for a particular customer.
20var SlideShowDefaultButtonText = 'Read more';
21var bAddDarkenedOverlayForSlideShowCaptions = false;
22
23// #################### Define some useful functions #######################
24
25// We have to put all functions here, as OSX does not allow functions to be inside if statements.
26
27// function to turn a slice name into a selector reference for the corresponding <section> tag
28function GetSectionTagRef(SliceName) {
29	return 'section.' + SliceName + ' ';
30}
31
32var SectionTag, SectionTags; // will be used to hold required slices
33function SectionTagExists(SliceName) {
34	if (SectionTags.hasClass(SliceName)) {
35		SectionTag = SectionTags.filter(GetSectionTagRef(SliceName));
36		if (SectionTag.length !== 0) { // at least one slice exists, great. You could have more than one in theory.
37			return true;
38		}
39	}
40	SectionTag = undefined; // remove all data.
41	return false;
42}
43
44function GetRefItem(SectionTag, Ref) {
45	if (typeof Ref === "string") {
46		if (Ref === '') { // allows us to return the section tag itself.
47			return SectionTag;
48		} else {
49			return SectionTag.find(Ref);
50		}
51	} else {
52		return Ref;
53	}
54}
55
56// A function to easily set JQuery toggles.
57// SectionTag is a $ variable.
58function ApplyToggleVisibilityOnClick(SectionTag, ClickRef, ToggleRef, iDelay, bShowToggleItemInitially) {
59
60	var ClickItem = GetRefItem(SectionTag, ClickRef);
61	var ToggleItem = GetRefItem(SectionTag, ToggleRef);
62
63	if (bShowToggleItemInitially) {
64		ToggleItem.show(0);
65	} else {
66		ToggleItem.hide(0);
67	}
68	// Note we add a function here. Since we are only using calling function arguements inside the function argument,
69	// variable scoping correctly works.
70	 ClickItem.click(function () {
71		ToggleItem.toggle(iDelay);
72	});
73}
74
75function ApplyHideOnClick(SectionTag, ClickRef, ToHideRef) {
76
77	var ClickItem = GetRefItem(SectionTag, ClickRef);
78	var ToHideItem = GetRefItem(SectionTag, ToHideRef);
79
80	 ClickItem.click(function () {
81		ToHideItem.hide(0);
82	});
83}
84 
85function ApplyToggleClassOnClick(SectionTag, ClickRef, ToggleRef, ClassName) {
86
87	var ClickItem = GetRefItem(SectionTag, ClickRef);
88	var ToggleItem = GetRefItem(SectionTag, ToggleRef);
89
90	// Note we add a function here. Since we are only using calling function arguements inside the function argument,
91	// variable scoping correctly works.
92	 ClickItem.click(function () {
93		ToggleItem.toggleClass(ClassName);
94	});
95}
96
97// function to test if text exists.
98var sAttrText, sAttrText2, sAttrText3, sAttrText4; // Results come back in these variables.
99var DollarTextarea = $("<textarea/>"); // store this once.
100function TextExists(attrText, bSplit) {
101
102	if (attrText === undefined) {return false;}
103	if (attrText === null) {return false;}
104
105	var TextToProcess = attrText.trim();
106	if (TextToProcess === '') {return false;}
107
108	// decode the text, so that &amp;lt; becomes < etc.
109	// This works by turning into HTML and then turning back into text.
110	if (TextToProcess.indexOf('&') !== -1) { // we could use the .includes('&') method, but it is quite new, so some browsers can't cope.
111		TextToProcess = DollarTextarea.html(TextToProcess).text();
112	}
113	if (TextToProcess === '') {return false;}
114
115	sAttrText = ''; // set return values to blank.
116	sAttrText2 = '';
117	sAttrText3 = '';
118	sAttrText4 = '';
119	if (bSplit) {
120		var arrSplitText = TextToProcess.split('*');
121		sAttrText = arrSplitText[0].trim();
122		if (arrSplitText.length > 1) {sAttrText2 = arrSplitText[1].trim();}
123		if (arrSplitText.length > 2) {sAttrText3 = arrSplitText[2].trim();}
124		if (arrSplitText.length > 3) {sAttrText4 = arrSplitText[3].trim();}
125	} else {
126		sAttrText = TextToProcess;
127	}
128
129	return (sAttrText + sAttrText2 + sAttrText3 + sAttrText4 !== '');
130}
131
132// Function to hide a column if it contains no images.
133var SystemSlice;
134function HideDivsIfAllEmpty(ColumnClass) {
135	var ImageWrappers = SystemSlice.find('div.' + ColumnClass);
136	if (ImageWrappers.find('img').length === 0) { // have to use find not children, as img tags can be inside <a> tags.
137		ImageWrappers.hide(0);
138	}
139}
140
141// ################### Slice activation functions go here. #########################
142
143// All slide shows have the same defaults at present.
144var BxDefaultValues = {
145	mode: 'fade',
146	auto: true,
147	pause: 8000,
148	speed: 500,
149	pager: true,
150	controls: true,
151	preloadImages: 'all',
152	touchEnabled: false,
153	adaptiveHeight: true
154};
155
156var SectionTagBackup;
157function ActivateBxSlider(SliceName,bPreserveSectionTag) {
158  	if(bPreserveSectionTag){SectionTagBackup = SectionTag;}
159	if (SectionTagExists(SliceName)) { // check if slice exists, and load into SectionTag if it does
160
161        var bannerSlides = SectionTag.find('div.bannerSlides'); // use a "find" here, as structure of slices varies.
162        var gallery_ul = bannerSlides.children('ul.gallery_ul');
163        var ImageList = gallery_ul.find('img');
164        if (ImageList.length === 0) {return;} // No images, so give up.
165
166        // ul.gallery_ul must be displayed before bx-slider can be applied.
167        // So since we hide it while the page was loading, we show it now.
168        bannerSlides.show(0); // show the slice now. It was hidden by CSS.
169
170        if (ImageList.length > 1) { // carry on as normal.
171          gallery_ul.bxSlider(BxDefaultValues);
172        } else { // Just 1 image, so we don't set up the slider, but do some minor adjustments to help the CSS.
173          gallery_ul.css('margin','0px');
174          var S = '<div class="bx-wrapper"><div class="bx-viewport"></div></div>';
175          gallery_ul.wrap(S);
176        }
177
178        // Code to enable user defined text to appear over banner slides.
179        ImageList.each(function() {
180			var ThisImg = $(this);
181			if (TextExists(ThisImg.attr('alt'), true)) { // check if there is any alt text.
182				var DarkenedClass = '';
183				if (bAddDarkenedOverlayForSlideShowCaptions) {DarkenedClass = ' DarkenedOverlay';}
184				var title = '<div class="slideTitle' + DarkenedClass + '">' + sAttrText + '</div>';
185				// even if the subtitle text is empty, we keep the div for styling reasons.
186				// If there is a long caption, reduce font weight from bold to normal.
187				var FontStyle = '';
188				if (sAttrText2.length > 100) {FontStyle = ' style="font-weight:400;" ';}
189				var subtitle = '<div class="slideText' + DarkenedClass + '"' + FontStyle + '>' + sAttrText2 + '</div>';
190
191				var ButtonLink = '';
192				var ButtonText = sAttrText3;
193				if (ButtonText === '') {ButtonText = SlideShowDefaultButtonText;}
194				if (ButtonText !== '' && ButtonText !== 'none'){
195					var ButtonColor = sAttrText4;
196					if (TextExists(ThisImg.parent().attr('href'), false)) { // check for href text. NOTE: sAttrTextX values are reset.
197
198						// add button colour if we have some colour data.
199						// Check for a " character, as that will spoil our HTML.
200						if (ButtonColor !== '' && ButtonColor.indexOf('"') === -1) {
201							ButtonColor = ' style="background-color:' + ButtonColor + ' !important;border-color:' + ButtonColor + ' !important;" ';
202						}
203
204						// build the completed button link.
205						ButtonLink = '<a class="slideButton" href="' + sAttrText + '"' + ButtonColor + '>' + ButtonText + '</a>';
206					}
207				}
208
209				var caption = '<div class="caption">' + title + subtitle + ButtonLink + '</div>';
210				$(caption).insertAfter(this);
211			}
212			ThisImg.removeAttr('title'); // remove the title attribute so that pop-up text does not appear.
213	  });
214	}
215  	if(bPreserveSectionTag){SectionTag = SectionTagBackup;}
216}
217
218// define a function, so we can activate a SlickNav menu in a controlled way.
219var IEDy = 0, bEDopen = false;
220function ActivateMenu(SliceName) {
221	if (SectionTagExists(SliceName)) { // check if slice exists, and load into SectionTag if it does
222
223	  var SectionTagRef = GetSectionTagRef(SliceName);
224	  var RootMenuDeskTop = SectionTag.find('div.nav-menu').children('ul.root_menu');
225
226	  RootMenuDeskTop.slicknav({ // activate SlickNav for this slice.
227		prependTo: SectionTagRef + '> div.SlickNav_Wrapper',
228		allowParentLinks: true, // Top level items can be links
229		label: '',
230        duration:100,
231        easingOpen:'linear',
232        easingClose:'linear',
233		// Use hex escape characters here.
234		closedSymbol: '&#xe900', // a logical OR "V" symbol
235		openedSymbol: '&#xe901', // a nice up pointing ">" symbol
236		duplicate: bDesktopScreenPossible // only need to duplicate if the desktop menus are needed.
237	  });
238
239		var SlickNavLastItem = SectionTag.find('ul.slicknav_nav > li:last-child');
240		//Add extra links onto the SlickNav menu manually, to replace top-link log-out buttons etc.
241		var ExtraLink_1 = '<li class="ExtraLink Giving">
241<a class="top-link button Login" href="/Groups/374913/GivingHomeMission.aspx">GIVING<img alt="Icon" src="/Images/Content/2019/Templates/54496/images/LogoCircleArrow.png"></a></li>';
242		var ExtraLink_2 = '';//'<li class="ExtraLink ContactUs"><a class="top-link button Login ContactUs" href="/Groups/220185/Contact_Us.aspx">CONTACT US</a></li>';
243		var ExtraLink_3 = '<li class="ExtraLink SearchOpen"></li>';
244		$(ExtraLink_2 + ExtraLink_1 + ExtraLink_3).insertAfter(SlickNavLastItem);
245
246		if (bOnTouchDevice && bDesktopScreenPossible) { // have to do more work on menus.
247
248			// Having made the SlickNav menu - delete what we don't want.
249
250			SectionTag.children("div.SlickNav_Wrapper").children("div.slicknav_menu").children('ul.slicknav_nav').find('li.SlickNavNotNeeded').remove();
251
252			// deactivate the top level <a> tag in the desk-top version so touch-screens work correctly.
253			// The link goes nowhere, but retains all the styling.
254			RootMenuDeskTop.children("li.has_sub_menu").children('a').removeAttr("href");
255		}
256
257		// Add a close menu icon into slickNav.
258		var SlickNavIcon = SectionTag.find('span.slicknav_icon');
259		$('<div class="SlickNavCloseIcon"></div>').insertAfter(SlickNavIcon);
260
261		// apply all the visibility on-clicks to make the menu slice work.
262
263		// Find some commonly used items.
264		//var SearchOverlay = SectionTag.find("div.search-overlay");
265		var SlickNavBtn = SectionTag.find("a.slicknav_btn");
266      	var Mask = BodyTag.find('div.MobileMenuMask');
267
268		//ApplyToggleVisibilityOnClick(SectionTag, "li.ExtraLink.SearchOpen", SearchOverlay, 0, false);
269		//ApplyToggleVisibilityOnClick(SectionTag, "div.top-link-wrapper a:last-child", SearchOverlay, 0, false);
270		//ApplyHideOnClick(SectionTag, "img.search-close", SearchOverlay);
271		//ApplyHideOnClick(undefined, SlickNavBtn, SearchOverlay);
272		// Toggles for menu-bars and menu-close icons
273		ApplyToggleVisibilityOnClick(undefined, SlickNavBtn, SlickNavIcon, 0, true); // no delay on the toggle.
274		ApplyToggleVisibilityOnClick(SectionTag, SlickNavBtn, "div.SlickNavCloseIcon", 0, false); // no delay on the toggle.
275      	ApplyToggleVisibilityOnClick(undefined, SlickNavBtn, Mask, 0, false); // no delay on the toggle.
276      	ApplyToggleClassOnClick(SectionTag, SlickNavBtn, '', 'SlickNavFullWidth'); 
277      	SlickNavBtn.click(function(){
278          if(!bEDopen){
279            IEDy = window.pageYOffset;
280          	window.scrollTo(0,0);
281          } else {
282            window.scrollTo(0,IEDy);
283          }
284          bEDopen = !bEDopen;
285        });
286      	// Link white-eye-glass to hidden search button.
287        //var HiddenSearchBox = SearchOverlay.find('input.button');
288  		//SearchOverlay.find('img.search-EyeGlass').click(function(){HiddenSearchBox.click();}); // set up the click.
289
290		// Need autocomplete="off" to be added to the search box <input> tag.
291		// This stops horrible browser autocomplete text from appearing.
292		//SearchOverlay.find('input.text').attr("autocomplete","off");
293
294	  }
295}
296
297function ActivateArticleList4(SliceName) { // SliceName is an object, not a string.
298
299	// Get the summaries
300	var Summarys = SliceName.find('div.articleListSummary span');
301
302  // Create the links at the bottom of the article cards.
303  var j=0, iBookShelfHidden=0;
304  SliceName.find('div.articleListTitle a').each(function () {
305	var ThisAtag = $(this);
306	var OuterDiv = ThisAtag.parent().parent();
307    var titleText = ThisAtag.text().trim().toLowerCase();
308    if (titleText.endsWith(' bookshelf')) {
309      OuterDiv.remove(); // remove the whole card.
310      iBookShelfHidden++;
311    } else {
312      var titleLink = ThisAtag.attr("href");
313      var articleListLink = OuterDiv.children('.articleListLink');
314      // See if we have new link text.
315      if (TextExists(Summarys.eq(j).text(), true)) {
316          if(sAttrText.toLowerCase() === titleText){Summarys.eq(j).parent().hide();} // hide summary if exactly the same as title.
317          if (sAttrText2 !== '') {
318              articleListLink.text(sAttrText2);
319          }
320      }
321      articleListLink.wrapInner('<a href="' + titleLink + '">');
322	  // Check the tags to see if we need to put in an image.
323      if(TemplateType.startsWith('Resources')) {
324        var ImageURL = 'FileTypeUNKNOWN.png';
325        var Tags = OuterDiv.children('.articleListTags');
326        if (Tags.length === 1) {
327          var TagText = Tags.text().trim();
328          if (TagText === 'pdf' || TagText.startsWith('pdf, ') || TagText.indexOf(' pdf, ') !== -1 || TagText.endsWith(', pdf')) {ImageURL = 'FileTypePDF.png';}
329          else if (TagText === 'doc' || TagText.startsWith('doc, ') || TagText.indexOf(' doc, ') !== -1 || TagText.endsWith(', doc')) {ImageURL = 'FileTypeDOC.png';}
330          else if (TagText === 'ppt' || TagText.startsWith('ppt, ') || TagText.indexOf(' ppt, ') !== -1 || TagText.endsWith(', ppt')) {ImageURL = 'FileTypePPT.png';}
331          else if (TagText === 'xls' || TagText.startsWith('xls, ') || TagText.indexOf(' xls, ') !== -1 || TagText.endsWith(', xls')) {ImageURL = 'FileTypeXLS.png';}
332          else if (TagText === 'zip' || TagText.startsWith('zip, ') || TagText.indexOf(' zip, ') !== -1 || TagText.endsWith(', zip')) {ImageURL = 'FileTypeZIP.png';}
333          
334          else if (TagText === 'vid' || TagText.startsWith('vid, ') || TagText.indexOf(' vid, ') !== -1 || TagText.endsWith(', vid')) {ImageURL = 'FileTypeVIDEO.png';}
335          //else if (TagText === 'dvd' || TagText.startsWith('dvd, ') || TagText.indexOf(' dvd, ') !== -1 || TagText.endsWith(', dvd')) {ImageURL = 'FileTypeBUY.png';}
336          else if (TagText === 'free' || TagText.startsWith('free, ') || TagText.indexOf(' free, ') !== -1 || TagText.endsWith(', free')) {ImageURL = 'FileTypeFREE.png';}
337          else if (TagText === 'aud' || TagText.startsWith('aud, ') || TagText.indexOf(' aud, ') !== -1 || TagText.endsWith(', aud')) {ImageURL = 'FileTypeAUDIO.png';}          
338          else if (TagText === 'buy' || TagText.startsWith('buy, ') || TagText.indexOf(' buy, ') !== -1 || TagText.endsWith(', buy')) {ImageURL = 'FileTypeBUY.png';}        
339        }
340        OuterDiv.children('.articleListImage').hide(); // hide any existing image
341        var H = '<div class="articleListImage"><a href="' + titleLink + '"><img src="/Images/Content/2019/Templates/54496/images/' + ImageURL + '"></a></div>';
342        $(H).prependTo(OuterDiv);
343      }
344    }
345	j++;
346  });
347console.log('iBookShelfHidden: ' + iBookShelfHidden);
348
349  Summarys.each(function () {
350	var ThisSummary = $(this);
351	var S = ThisSummary.text();
352	if (TextExists(S, true)) {
353		sAttrText = sAttrText.replace(/\\/g,'<br>');
354		if (S !== sAttrText) {
355			ThisSummary.html(sAttrText);
356		}
357	}
358  });
359}
360
361function ActivateBlockImages(SliceName) {
362	if (SectionTagExists(SliceName)) { // check if slice exists, and load into SectionTag if it does
363		SectionTag.find("div.image_blocks img" ).each(function() {
364			if (TextExists($(this).attr('alt'), true)) { // check if there is any alt text.
365				var cardGridCaption = '<div class="image_block_title_wrapper"><div class="image_block_title">' + sAttrText + '</div><div class="image_block_text">' + sAttrText2 + '</div></div>';
366				$(cardGridCaption).insertAfter( this );
367			}
368			$(this).removeAttr('title'); // remove the title attribute so that pop-up text does not appear.
369		});
370	}
371}
372 
373// General Code to find a group notes value
374function GetGroupNotesValue(NoteName,bIsLink) {
375	var GNames = SectionTag.find('span.groupnotes_name');
376	var iGN = 0, bFinished = false, NN = NoteName + ':', NN2 = NoteName + ' (?):';
377	GNames.each(function() { // If 2 notes have the same name, then the value of the first is returned.
378		if (!bFinished) {
379			var ThisSpan = $(this);
380			var S = ThisSpan.text();
381			if(S === NN || S === NN2){
382				bFinished = true;
383			} else {
384				iGN++;
385			}
386		}
387	});
388	if (bFinished) {
389		var GValue = SectionTag.find('span.groupnotes_value').eq(iGN);
390		if (bIsLink) {
391			return GValue.find('a').attr('href');
392		} else {
393			return GValue.text();
394		}
395	}
396	return '';
397}
398
399var TemplateType = 'About Us';
400var ArticleCardDisplay = 'Full Cards';
401var ResourceSort = 'Date Ascending';
402function ActivateBannerImage(SliceName) {
403	if (SectionTagExists(SliceName)) { // check if slice exists, and load into SectionTag if it does
404
405		var bImageApplied = false;
406
407        if (TextExists(GetGroupNotesValue('Banner Image',true), false)) {
408
409          SectionTag.css('background-image','url(' + sAttrText + ')');
410          bImageApplied = true;
411
412          // background image applied, so add group name, if available.
413          if (TextExists($('head meta[name="Group Name"]').attr('content'), false)) {
414            SectionTag.find('h1').text(sAttrText);
415          } else if (TextExists(BodyTag.find('section.slice_content_page nav div.group_nav_selected > a').text(), false)) {
416            // Try and get name from side-bar GroupNav - see line above
417            SectionTag.find('h1').text(sAttrText);
418          } else if (TextExists($('head meta[name="og:title"]').attr('content'), false)) {
419            // Try the article name.
420            SectionTag.find('h1').text(sAttrText);
421            SectionTag.find('h1').addClass('SmallerFont');
422          }
423        }
424        // While we are here, get the Template Type
425        var S = GetGroupNotesValue('Template Mode',false);
426        if (S !== '') {
427          TemplateType = S;
428          if(TemplateType !== 'About Us'){
429            BodyTag.addClass(TemplateType.replace(' + ','').replace(' ','').replace(' ',''));
430          }
431        }
432
433        S = GetGroupNotesValue('Article Cards Mode',false);
434        if (S !== '') {ArticleCardDisplay = S;}
435
436        S = GetGroupNotesValue('Resource Article Sort Mode',false);
437        if (S !== '') {ResourceSort = S;} 
438      
439		if (!bImageApplied) { // Didn't find background image, so hide the whole slice.
440			SectionTag.hide();
441			if (SectionTagExists('slice_content_page')) { // add a grey border to the content slice.
442				SectionTag.addClass('AddTopBorder');
443			}
444		}
445	}
446}
447
448function ActivateRA() { // Related Articles - Need to build the HTML.
449  var RA = BodyTag.find('section.sliceRelatedArticles');
450  if (RA.length > 0) {
451    if (RA.find('li.links').length > 0) { // check if there is any content
452
453      // Work out what links we have.
454      var Spans = RA.find('span.LinkHeading');
455      var S = Spans.eq(0).text().trim();
456      var bArticles = (S === 'Related Articles');
457      var bFiles = (S === 'Files' || Spans.eq(1).text().trim() === 'Files');
458
459      var ULs = RA.find('ul');
460
461      var ArticleBoxHTML = '';
462      if (bArticles) {
463          ArticleBoxHTML = '<div class="RX_ArticleBox"><div>Articles:</div><ul>' + ULs.eq(0).html() + '</ul></div>';
464      }
465
466      var FileBoxHTML = '';
467      if (bFiles) {
468          if (bArticles) {S = ULs.eq(1).html();} else {S = ULs.eq(0).html();}
469          FileBoxHTML = '<div class="RX_FileBox"><div>Files:</div><ul>' + S + '</ul></div>';
470      }
471      
472      if(ArticleBoxHTML !== '' && FileBoxHTML !== ''){
473      	ArticleBoxHTML.replace('RX_ArticleBox','RX_ArticleBox HalfWidth');
474        FileBoxHTML.replace('RX_FileBox','RX_FileBox HalfWidth');
475      }
476
477      var H ='<div class="RA_TitleWrapper"><div class="RA_Title">Related Content</div><img src="/Images/Content/2019/Templates/54496/images/RelatedContentBlock.png"></div><div class="RA_LinksBox">' + ArticleBoxHTML + FileBoxHTML + '</div>';
478      RA.html(H);
479
480      if (bFiles) {
481          H = $('<img src="/Images/Content/2019/Templates/54496/images/IconFile.png">');
482          H.prependTo(RA.find('div.RX_FileBox a'));
483      }
484
485	  // Clean up the HTML
486      RA.find('a').each(function(){
487      	var A = $(this);
488        var href = A.attr('href').trim();
489        A.attr('href',href);
490        if (href.startsWith('/P')) {A.attr('target','_blank');}
491      });
492      
493      RA.show();
494    }
495  }
496}
497 
498 function ReduceArticleHref (S,bCheckLongHref) {
499   var href = S, iSlash;
500   if (bCheckLongHref && !href.startsWith('/Articles/')) {
501     	href = href.replace('http://','');
502   		href = href.replace('https://','');
503        iSlash = href.indexOf('/');
504   		href = href.substring(iSlash);
505     	if(!href.startsWith('/Articles/')){return '';}
506   }
507   iSlash = href.indexOf('/',10);
508   href = href.substring(0, iSlash + 1);
509   return href;
510 }
511 
512function DeDupeArticleList() {
513 	var AB_As = SectionTag.find('div.main-content div.ArticleBody a');
514   	var CP_AL = SectionTag.find('div.main-content div.ContentPageArticleList div.ContentPageAL a');
515    // Make a fast array of CP_AL links
516	var i = 0, arr = [];
517   	CP_AL.each(function () {
518      	arr[i] = ReduceArticleHref($(this).attr('href'), false);
519      	i++;
520	});
521	var j = 0, k, arr2 = [];
522   	AB_As.each(function () {
523     	var href = ReduceArticleHref($(this).attr('href'), true);
524        if (href !== '') {
525          for (k = 0; k < i; k++) {
526              if (href === arr[k]) {
527                  arr2[j] = k;
528                  j++;
529              }
530          }
531        }
532	});
533  	// add in any related links.
534  	SectionTag.find('section.sliceRelatedArticles div.RX_ArticleBox a').each(function (){
535     	var href = ReduceArticleHref($(this).attr('href'), false);
536		for (k = 0; k < i; k++) {
537			if (href === arr[k]) {
538				arr2[j] = k;
539				j++;
540			}
541		}
542	});
543	// hide the dupes.
544  	var iRemoved=0,bMask = []; // use a mask so we don't try and delete the same thing twice etc.
545	for (k = 0; k < i; k++) { // there will be < i articles on the page
546		bMask[k] = true;
547	}
548	for (k = 0; k < j; k++) {
549      var l = arr2[k];
550      if(bMask[l]){
551		CP_AL.eq(l).parent().parent().remove();
552        bMask[l] = false;
553        iRemoved++;
554      }
555	}
556   console.log('Dupes removed: ' + iRemoved);
557  	// If some links left, show whole slice.
558  	CP_AL = SectionTag.find('div.main-content div.ContentPageArticleList');
559  	if (CP_AL.find('div.ContentPageAL a').length > 0) {
560      if(TemplateType === 'About Us + Blog'){CP_AL.find('div.ContentPageAL').addClass('Blog');}
561      CP_AL.show();
562    }
563}
564 
565function TurnGalleryIntoArticleList(SliceName) {
566	if (SectionTagExists(SliceName)) { // check if slice exists, and load into SectionTag if it does
567	  var OuterDiv = SectionTag.find('div.article_cards.LandingGallery'); // module CSS class must be this
568	  OuterDiv.find('li.gallery_li a').each(function () {
569		var ThisAtag = $(this);
570		var titleLink = ThisAtag.attr("href");
571		var Target = ThisAtag.attr("target");
572		var ThisImg = ThisAtag.children('img');
573		TextExists(ThisImg.attr('alt'), true);
574		var Div1 = '<div class="articleListImage"><a href="' + titleLink + '" target="' + Target + '"><img src="' + ThisImg.attr('src') + '" alt="Summary Image"/></a></div>';
575		var Div2 = '<div class="articleListTitle"><a href="' + titleLink + '" target="' + Target + '">' + sAttrText + '</a></div>';
576		//if (sAttrText3 !== '') {sAttrText2 = sAttrText2 + '*' + sAttrText3;}
577		var Div3 = ''; //if (sAttrText2 !== ''){Div3 = '<div class="articleListSummary"><span>' + sAttrText2 + '</span></div>';}
578		var Div4 = ''; //'<div class="articleListLink">Read more</div>';
579		var S = '<div>' + Div1 + Div2 + Div3 + Div4 + '</div>';
580		$(S).appendTo(OuterDiv);
581	  });
582	}
583}
584
585// ########################## Check various conditions #############################
586
587var bOnTouchDevice = ('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0);
588var iDeskTopWidth = 992;
589var iMobileScreenAllowence = 64; // Because of other stuff on a screen, you have to assume the browser window could get bigger on a rotation.
590var bDesktopScreenPossible = ((screen.width + iMobileScreenAllowence) >= iDeskTopWidth || (screen.height + iMobileScreenAllowence) >= iDeskTopWidth);
591
592var BodyTag = $('body');
593var bOnSystemPopupPage = BodyTag.hasClass('system_popup') || (window.location.href.toLowerCase().indexOf('popup=yes') !== -1);
594var bUserLoggedIn = BodyTag.hasClass('logged_in_user');
595
596SectionTags = BodyTag.find('section'); // Store all the section tags to speed up later code.
597var bOnContentPage = SectionTags.hasClass('slice_content_page');
598var bOnSystemPage = SectionTags.hasClass('slice_system_page');
599var bOnHomePage = SectionTags.hasClass('slice_image_blocks_4');
600var bOnLandingPage = SectionTags.hasClass('LandingPage');
601
602// Sort out IE stuff.
603if(bOnIE){
604  BodyTag.addClass('OnIE');
605  var S = '<div class="IEWarning">Unfortunately this website does not display correctly on the IE11 browser. We advise the use of Chrome, Edge, Safari, or FireFox.</div>';
606  $(S).appendTo(BodyTag);
607} 
608 
609if (bOnContentPage || bOnLandingPage) {
610	ActivateBannerImage('slice_BannerImage');
611}
612
613// Activate the slide shows first as they are usually near the top of the visible screen.
614if (bOnHomePage) {
615
616	// ##############################################################
617	// # js for Slide Shows slices. We use BX-slider V4.2.5
618	// ##############################################################
619
620	// The slide-shows are hidden via CSS when the page first loads, to give a smoother page-load experience.
621	// All slide-show CI modules must have a class "bannerSlides" defined within them.
622
623	// Activate all the slide-shows. Do in sensible order, so any visible ones are done first.
624	ActivateBxSlider('slice_SlidesFullWidth',false);
625}
626
627// #######################################
628// # Menu data changes
629// #######################################
630
631// We make the required adjustments to the one set of menu HTML on the page, before cloning it and activating all the copies.
632
633var ulModuleRootMenu = BodyTag.find('ul.root_menu');
634var bMenuPresent = (ulModuleRootMenu.length !== 0);
635if (bMenuPresent) {
636
637  // Set up the search icon in the search box.
638  if(bDesktopScreenPossible){
639    var DeskTopSearchBox = BodyTag.find('header div.top-link-wrapper div.search-form');
640    var HiddenSearchBox = DeskTopSearchBox.find('input.button');
641    DeskTopSearchBox.find('input.text').attr("autocomplete","off");
642    $('<img alt="Icon" src="/Images/Content/2019/Templates/54496/images/IconEyeGlassBlue.png">').appendTo(DeskTopSearchBox);
643    DeskTopSearchBox.find('img').click(function(){HiddenSearchBox.click();}); // set up the click.
644  }
645
646  // Only keep some of the top-level menu items.
647  ulModuleRootMenu.find('li.menu_item_level_1').each(function() {
648    var ThisLi = $(this);
649    var Ahref = ThisLi.children('a').attr('href');
650    if (
651      	!Ahref.startsWith('/Groups/213223/') &&
652        !Ahref.startsWith('/Groups/220180/') &&
653        !Ahref.startsWith('/Groups/220181/') &&
654        !Ahref.startsWith('/Groups/220184/') &&
655        !Ahref.startsWith('/Groups/220185/') && // Contact Us
656        !Ahref.startsWith('/Groups/220182/') && // Latest Updates
657      	!Ahref.startsWith('/MyArea/')
658    ) {
659    	ThisLi.remove();
660    }
661  });
662    
663   /* remove sub menus from Home */
664   // This assumes that the home menu is the first item with a sub menu.
665  var HomeMenuLi = ulModuleRootMenu.children('li:first-child');
666  HomeMenuLi.children('ul').remove();
667  HomeMenuLi.removeClass('has_sub_menu'); // remove class
668  //HomeMenuLi.children('a').attr("href","/"); // replace link with base domain reference, not a group reference.    
669    
670  // remove copies of 1st item elements in dropdown sub-menu.
671  ulModuleRootMenu.find('li.menu_item_level_2:first-child').each(function() {
672
673	var ThisLi = $(this);
674	if(ThisLi.children("a[href^='/MyArea/']").length === 0) { // only if not a link into /MyArea/...
675
676	  if(ThisLi.siblings().length === 0) { // no other <li> so it is the only entry
677		var ul = ThisLi.parent();
678	    ul.parent().removeClass('has_sub_menu'); // remove class from the <li> at the level above
679		ul.remove(); // delete whole parent <ul>
680
681	  } else {
682		if (bOnTouchDevice && bDesktopScreenPossible) {
683			// On a touch device, the copies of the level one links at the 2nd level have to be kept for the desktop menus.
684			// But in the SlickNav menus, these 2nd level links are not needed.
685			// So we mark the items so we can delete them later, after data is copied into the SlickNav menu.
686			ThisLi.addClass('SlickNavNotNeeded'); // Mark the 2nd level <li> tag.
687		} else {
688			// Not on a touch screen, so Desktop and SlickNav menus will be the structurally the same.
689			ThisLi.remove(); // so just remove this <li> tag
690		}
691	  }
692	}
693  });
694
695	// #######################################
696	// # SlickNav menus V1.0.10
697	// #######################################
698
699	ActivateMenu('slice_Header_L');
700
701  // Set up Search box inside SlickNav
702  var DeskTopSearchBoxM = BodyTag.find('header div.SlickNav_Wrapper div.search-overlay');
703  var LIs = BodyTag.find('header div.SlickNav_Wrapper ul.slicknav_nav li.ExtraLink.SearchOpen');
704  DeskTopSearchBoxM.appendTo(LIs);
705  var HiddenSearchBoxM = DeskTopSearchBoxM.find('input.button');
706  DeskTopSearchBoxM.find('input.text').attr("autocomplete","off");
707  $('<img alt="Icon" src="/Images/Content/2019/Templates/54496/images/IconEyeGlassBlue.png">').appendTo(DeskTopSearchBoxM);
708  DeskTopSearchBoxM.find('img').click(function(){HiddenSearchBoxM.click();}); // set up the click.
709
710} // end of if bNeedMenus
711
712// Here do things ONLY needed on a home page.
713if (bOnHomePage) {
714
715	  // Article list - 4 in a row on desktop
716	if (SectionTagExists('slice_WelcomeArticles')) { // check if slice exists, and load into SectionTag if it does
717		ActivateArticleList4(SectionTag);
718	}
719
720	// image blocks
721	ActivateBlockImages('slice_image_blocks_4');
722
723} else if (bOnContentPage) {
724
725  	if (SectionTagExists("slice_content_page")) {
726      
727console.log('TemplateType: ' + TemplateType);
728console.log('ArticleCardDisplay: ' + ArticleCardDisplay);
729      
730      // Check if article is empty - if so, then show the replacement of 6 article cards.
731      var CA = SectionTag.find('div.CurrentArticle');
732      var RA = SectionTag.find('div.ReplacementArticle');
733      var bHaveCurrentArticle = ( (CA.length === 1) && (CA.find('div#bookshelfWrapper').length === 0) );
734console.log('bHaveCurrentArticle: ' + bHaveCurrentArticle);
735      if (bHaveCurrentArticle) {
736        if (TemplateType === 'About Us' || TemplateType === 'About Us Purple') {ActivateBxSlider('slice_SlidesFullWidth',true);}
737        if (TemplateType === 'Baptist Times') {SectionTag.find('div.TaggedAL').remove();}
738        RA.remove(); // delete this so all the dupes go.
739        ActivateRA(); // Build Related Articles - do in all modes - as we have a current article.
740      } else {
741        CA.hide();
742		// Look for a BT home-mission article
743		if (TemplateType === 'Baptist Times') {
744			// First check if the home-mission stories article is already in the list of 6
745			var bFound = false;
746			var AC = RA.find('div.article_cards');
747			var RAs = AC.children();
748			RAs.each(function(){
749				var S = $(this).find('div.articleListTitle a').text().toLowerCase();
750				if(S.endsWith('home mission stories')){bFound = true;}
751			});
752			if(!bFound){
753				var TaggedAL = SectionTag.find('div.TaggedAL div.article_cards').children();
754				 if (TaggedAL.length === 1 ) {
755						// Need to move this article into the group of 6
756						if(RAs.length === 6){RAs.eq(5).remove();}
757						TaggedAL.prependTo(AC);
758                   		console.log('Home Mission Stories article slotted in.');
759				 }
760			}
761		}
762        SectionTag.find('div.TaggedAL').remove(); // delete this as well. You can only have a TaggedAL to go with an article.
763        if (RA.find('div.article_cards').children().length > 0) {
764          RA.show();
765          console.log('ReplacementArticle current-group card list showing.');
766        } else { // even the replacement of 6 article cards is empty, so show the group-based cards.
767          SectionTag.find('div.ReplacementArticleB').show();
768          console.log('ReplacementArticleB group list showing.');
769        }
770      }
771      
772      		// HACK
773		var S = location.href;
774		if(S.indexOf('220492') !== -1){SectionTag.find('div.ReplacementArticleB').show();}
775		
776      // Look for article_cards
777      var AB = SectionTag.find('div.ArticleBody');
778      var bArcticleCards = (AB.find('div.article_cards').length > 0);
779      if (bArcticleCards) {
780	  	ActivateArticleList4(AB); // do in all modes.
781        SectionTag.children('div.container').addClass('Wide');
782      }
783
784      if (TemplateType.startsWith('About Us')) {
785        // See if the Tagged AL has anything in it.
786        var TaggedAL = SectionTag.find('div.TaggedAL div.article_cards');
787        if (TaggedAL.length === 1 ) {
788          // great, we are showing the tagged AL.
789          console.log('Tagged AL showing.');
790        } else if (TemplateType === 'About Us + Blog') {
791        	DeDupeArticleList(); // there is no tagged list, so show this list instead.
792          console.log('Blog AL showing.');
793        }
794        /*
795		// Check if we have a SafeGuarding Page.
796		var SG = SectionTag.find('div.ArticleBody div.SafeGuardFlexBox');
797		if(SG.length > 0){
798			SectionTag.addClass('FullWidth');
799		} else {
800			SectionTag.find('aside div.ContentPageImage.Advert').show();
801		}
802        */
803        SectionTag.find('aside div.ContentPageImage.Advert').show();
804        
805		// Look for events.
806		var E = SectionTag.find('aside div.SideEventsList');
807		if (E.children('div.EventModule').children().length > 0) {
808			E.show();
809		}
810
811      } else if (TemplateType === 'Baptist Times') {
812        // DeDupe the article-list.
813        DeDupeArticleList();
814        SectionTag.find('aside div.ContentPageImage').show();
815
816        if (bHaveCurrentArticle && !bArcticleCards) {
817          // Do the Facebook and Twitter share buttons.
818          var myURL = encodeURI(window.location.href);
819          var SMS = SectionTag.find('section.SocialMediaShare'); // 2 of these
820
821          var FacebookButton = SMS.find('a.FaceBookShare');
822          var FacebookShareURL = 'https://www.facebook.com/sharer/sharer.php?u=' + myURL;
823          FacebookButton.attr('href', FacebookShareURL);
824
825          var TwitterButton = SMS.find('a.TwitterShare');
826          var TwitterText = 'Please%20read%20this:';
827          var Meta = $('head meta[name="og:title"]');
828          if (Meta.length === 1) {
829            TwitterText = Meta.attr('content');
830            TwitterText = encodeURI(TwitterText);
831          }
832          var TwitterShareURL = 'https://twitter.com/intent/tweet?text=' + TwitterText + '&via=BaptistTimes&url=' + myURL;
833          TwitterButton.attr('href', TwitterShareURL);
834          SMS.show();
835        }
836
837      } else if (TemplateType.startsWith('Resources')) {
838		var CPS = BodyTag.find('section.ContentPageSearch');
839        CPS.show();
840        CPS = CPS.find('div.search-overlay');
841        CPS.find('input.text').attr("autocomplete","off");
842        // Link white-eye-glass to hidden search button.
843        var HiddenSearchBoxR = CPS.find('input.button');
844  		CPS.find('img.search-EyeGlass').click(function(){HiddenSearchBoxR.click();}); // set up the click.
845        // Add an extra class, so we can re-format PDF based articles.
846        AB.addClass('Resources');
847        var DMI = AB.find('div.mediaInfo');
848        var FileText = DMI.text().trim().toLowerCase();
849        if(FileText.indexOf('file type: word') !== -1 || FileText.indexOf('file type: doc') !== -1){
850        	DMI.children('div.mediaButtons').addClass('FileWord');
851        } else if (FileText.indexOf('file type: pdf') !== -1){
852        	DMI.children('div.mediaButtons').addClass('FilePDF');
853        } else if (FileText.indexOf('file type: xls') !== -1){
854        	DMI.children('div.mediaButtons').addClass('FileXLS');
855        } else if (FileText.indexOf('file type: ppt') !== -1){
856        	DMI.children('div.mediaButtons').addClass('FilePPT');
857        } else if (FileText.indexOf('file type: buy') !== -1){
858        	DMI.children('div.mediaButtons').addClass('FileBUY');
859        } else if (FileText.indexOf('file type: zip') !== -1){
860        	DMI.children('div.mediaButtons').addClass('FileZIP');
861        } else if (FileText.indexOf('file type: audio') !== -1){
862        	DMI.children('div.mediaButtons').addClass('FileAUDIO');
863        } else if (FileText.indexOf('file type: free') !== -1){
864        	DMI.children('div.mediaButtons').addClass('FileFREE');
865        } else if (FileText.indexOf('file type: video') !== -1){
866        	DMI.children('div.mediaButtons').addClass('FileVIDEO');
867        } else {
868        	DMI.children('div.mediaButtons').addClass('FileUNKNOWN');
869        }
870        //console.log(AB.find('div.mediaInfo').text());
871      }
872
873      // code to try and make content images work on mobile phones. Set max-width css property is if has not already been set.
874      // If width and height attributes are both set, then the image is compressed horizontally, but that is still better than it overflowing.
875      if (bHaveCurrentArticle) {
876        var ContentImages = SectionTag.find('div.ArticleBody img');
877        ContentImages.each(function() {
878            var Img = $(this);
879            if (Img.css('max-width') === 'none') {
880                Img.css('max-width','100%');
881            }
882        });
883      }
884    }
885
886} else if (bOnLandingPage) {
887  
888   console.log('TemplateType: ' + TemplateType);
889   console.log('ArticleCardDisplay: ' + ArticleCardDisplay);
890   
891   if (TemplateType === 'Baptist Times') {
892	   TurnGalleryIntoArticleList('slice_WelcomeArticles');
893   }
894
895	var WA;
896  // Main Article list
897  if (SectionTagExists('slice_WelcomeArticles')) { // check if slice exists, and load into SectionTag if it does
898    ActivateArticleList4(SectionTag);
899    if (ArticleCardDisplay !== 'Full Cards') {
900    	SectionTag.addClass('TitlesOnly');
901    }
902    WA = SectionTag;
903  }
904  
905  var CPS = BodyTag.find('section.ContentPageSearch.LandingPage');
906  var bHasArticle = (CPS.find('div.ArticleBody').length > 0);
907   console.log('bHasTopArticle: ' + bHasArticle);
908  
909  if (TemplateType.startsWith('About Us')) {
910    if(bHasArticle) {
911  		CPS.addClass('White').addClass('Narrow');
912      ActivateBxSlider('slice_SlidesFullWidth',true);
913    } else {
914      CPS.hide();
915    }
916    
917    // Show the "Landing2019" tagged list, hide the normal St. Alfege one.
918    WA.find('div.article_cards').hide();
919	//WA.find('div.article_cards.LandingTagged').css('display','flex');
920    var LG = WA.find('div.article_cards.LandingTagged');
921    console.log(location.pathname);
922    if(location.pathname.startsWith('/Groups/371309/')){LG.addClass('RowReverse');}
923	LG.css('display','flex');    
924    WA.find('div.ReplacementLanding.GroupCards').hide(); // Don't ever need this in "About Us" mode.
925    console.log('Showing "Landing2019" tagged article list.');
926    
927  } else if (TemplateType === 'Baptist Times') {
928    if(bHasArticle) {
929      	CPS.addClass('White');
930    	ActivateBxSlider('slice_SlidesFullWidth',true);
931    } else {
932      CPS.hide();
933    } 
934    WA.addClass('Narrow');
935    
936    // Show the "Landing2019" tagged list, hide the normal St. Alfege one.
937    WA.find('div.article_cards').hide();
938    WA.find('div.article_cards.LandingGallery').css('display','flex');
939    WA.find('div.ReplacementLanding.GroupCards').hide(); // Don't ever need this in "Baptist Times" mode.
940    console.log('Showing Landing-page gallery.');
941    
942    /*
943	var ChildGroupList = WA.find('div.ReplacementLanding');
944	var bLeafNode = (ChildGroupList.find('li').length === 0);
945    console.log('bLeafNode: ' + bLeafNode);
946	if (!bLeafNode) {
947		ChildGroupList.css('display','flex');
948		// Need to hide all child-group articles from the article-list, or else it looks too cluttered.
949		WA.find('div.article_cards').hide();
950		WA.find('div.article_cards.NoChildGroups').css('display','flex');
951      console.log('Showing Group List + articles in current group only.');
952	}
953    */
954    
955  } else if (TemplateType.startsWith('Resources')) {
956    
957    WA.addClass('White');
958    WA.find('div.BreadCrumbs').show();
959    
960    if(TemplateType !== 'Resources (Simple)'){
961      var ChildGroupList = WA.find('div.ReplacementLanding');
962      var bLeafNode = (ChildGroupList.find('div.GroupNavTitle').length === 0);
963      console.log('bLeafNode: ' + bLeafNode);
964      if (!bLeafNode) {
965          ChildGroupList.css('display','flex');
966          // Need to hide all child-group articles from the article-list, or else it looks too cluttered.
967          WA.find('div.article_cards').hide();
968          WA.find('div.article_cards.NoChildGroups').css('display','flex');
969      } else {
970        // Sort cards into the right order.
971        console.log("ResourceSort: " + ResourceSort);
972        if(ResourceSort === "Date Ascending"){ // Reverse sort what we have.
973          var i=0;
974          var AC = WA.find('div.article_cards').eq(0); // first div.article_cards only
975          AC.children().each(function(){
976            if(i > 0) { // skip the first.
977            	var T = $(this);
978              	T.prependTo(AC);
979            }
980             //console.log(i);
981            i++;
982          });
983        } else if(ResourceSort === "Title A-Z" || ResourceSort === "Title Z-A"){ 
984          var i=0;
985          var AC = WA.find('div.article_cards').eq(0); // first div.article_cards only
986          var ACC = AC.children();
987          var arr=[], arr2=[];
988          var S;
989          ACC.each(function(){
990            S = $(this).find('div.articleListTitle a').text().trim().toLowerCase();
991            // Attempt to sort numbers in an intelligent way.
992            S = S.replace('10','A0');
993            S = S.replace('11','A1');
994            S = S.replace('12','A2');
995            S = S.replace('13','A3');
996            S = S.replace('14','A4');
997            S = S.replace('15','A5');
998            S = S.replace('16','A6');
999            S = S.replace('17','A7');
1000            S = S.replace('18','A8');
1001            S = S.replace('19','A9');
1002            S = S.replace('20','B0');
1003            S = S.replace('21','B1');
1004            S = S.replace('22','B2');
1005            S = S.replace('23','B3');
1006            S = S.replace('24','B4');
1007            S = S.replace('25','B5');
1008            S = S.replace('26','B6');
1009            S = S.replace('27','B7');
1010            S = S.replace('28','B8');
1011            S = S.replace('29','B9');
1012            arr[i] = S;
1013            arr2[i] = arr[i];
1014            i++;
1015          });
1016          var j = i; // number of elements in arr
1017          arr2.sort(); // sort this one.
1018          if(ResourceSort === "Title Z-A"){arr2.reverse();}
1019          //console.log(arr);
1020          //console.log(arr2.sort());
1021          // Loop over sorted array in reverse order
1022          for(i = j; i > 0; i--){
1023            for(var k = j; k > 0; k--){
1024              if(arr2[i-1] === arr[k-1]){ // shift indexes by -1
1025              	ACC.eq(k-1).prependTo(AC);
1026              }
1027            }
1028            //console.log(i);
1029          }
1030        }
1031		// Make sure any article with "Index" in its name, is at the start of the list.
1032		var AC = WA.find('div.article_cards').eq(0); // first div.article_cards only
1033        var ACC = AC.children();
1034		var bKeepGoing = true;
1035		ACC.each(function(){
1036			if(bKeepGoing){
1037				var T = $(this);
1038				var S = T.children('div.articleListTitle').children('a').text();
1039				if(S.indexOf('Index') !== -1 || S.endsWith(' Introduction')){
1040					T.prependTo(AC); // Move to start of article list
1041					bKeepGoing = false;
1042                  	console.log('Moved Index article to first position.');
1043				}
1044			}
1045		});
1046      }
1047    }
1048
1049    // Search only appears in R mode
1050    CPS.addClass('NarrowR');
1051    CPS = CPS.find('div.search-overlay'); // Re-define CPS
1052    CPS.show();
1053    CPS.find('input.text').attr("autocomplete","off");
1054    // Link white-eye-glass to hidden search button.
1055    var HiddenSearchBoxR = CPS.find('input.button');
1056    CPS.find('img.search-EyeGlass').click(function(){HiddenSearchBoxR.click();}); // set up the click.
1057  }
1058    
1059
1060} else if (bOnSystemPage || bOnSystemPopupPage) {
1061
1062	// work out what kind of page we are on.
1063	var PageType = window.location.pathname.toLowerCase();
1064	if (PageType.endsWith(".aspx")) {
1065		PageType = PageType.substring(0, PageType.indexOf(".aspx"));
1066		PageType = PageType.replace(/\//g, "_"); // replace all / to _ Have to use \/ to get a / in the reg-ex. The g denotes a global exchange.
1067		PageType = PageType + "_aspx";
1068	} else if (PageType.indexOf(".html") === (PageType.length - 5)) {
1069		// Assume we are on a local machine.
1070		PageType = '_user_registration_aspx';
1071	}
1072	//alert(PageType);
1073
1074	/* Possible page types are now:
1075	'_calendar_month_aspx'
1076	'_media_allmedia_aspx'
1077	'_user_registration_aspx'
1078	'_user_copyright_aspx'
1079	'_user_termsandconditions_aspx'
1080	'_user_privacypolicy_aspx'
1081	'_user_help_aspx'
1082	'_publisher_search_aspx' - this is search results.
1083	'_paymentgroup_registration_aspx'
1084	'_myarea_walletitem_aspx'
1085	*/
1086
1087	if (SectionTagExists("slice_system_page")) { // check if slice exists, and load into SectionTag if it does
1088		SystemSlice = SectionTag;
1089		SystemSlice.addClass(PageType); // add class onto <section> tag, so CSS can locate it.
1090	} else {
1091		BodyTag.addClass(PageType); // add class onto <body> tag, so CSS can locate it. This will apply to various pop-up windows eg shop T&Cs.
1092		BodyTag.addClass('system_popup'); // add this in case it is not on.
1093    }
1094
1095	if (PageType === '_media_allmedia_aspx' || PageType === '_publisher_search_aspx') {
1096
1097		// Add a toggle for the media controls.
1098		var MediaControls = SystemSlice.find('div#media_controls'); // these media controls are on the search page too.
1099		if (MediaControls.length !== 0) {
1100			$('<a class="system_toggle_advanced">Advanced Options</a>').insertBefore(MediaControls);
1101			ApplyToggleVisibilityOnClick(SystemSlice, "a.system_toggle_advanced", MediaControls, 0, false);
1102		}
1103
1104		HideDivsIfAllEmpty('media_summary_image'); // Hide some empty columns, if needed.
1105
1106		if (PageType === '_publisher_search_aspx') { // Extra things to do on the search page.
1107
1108			HideDivsIfAllEmpty('search_article_image'); // Hide some empty columns, if needed.
1109			HideDivsIfAllEmpty('search_event_image'); // Hide some empty columns, if needed.
1110
1111			// If we have been sent to the search page explicitly then prepare the page for searching.
1112			 var SearchBox = SystemSlice.find('input[id$="_txtSearchStringTemplate"]');
1113			 if (SearchBox.length === 1) {
1114				 if (SearchBox.val() === 'Activate_Search') {
1115					 SystemSlice.find('h2').hide(); // hide the search result titles
1116					 SearchBox.val(''); // Clear the search text box
1117					 SearchBox.attr('placeholder','Type your search text here');
1118					 SearchBox.attr("autocomplete","off");
1119					 MediaControls.show(); // make the search controls show.
1120				 }
1121			 }
1122
1123			// If no data is found then, print a message, rather than have a blank page.
1124			 if (SystemSlice.find('div.system_section').length === 0) {
1125				 var HTML = '<span>No data found.<br><br>Please use the advanced options to refine your search.</span>';
1126				 $(HTML).appendTo(SystemSlice.find('div.system_body'));
1127				 MediaControls.show(); // make the search controls show.
1128			 }
1129		}
1130	}
1131
1132	// Fix calendar mobile page. Add a class to days we want to hide on the mobile/list view.
1133	if (PageType === '_calendar_month_aspx') {
1134		var DivToday = SystemSlice.find('div.calendar_day_wrapper_today');
1135		if (DivToday.length !== 0) {  // we are on a calendar page with today's date.
1136			var NoEvents = SystemSlice.find('div#calendar_no_events');
1137			if (NoEvents.length === 0) { // only bother if there are some events.
1138				DivToday.prevAll().addClass('CalendarHideOnListView'); // so we can hide days earlier in the current week.
1139				var DivThisWeek = DivToday.parent();
1140				DivThisWeek.prevAll().addClass('CalendarHideOnListView'); // so we can hide earlier weeks.
1141				// If no events are visible, then tell the user.
1142				var AllDaysInVisibleWeeks = SystemSlice.find('div.calendar_week:not(".CalendarHideOnListView") div.calendar_day_wrapper');
1143				var iDaysVisible = AllDaysInVisibleWeeks.not('.calendar_day_wrapper_empty').not('.CalendarHideOnListView').length;
1144				if (iDaysVisible === 0) {
1145					$('<div id="calendar_no_events">There are no events in the selected month.</div>').insertAfter(SystemSlice.find('div.calendar'));
1146				}
1147			}
1148		}
1149	}
1150
1151} // end of bOnHomePage or bOnSystemPage if-block
1152
1153// Corrections for various hardware/browsers
1154var P = navigator.platform;
1155var bSmallAppleDevice = (P === 'iPhone' || P === 'iPad' || P === 'iPod');
1156//var bAppleDevice = (P === 'MacIntel' || bSmallAppleDevice);
1157
1158var UA = navigator.userAgent;
1159// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent for details.
1160var bOnSafari = (UA.indexOf('Safari/') !== -1 && UA.indexOf('Chrome/') === -1 && UA.indexOf('Chromium/') === -1);
1161
1162//alert(P + ' # ' + UA); // DEBUGGING line.
1163
1164if (bOnSafari) {
1165	// Fix the twitter feed on Safari. Need to replace height:100% with a fixed height, to prevent a near infinite scroll.
1166	// We can't just add a class on the <iframe>, as it is created dynamically by Twitter js.
1167	// So instead we add a class on the wrapper div, just before where the iframe will appear.
1168	// SectionTags.find('div.WhatsOnTwitter').addClass('OnAppleDevice');
1169}
1170if (bSmallAppleDevice) {
1171	// Parallex images are often a mess on small apple devices, so add a tag onto the <body> tag so we can take evasive action.
1172	BodyTag.addClass('OnSmallAppleDevice');
1173}
1174
1175// Sort out login/logout/register/web-office links
1176if (bUserLoggedIn) {
1177	var SB = BodyTag.find('div.HiddenStatusBar');
1178	if (SB.length === 1) {
1179		var bWebOfficeActive = (SB.find('a.weboffice_link').length === 1);
1180		if (!bWebOfficeActive) { // Need to hide WO links.
1181			BodyTag.find('section.NewsLetterFooter a.FooterWebOffice').hide();
1182		}
1183	}
1184}
1185
1186// Fix the cookies slice
1187var CS = BodyTag.find('footer div.slice_Cookies');
1188 if (CS.length === 1) {
1189 	CS.find('img').attr('src','/Images/Content/2019/Templates/54496/images/IconClose.png');
1190 }
1191 
1192// Linked In images
1193 /*
1194var HeadTag = $('head');
1195var MetaTag = HeadTag.find('meta[name="image"]');
1196 if(MetaTag.length === 1){
1197 	MetaTag.attr('property','og:image');
1198 }
1199 */
1200 
1201// Sticky header
1202// We need iYforHeaderTintDown - iYforHeaderTintUp to be larger than the difference between heights
1203// for the large and small headers.
1204var HeaderSlice = BodyTag.find('header');
1205var SlickNavBtn = HeaderSlice.find("a.slicknav_btn");
1206 
1207var bHeaderTintOn = false, iYforHeaderTintDown = 50,  iYforHeaderTintUp = 2;
1208function PollScrollDownChanges() { // This routine must be very streamlined. Called every 250ms.
1209
1210	var iY = window.pageYOffset;
1211
1212	if (!bHeaderTintOn && iY >= iYforHeaderTintDown) {
1213		if (window.innerWidth > 991) { // only apply if screen is of desktop size.
1214			HeaderSlice.addClass('HeaderSmall');
1215			bHeaderTintOn = true;
1216		}
1217	}
1218	if (bHeaderTintOn && iY < iYforHeaderTintUp) {
1219        HeaderSlice.removeClass('HeaderSmall');
1220		bHeaderTintOn = false;
1221	}
1222}
1223
1224// If the screen is resized, then we have to click shut the SlickNav Menu, if it is open.
1225var iLastWidth = 0;
1226function ShutSlickNav() {
1227	var iWidth = window.innerWidth;
1228	if (iWidth !== iLastWidth) { // don't run code if it looks like we just have the browser top menu appearing and disappearing.
1229		iLastWidth = iWidth;
1230		if (bDesktopScreenPossible) {
1231			if (SlickNavBtn.hasClass('slicknav_open')){
1232				SlickNavBtn.click();
1233			}
1234			if (bOnHomePage && iWidth < 992 && HeaderSlice.hasClass('HeaderSmall')) { 
1235				HeaderSlice.removeClass('HeaderSmall');
1236				bHeaderTintOn = false;
1237			}
1238		}
1239	}
1240}
1241
1242window.addEventListener("resize", function(){ShutSlickNav();}, false); 
1243if (bDesktopScreenPossible) {
1244	window.setInterval(function(){PollScrollDownChanges();}, 100); // poll to see if user has scrolled down.
1245}
1246
1247});
1248
1249// Dummy routines to prevent errors
1250function insertFolderImages() {return false;}

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.