PageSourceSearch

https://www.stjohnschelsea.org/Images/Content/3507/Templates/77055/js/script.js

js stjohnschelsea.org collected 2026-10-09 01:28:26 UTC 37,997 bytes, 911 lines download raw bytes

1/*
2	Main ChurchInsight template Javascript/JQuery file. Version 20.Feb.2017
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
14// Custom values set here. Change for a particular customer.
15var SlideShowDefaultButtonText = 'Read more';
16var bAddDarkenedOverlayForSlideShowCaptions = false;
17var bSplitFooterAddressAtSecondComma = true;
18
19// #################### Define some useful functions #######################
20
21// We have to put all functions here, as OSX does not allow functions to be inside if statements.
22
23// function to turn a slice name into a selector reference for the corresponding <section> tag
24function GetSectionTagRef(SliceName) {
25	return 'section.' + SliceName + ' ';
26}
27
28var SectionTag, SectionTags; // will be used to hold required slices
29function SectionTagExists(SliceName) {
30	if (SectionTags.hasClass(SliceName)) {
31		SectionTag = SectionTags.filter(GetSectionTagRef(SliceName));
32		if (SectionTag.length !== 0) { // at least one slice exists, great. You could have more than one in theory.
33			return true;
34		}
35	}
36	SectionTag = undefined; // remove all data.
37	return false;
38}
39
40function GetRefItem(SectionTag, Ref) {
41	if (typeof Ref === "string") {
42		return SectionTag.find(Ref);
43	} else {
44		return Ref;
45	}
46}
47
48// A function to easily set JQuery toggles.
49// SectionTag is a $ variable.
50function ApplyToggleOnClick(SectionTag, ClickRef, ToggleRef, iDelay, bShowToggleItemInitially) {
51
52	var ClickItem = GetRefItem(SectionTag, ClickRef);
53	var ToggleItem = GetRefItem(SectionTag, ToggleRef);
54
55	if (bShowToggleItemInitially) {
56		ToggleItem.show(0);
57	} else {
58		ToggleItem.hide(0);
59	}
60	// Note we add a function here. Since we are only using calling function arguements inside the function argument,
61	// variable scoping correctly works.
62	 ClickItem.click(function () {
63		ToggleItem.toggle(iDelay);
64	});
65}
66
67/*
68function ApplyHideOnClick(SectionTag, ClickRef, ToHideRef) {
69
70	var ClickItem = GetRefItem(SectionTag, ClickRef);
71	var ToHideItem = GetRefItem(SectionTag, ToHideRef);
72
73	 ClickItem.click(function () {
74		ToHideItem.hide(0);
75	});
76}
77*/
78
79function ApplyToggleClassOnClick(SectionTag, ClickRef, ToggleRef, ClassName) {
80
81	var ClickItem = GetRefItem(SectionTag, ClickRef);
82	var ToggleItem = GetRefItem(SectionTag, ToggleRef);
83
84	// Note we add a function here. Since we are only using calling function arguements inside the function argument,
85	// variable scoping correctly works.
86	 ClickItem.click(function () {
87		ToggleItem.toggleClass(ClassName);
88	});
89}
90 
91function ApplyToggleVisibilityOnClick(SectionTag, ClickRef, ToggleRef, iDelay, bShowToggleItemInitially) {
92
93	var ClickItem = GetRefItem(SectionTag, ClickRef);
94	var ToggleItem = GetRefItem(SectionTag, ToggleRef);
95
96	if (bShowToggleItemInitially) {
97		ToggleItem.show(0);
98	} else {
99		ToggleItem.hide(0);
100	}
101	// Note we add a function here. Since we are only using calling function arguements inside the function argument,
102	// variable scoping correctly works.
103	 ClickItem.click(function () {
104		ToggleItem.toggle(iDelay);
105	});
106}
107
108// function to test if text exists.
109var sAttrText, sAttrText2, sAttrText3, sAttrText4; // Results come back in these variables.
110var DollarTextarea = $("<textarea/>"); // store this once.
111function TextExists(attrText, bSplit) {
112
113	if (attrText === undefined) {return false;}
114	if (attrText === null) {return false;}
115
116	var TextToProcess = attrText.trim();
117	if (TextToProcess === '') {return false;}
118
119	// decode the text, so that &amp;lt; becomes < etc.
120	// This works by turning into HTML and then turning back into text.
121	if (TextToProcess.indexOf('&') !== -1) { // we could use the .includes('&') method, but it is quite new, so some browsers can't cope.
122		TextToProcess = DollarTextarea.html(TextToProcess).text();
123	}
124	if (TextToProcess === '') {return false;}
125
126	sAttrText = ''; // set return values to blank.
127	sAttrText2 = '';
128	sAttrText3 = '';
129	sAttrText4 = '';
130	if (bSplit) {
131		var arrSplitText = TextToProcess.split('*');
132		sAttrText = arrSplitText[0].trim();
133		if (arrSplitText.length > 1) {sAttrText2 = arrSplitText[1].trim();}
134		if (arrSplitText.length > 2) {sAttrText3 = arrSplitText[2].trim();}
135		if (arrSplitText.length > 3) {sAttrText4 = arrSplitText[3].trim();}
136	} else {
137		sAttrText = TextToProcess;
138	}
139
140	return (sAttrText + sAttrText2 + sAttrText3 + sAttrText4 !== '');
141}
142
143// Function to hide a column if it contains no images.
144var SystemSlice;
145function HideDivsIfAllEmpty(ColumnClass) {
146	var ImageWrappers = SystemSlice.find('div.' + ColumnClass);
147	if (ImageWrappers.find('img').length === 0) { // have to use find not children, as img tags can be inside <a> tags.
148		ImageWrappers.hide(0);
149	}
150}
151
152// ################### Slice activation functions go here. #########################
153
154// All slide shows have the same defaults at present.
155var BxDefaultValues;
156function ActivateBxSlider(SliceName) {
157	if (SectionTagExists(SliceName)) { // check if slice exists, and load into SectionTag if it does
158
159        var bannerSlides = SectionTag.find('div.bannerSlides'); // use a "find" here, as structure of slices varies.
160        var gallery_ul = bannerSlides.children('ul.gallery_ul');
161        var ImageList = gallery_ul.find('img');
162        if (ImageList.length === 0) {return;} // No images, so give up.
163
164        // ul.gallery_ul must be displayed before bx-slider can be applied.
165        // So since we hide it while the page was loading, we show it now.
166        bannerSlides.show(0); // show the slice now. It was hidden by CSS.
167
168        if (ImageList.length > 1) { // carry on as normal.
169          gallery_ul.bxSlider(BxDefaultValues);
170        } else { // Just 1 image, so we don't set up the slider, but do some minor adjustments to help the CSS.
171          gallery_ul.css('margin','0px').css('list-style-type','none');
172          var S = '<div class="bx-wrapper"><div class="bx-viewport"></div></div>';
173          gallery_ul.wrap(S);
174        }
175
176        // Code to enable user defined text to appear over banner slides.
177        ImageList.each(function() {
178			var ThisImg = $(this);
179			if (TextExists(ThisImg.attr('alt'), true)) { // check if there is any alt text.
180				var DarkenedClass = '';
181				if (bAddDarkenedOverlayForSlideShowCaptions) {DarkenedClass = ' DarkenedOverlay';}
182				var title = '<div class="slideTitle' + DarkenedClass + '">' + sAttrText + '</div>';
183				// even if the subtitle text is empty, we keep the div for styling reasons.
184				// If there is a long caption, reduce font weight from bold to normal.
185				var FontStyle = '';
186				if (sAttrText2.length > 100) {FontStyle = ' style="font-weight:400;" ';}
187				var subtitle = '<div class="slideText' + DarkenedClass + '"' + FontStyle + '>' + sAttrText2 + '</div>';
188				
189				var ButtonLink = '';
190				var ButtonText = sAttrText3;
191				if (ButtonText === '') {ButtonText = SlideShowDefaultButtonText;}
192                var TextColor = '';
193				if (ButtonText !== '' && ButtonText !== 'none'){
194					var ButtonColor = sAttrText4;
195                  	TextColor = 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                      //sAttrText = 'javascript:location.href="' + sAttrText + '";';
206						ButtonLink = '<a class="slideButton" href="' + sAttrText + '"' + ButtonColor + '>' + ButtonText + '</a>';
207					}
208				}
209                if(TextColor !== '') {
210                  title = title.replace('<div','<div style="color:' + TextColor + ';"');
211                  subtitle = subtitle.replace('<div','<div style="color:' + TextColor + ';"');
212                }				
213				var caption = '<div class="caption">' + title + subtitle + ButtonLink + '</div>';
214				$(caption).insertAfter(this);
215			}
216	  });
217      
218      // Re-factor the HTML on touch devices, so that swiping will work.
219		if(bOnTouchDevice && ImageList.length > 1){
220          gallery_ul.children().children('a').each(function() { // > li > a
221             var ThisA = $(this);
222             if(ThisA.find('a').length === 1){
223              ThisA.children().insertAfter(ThisA);
224              ThisA.hide();
225             }
226          });
227        }
228      
229	}
230}
231
232// define a function, so we can activate a SlickNav menu in a controlled way.
233var SlickNavBtn, HeaderSlice;
234var IEDy = 0, bEDopen = false;
235function ActivateMenu(SliceName) {
236	if (SectionTagExists(SliceName)) { // check if slice exists, and load into SectionTag if it does
237
238	  var SectionTagRef = GetSectionTagRef(SliceName);
239	  var RootMenuDeskTop = SectionTag.children('div.nav-menu').children('ul.root_menu');
240
241	  RootMenuDeskTop.slicknav({ // activate SlickNav for this slice.
242		prependTo: SectionTagRef + '> div.SlickNav_Wrapper',
243		allowParentLinks: true, // Top level items can be links
244		label: 'Menu',
245		// Use hex escape characters here.
246		closedSymbol: '&#xe900', // a logical OR "V" symbol
247		openedSymbol: '&#xe901', // a nice up pointing ">" symbol
248		duplicate: bDesktopScreenPossible // only need to duplicate if the desktop menus might be needed.
249	  });
250
251		// Add extra links onto the menu, to replace top-link log-out buttons etc.
252		// We can only do this after the menu is initialised, so that class "slicknav_nav" exists.
253      	var ExtraLink_0 = '';
254		var ExtraLink_1, ExtraLink_2;
255		if (bUserLoggedIn) {
256      		ExtraLink_0 = '<li class="ExtraLink"><a href="/MyArea/Introduction.aspx"><i class="icomoon-TopLinks-MyArea"></i>My Area</a></li>';
257          	ExtraLink_1 = '<li class="ExtraLink"><a href="/User/Logout.aspx"><i class="journey-icon-login"></i>Logout</a></li>';
258			ExtraLink_2 = '<li class="ExtraLink"><a href="/Admin/Default.aspx"><i class="icomoon-TopLinks-WebOffice"></i>Web Office</a></li>';
259		  } else {
260			ExtraLink_1 = '<li class="ExtraLink"><a href="/user/login.aspx"><i class="journey-icon-login"></i>Login</a></li>';
261			ExtraLink_2 = '<li class="ExtraLink"><a href="/User/Registration.aspx"><i class="icomoon-TopLinks-Register"></i>Register</a></li>';
262		  }
263		  var ExtraLink_3 = '<li class="ExtraLink SearchOpen"><a><i class="journey-icon-search"></i>Search</a></li>';
264		  var SlickNavLastItem = SectionTagRef + 'ul.slicknav_nav > li:last-child';
265		  $(ExtraLink_0 + ExtraLink_1 + ExtraLink_2 + ExtraLink_3).insertAfter(SlickNavLastItem);
266
267		if (bOnTouchDevice && bDesktopScreenPossible) { // have to do more work on menus.
268
269			// Having made the SlickNav menu - delete what we don't want.
270			
271			SectionTag.children("div.SlickNav_Wrapper").children("div.slicknav_menu").children('ul.slicknav_nav').find('li.SlickNavNotNeeded').remove();
272
273			// deactivate the top level <a> tag in the desk-top version so touch-screens work correctly.
274			// The link goes nowhere, but retains all the styling.
275			RootMenuDeskTop.children("li.has_sub_menu").children('a').removeAttr("href");
276		}
277
278		// Add a close menu icon into slickNav.
279		var SlickNavIcon = SectionTag.find('span.slicknav_icon');
280		$('<div class="SlickNavCloseIcon"></div>').insertAfter(SlickNavIcon);
281
282		// apply all the visibility on-clicks to make the menu slice work.
283
284		// Find some commonly used items.
285		var SearchOverlay = SectionTag.parent().children("div.search-overlay");
286      	var MobileSearchOpen = SectionTag.find("div.SlickNav_Wrapper li.ExtraLink.SearchOpen");
287		SlickNavBtn = SectionTag.find("a.slicknav_btn");
288		//var Logo = SectionTag.find("div.logo-container");
289
290		//ApplyToggleOnClick(SectionTag, "li.ExtraLink.SearchOpen", SearchOverlay, 0, false);
291      	// Open search function.
292      	MobileSearchOpen.click(function(){
293          SearchOverlay.addClass('On');
294          SearchOverlay.find('input.text').focus();
295        });
296      
297		//ApplyToggleOnClick(SectionTag, "div.top-link-wrapper a:nth-child(3)", SearchOverlay, 0, false);
298		//ApplyToggleVisibilityOnClick(SectionTag, "div.top-link-wrapper a:last-child", SearchOverlay, 0, false);
299
300      	//ApplyHideOnClick(SectionTag, "a.search-close", SearchOverlay);
301		//ApplyHideOnClick(undefined, SlickNavBtn, SearchOverlay);
302		// Toggles for menu-bars and menu-close icons
303		ApplyToggleOnClick(undefined, SlickNavBtn, SlickNavIcon, 0, true); // no delay on the toggle.
304		ApplyToggleOnClick(SectionTag, SlickNavBtn, "div.SlickNavCloseIcon", 0, false); // no delay on the toggle.
305
306      	// Make fixed slicknav scrollable.
307		var Mask = SectionTag.parent().children('div.MobileMenuMask');
308      	ApplyToggleVisibilityOnClick(undefined, SlickNavBtn, Mask, 0, false); // no delay on the toggle.
309      	ApplyToggleClassOnClick(SectionTag, SlickNavBtn, SectionTag, 'SlickNavFullWidth'); 
310      	SlickNavBtn.click(function(){
311          if(!bEDopen){
312            IEDy = window.pageYOffset;
313          	window.scrollTo(0,0);
314          } else {
315            window.scrollTo(0,IEDy);
316          }
317          bEDopen = !bEDopen;
318        });
319      
320        var LastMenuLi = SectionTag.find("ul.root_menu > li:last-child a");
321      	LastMenuLi.click(function(){
322          SearchOverlay.addClass('On');
323          SearchOverlay.find('input.text').focus();
324          //Mask.show();
325        });
326		var SearchClose = SectionTag.parent().find('a.search-close');
327      	SearchClose.click(function(){
328          SearchOverlay.removeClass('On');
329          //if(!SlickNavBtn.hasClass('slicknav_open')){
330          	//Mask.hide();
331          //}
332        });
333
334		// Need autocomplete="off" to be added to the search box <input> tag.
335		// This stops horrible browser autocomplete text from appearing.
336		SectionTag.find('div.search_div input').attr("autocomplete","off");
337
338	  }
339}
340
341function ActivateFooter(SliceName) {
342	if (bSplitFooterAddressAtSecondComma) {
343		if (SectionTagExists(SliceName)) { // check if slice exists, and load into SectionTag if it does
344			// .footer-column-2 can be a div or a span, so just look for the class.
345			var FooterAddress = SectionTag.find('.footer-column-2');
346			var AddressText = FooterAddress.text();
347			AddressText = AddressText.replace(/\,/, "¬"); // change first comma
348			AddressText = AddressText.replace(/\,/, ",<br>"); // now break at the 2nd comma
349			AddressText = AddressText.replace(/¬/, ","); // put back first comma
350			FooterAddress.html(AddressText);
351		}
352	}
353}
354 
355// The css needed for the code below is already in ContentPage.css files
356var LIs;
357function RemoveActiveLink(GNum) {
358  var Link = '/Groups/' + GNum + '/';
359  var A = LIs.children('a[href^="' + Link + '"]');
360  A.removeAttr('href').css('cursor','auto');
361  if (bOnTouchDevice){A.next().children().eq(0).remove();}
362  // Check top box of side-bar group-nav
363  var BHM = BodyTag.find('nav td.boxout_header_middle a');
364  if(BHM.length === 1 && !BHM.hasClass('NotActiveGroupNavBoxLink') && BHM.attr('href').startsWith(Link)){
365    BHM.removeAttr('href').addClass('NotActiveGroupNavBoxLink');
366  }
367  if (location.pathname.startsWith(Link)){
368    if (SectionTagExists('slice_content_page')) {
369      if(SectionTag.find('div.main-content').length === 0){
370        var H = '<div class="main-content"><div class="ArticleBody"></div></div>';
371      	$(H).prependTo(SectionTag.find('div.container'));
372      }
373      var SideLinks = SectionTag.find('aside nav div.group_nav_selected').clone();
374      SideLinks.addClass('ClonedGroupNav');
375      var Atag = SideLinks.children('a');
376      Atag.removeAttr('href');
377      $('<div>Please choose a sub-page:</div>').insertAfter(Atag);
378      SectionTag.find('div.main-content div.ArticleBody').html(SideLinks);
379    }
380  }
381}
382 
383var iMissingImage = 0;
384function AddMissingImageHTML(Card, prefix){
385  if(Card.find('img').length === 0){
386    iMissingImage++;
387    if(iMissingImage === 7){iMissingImage = 1;}
388    var href = Card.find('div.' + prefix + 'ListTitle a').attr('href');           
389    var ImgSrc = '/Hubb/Images/Background-0' + iMissingImage.toString() + '.jpg';
390    var S = '<div class="' + prefix + 'ListImage"><a href="' + href + '"><img src="' + ImgSrc + '"></a></div>';
391    $(S).prependTo(Card);
392  }   
393}
394 
395function ActivateArticleList3(SliceName) {
396	if (SectionTagExists(SliceName)) { // check if slice exists, and load into SectionTag if it does
397
398      // Get the parallax image
399      var ImgSrc = SectionTag.children('div.HideElement').find('img');
400      if(ImgSrc.length > 0){
401        var S = 'url(' + ImgSrc.eq(0).attr('src') + ')';
402      	SectionTag.css('background-image',S);
403      }
404      
405      SectionTag.find('div.UML_AL_1 > div').each(function () {	
406        var ThisCard = $(this);
407      	AddMissingImageHTML(ThisCard,'article');
408      });
409      
410		// Get the summaries
411		var Summarys = SectionTag.find('div.articleListSummary span');
412
413	  // Create the links at the bottom of the article cards. 
414	  var j=0;
415	  SectionTag.find('div.articleListTitle a').each(function () {
416		var ThisAtag = $(this);
417		var titleLink = ThisAtag.attr("href");
418		var articleListLink = ThisAtag.parent().parent().children('.articleListLink');
419		// See if we have new link text.
420		if (TextExists(Summarys.eq(j).text(), true)) {
421			if (sAttrText2 !== '') {
422				articleListLink.text(sAttrText2);
423			}
424		}
425		articleListLink.wrapInner('<a class="ArrowToRight" href="' + titleLink + '">');
426		j++;
427	  });
428	  
429	  Summarys.each(function () {
430		var ThisSummary = $(this);
431		var S = ThisSummary.text();
432		if (TextExists(S, true)) {
433			sAttrText = sAttrText.replace(/\\/g,'<br>');
434			if (S !== sAttrText) {
435				ThisSummary.html(sAttrText);
436			}
437		}
438 	  });
439  }
440}
441 
442function ActivateEventsList4(SliceName) {
443	if (SectionTagExists(SliceName)) { // check if slice exists, and load into SectionTag if it does
444      	SectionTag.find('div.UML_EL_1 > div').each(function () {	
445          var ThisCard = $(this);
446		  AddMissingImageHTML(ThisCard,'event');
447          var ThisDate = ThisCard.find('div.eventListDate');
448          var S = ThisDate.text();
449		  // If date looks like a US version ie. "MMM DD", then swap some stuff around.
450		  var S13 = S.substr(0,1);
451		  if(S13 === 'J' || S13 === 'F' || S13 === 'M' || S13 === 'A' || S13 === 'S' || S13 === 'O' || S13 === 'N' || S13 === 'D'){
452			  S = S.substr(3,3).trim() + ' ' + S.substr(0,3) + ' ' + S.substr(6).trim();
453		  }
454          // Now carry on, as all dates are in 'DD MMM' format.
455		  ThisDate.text(S.substr(6).trim());
456          var DN = S.substr(0,2).trim();
457          if(DN.length === 1){DN = '0' + DN;}
458          var DM = S.substr(2,4).trim().toUpperCase();
459          var BoxDate = '<div class="BoxDate"><div>' + DN + '</div><div>' + DM + '</div></div>';
460		  $(BoxDate).appendTo(ThisDate);
461        });
462    }
463}
464 
465function ActivateMediaList4(SliceName) {
466	if (SectionTagExists(SliceName)) { // check if slice exists, and load into SectionTag if it does
467      	SectionTag.find('div.UML_ML_1 span.MediaList > div').each(function () {	
468          var ThisCard = $(this);
469		  AddMissingImageHTML(ThisCard,'media');
470          var BoxDate = '<div class="BoxDate"><span></span></div>'; // Icon added to the <span> via CSS
471		  var ImageLink = ThisCard.find('div.mediaListImage a');
472          $(BoxDate).appendTo(ImageLink);
473        });
474    }
475}
476 
477function ActivateBlockImages(SliceName) {
478	if (SectionTagExists(SliceName)) { // check if slice exists, and load into SectionTag if it does
479		SectionTag.find("div.image_blocks img" ).each(function() {
480          	var ThisImg = $(this);
481			if (TextExists(ThisImg.attr('alt'), true)) { // check if there is any alt text.
482				var cardGridCaption = '<div class="image_block_title_wrapper"><div class="image_block_title">' + sAttrText + '</div><div class="image_block_text">' + sAttrText2 + '</div></div>';
483				$(cardGridCaption).insertAfter( ThisImg );
484			}
485			ThisImg.removeAttr('title'); // remove the title attribute so that pop-up text does not appear.
486		});
487	}
488}
489 
490function ActivateSlideShowSideBar(SliceName) {
491  //return;
492	if (SectionTagExists(SliceName)) { // check if slice exists, and load into SectionTag if it does
493	  var AB = SectionTag.find("div.SlideShowArticle div.ArticleBody");
494      var S = '<div class="DropBelow"></div>';
495      $(S).insertAfter(AB.children().eq(3));
496      var Tags = AB.children();
497      var DB = Tags.eq(4);
498      Tags.eq(2).clone().prependTo(DB);
499      Tags.eq(1).clone().prependTo(DB);
500      Tags.eq(0).clone().prependTo(DB);
501	}
502}
503 
504// ########################## Check various conditions #############################
505
506var bOnTouchDevice = ('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0);
507var iDeskTopWidth = 992;
508var iMobileScreenAllowence = 64; // Because of other stuff on a screen, you have to assume the browser window could get bigger on a rotation.
509var bDesktopScreenPossible = ((screen.width + iMobileScreenAllowence) >= iDeskTopWidth || (screen.height + iMobileScreenAllowence) >= iDeskTopWidth);
510
511var BodyTag = $('body');
512var bOnSystemPopupPage = BodyTag.hasClass('system_popup') || (window.location.href.toLowerCase().indexOf('popup=yes') !== -1);
513var bUserLoggedIn = BodyTag.hasClass('logged_in_user');
514
515SectionTags = BodyTag.find('section'); // Store all the section tags to speed up later code.
516var bOnContentPage = SectionTags.hasClass('slice_content_page');
517var bOnSystemPage = SectionTags.hasClass('slice_system_page');
518var bOnHomePage = SectionTags.hasClass('slice_SlidesFullWidth');
519 
520// Corrections for various hardware.
521var P = navigator.platform.trim().toLowerCase();
522//alert('Device: ' + P);
523var bSmallAppleDevice = (P === 'iphone' || P === 'ipad' || P === 'ipod');
524if (bSmallAppleDevice) {
525	BodyTag.addClass('OnSmallAppleDevice');
526  //alert('DeviceX: ' + P);
527}
528 
529// Activate the slide shows first as they are usually near the top of the visible screen.
530if (bOnHomePage) {
531
532	// ##############################################################
533	// # js for Slide Shows slices. We use BX-slider V4.2.5
534	// ##############################################################
535
536	// The slide-shows are hidden via CSS when the page first loads, to give a smoother page-load experience.
537	// All slide-show CI modules must have a class "bannerSlides" defined within them.
538
539	// Activate all the slide-shows. Do in sensible order, so any visible ones are done first.
540// All slide shows have the same defaults at present.
541  BxDefaultValues = {
542      mode: 'fade',
543      auto: true,
544      pause: 8000,
545      speed: 500,
546      pager: true,
547      controls: false,
548      preloadImages: 'all',
549      adaptiveHeight:true,
550      touchEnabled:false,
551      buildPager: function(i){return i+1;}
552  };
553	ActivateBxSlider('slice_SlidesFullWidth');
554}
555
556// #######################################
557// # Menu data changes
558// #######################################
559
560// We make the required adjustments to the one set of menu HTML on the page, before cloning it and activating all the copies.
561
562var ulModuleRootMenu = BodyTag.find('ul.root_menu');
563var bMenuPresent = (ulModuleRootMenu.length !== 0);
564if (bMenuPresent) {
565
566   /* remove sub menus from Home */
567   // We check that the first link actually looks like a "Home" one.
568   // We assume that the home menu (if present) is the first item within a menu.
569  var HomeMenuLi = ulModuleRootMenu.children('li:first-child');
570  if(HomeMenuLi.children('a').text().trim().toLowerCase() === 'home'){
571	  HomeMenuLi.children('ul').remove();
572	  HomeMenuLi.removeClass('has_sub_menu'); // remove class
573  }
574  
575  // Make sure the online bible goes to a fresh tab/page.
576  ulModuleRootMenu.find('a[href$="/Online_Bible.aspx"]').attr("target","_blank");  
577  
578  // Set up the search icon in the search box.
579  /*
580  var DeskTopSearchBox = BodyTag.find('header div.top-link-wrapper div.search-form');
581  $('<i class="journey-icon-search"></i>
581').appendTo(DeskTopSearchBox);
582  var HiddenSearchBox = DeskTopSearchBox.find('input.button');
583  var EyeGlass = DeskTopSearchBox.find('i');
584  EyeGlass.click(function(){HiddenSearchBox.click();}); // set up the click.
585  var InputText = DeskTopSearchBox.find('input.text');
586  InputText.focus(function(){EyeGlass.addClass('InFocus');});
587  InputText.blur(function(){EyeGlass.removeClass('InFocus');});
588  */
589  
590  if (bUserLoggedIn) {
591	//ulModuleRootMenu.children('li:last-child').children('ul').remove(); // delete submenus of Myarea.
592	BodyTag.find('header div.top-link-wrapper a.Login').attr('href','/user/logout.aspx').text('LOGOUT');
593	BodyTag.find('header div.top-link-wrapper a.Bookings').attr('href','/admin').text('WEB OFFICE');
594  }  
595  
596  // remove copies of 1st item elements in dropdown sub-menu.
597  ulModuleRootMenu.find('li.menu_item_level_2:first-child').each(function() {
598
599	var ThisLi = $(this);
600	if(ThisLi.children("a[href^='/MyArea/']").length === 0) { // only if not a link into /MyArea/...
601
602	  if(ThisLi.siblings().length === 0) { // no other <li> so it is the only entry
603		var ul = ThisLi.parent();
604	    ul.parent().removeClass('has_sub_menu'); // remove class from the <li> at the level above
605		ul.remove(); // delete whole parent <ul>
606
607	  } else {
608		if (bOnTouchDevice && bDesktopScreenPossible) {
609			// On a touch device, the copies of the level one links at the 2nd level have to be kept for the desktop menus.
610			// But in the SlickNav menus, these 2nd level links are not needed.
611			// So we mark the items so we can delete them later, after data is copied into the SlickNav menu.
612			ThisLi.addClass('SlickNavNotNeeded'); // Mark the 2nd level <li> tag.
613		} else {
614			// Not on a touch screen, so Desktop and SlickNav menus will be the structurally the same.
615			ThisLi.remove(); // so just remove this <li> tag
616		}
617	  }
618	}
619  });
620  
621/*
622LIs = ulModuleRootMenu.children();
623RemoveActiveLink ('351004');
624RemoveActiveLink ('351006');
625*/
626  
627  $('<li class="MenuSearchOpen"><a><i class="journey-icon-search"></i></a></li>').appendTo(ulModuleRootMenu);
628
629	// #######################################
630	// # SlickNav menus V1.0.10
631	// #######################################
632
633	ActivateMenu('slice_Header_L');
634	
635	// ######## Footer Slice code ####################
636	
637	// If there is a header, then there is probably a footer.
638	// This is the footer top. There is no need to clone this HTML.
639	
640	ActivateFooter("slice_FooterTop_L");
641
642} // end of if bNeedMenus
643
644// Here do things ONLY needed on a home page.
645if (bOnHomePage) {
646
647  	ActivateSlideShowSideBar('SlideShowWrapper');
648  	ActivateBlockImages('slice_Gallery4');
649  	ActivateEventsList4('EventsCardsFour');
650  	ActivateMediaList4('SermonCardsFour');
651  
652} else if (bOnContentPage) {
653  
654  if (SectionTagExists('slice_content_page')) { // check if slice exists, and load into SectionTag if it does
655	
656	// code to try and make content images work on mobile phones. Set max-width css property is if has not already been set.
657	// If width and height attributes are both set, then the image is compressed horizontally, but that is still better than it overflowing.
658	var AB = SectionTag.find('div.main-content');
659  	var ContentImages = AB.find('img');
660	ContentImages.each(function() {
661		var Img = $(this);
662		if (Img.css('max-width') === 'none') {
663			Img.css('max-width','100%');
664		}
665	});
666  
667  	var TopAL = AB.find('div.TopMenuEntryAL');
668  	if(TopAL.length > 0){
669    	SectionTag.addClass('NoGroupNav');
670    }
671    
672    var FC = SectionTag.find('div.main-content div[id$="_elFormContents"]');
673    if(FC.length > 0){
674      SectionTag.addClass('HasForm');
675      // Look for a invisible-recaptcha
676      var IR = FC.children('div.invisible-recaptcha');
677      if (IR.length === 1){
678      	var ISB = FC.find('input.sitebutton[type="button"]');
679        if (ISB.length === 1){
680        	IR.insertAfter(ISB);
681        }
682      }
683    }
684  }
685	
686} else if (bOnSystemPage || bOnSystemPopupPage) {
687
688	// work out what kind of page we are on.
689	var PageType = window.location.pathname.toLowerCase();
690	if (PageType.endsWith(".aspx")) {
691		PageType = PageType.substring(0, PageType.indexOf(".aspx"));
692		PageType = PageType.replace(/\//g, "_"); // replace all / to _ Have to use \/ to get a / in the reg-ex. The g denotes a global exchange.
693		PageType = PageType + "_aspx";
694	} else {
695		// Assume we are on a local machine.
696		PageType = '_user_registration_aspx';
697	}
698	//alert(PageType);
699
700	/* Possible page types are now:
701	'_calendar_month_aspx'
702	'_media_allmedia_aspx'
703	'_user_registration_aspx'
704	'_user_copyright_aspx'
705	'_user_termsandconditions_aspx'
706	'_user_privacypolicy_aspx'
707	'_user_help_aspx'
708	'_publisher_search_aspx' - this is search results.
709	'_paymentgroup_registration_aspx'
710	'_myarea_walletitem_aspx'
711	*/
712
713	if (SectionTagExists("slice_system_page")) { // check if slice exists, and load into SectionTag if it does
714		SystemSlice = SectionTag;
715		SystemSlice.addClass(PageType); // add class onto <section> tag, so CSS can locate it.
716	} else {
717		BodyTag.addClass(PageType); // add class onto <body> tag, so CSS can locate it.
718		BodyTag.addClass('system_popup'); // add this in case it is not on.
719    }
720
721	if (PageType === '_media_allmedia_aspx' || PageType === '_publisher_search_aspx') {
722		
723		// Add a toggle for the media controls.
724		var MediaControls = SystemSlice.find('div#media_controls'); // these media controls are on the search page too.
725		if (MediaControls.length !== 0) {
726			$('<a class="system_toggle_advanced">Search Options</a>').insertBefore(MediaControls);
727			ApplyToggleOnClick(SystemSlice, "a.system_toggle_advanced", MediaControls, 0, false);
728          	$('<div class="LineB"></div>').insertAfter(MediaControls.children().eq(3)); // do 3 before 1
729            $('<div class="LineB"></div>').insertAfter(MediaControls.children().eq(1));
730          	$('<div class="Line"></div>').appendTo(MediaControls);
731          	var MediaSort = SystemSlice.find('div#media_sort');
732          	MediaSort.appendTo(MediaControls);
733          	var XML = SystemSlice.find('ul#media_buttons');
734          	XML.children().children().text('( XML feed )');
735          	XML.appendTo(MediaControls);
736          	var CloseImg = $('<img src="/Images/Content/2427/Templates/53446/images/IconClose.png">');
737            CloseImg.click(function(){
738              MediaControls.hide();
739            });
740          	CloseImg.prependTo(MediaControls);
741		}
742		
743		HideDivsIfAllEmpty('media_summary_image'); // Hide some empty columns, if needed.
744		
745		if (PageType === '_publisher_search_aspx') { // Extra things to do on the search page.
746			
747			HideDivsIfAllEmpty('search_article_image'); // Hide some empty columns, if needed.
748			HideDivsIfAllEmpty('search_event_image'); // Hide some empty columns, if needed.
749			
750			// If we have been sent to the search page explicitly then prepare the page for searching.
751			 var SearchBox = SystemSlice.find('input[id$="_txtSearchStringTemplate"]');
752			 if (SearchBox.length === 1) {
753				 if (SearchBox.val() === 'Activate_Search') {
754					 SystemSlice.find('h2').hide(); // hide the search result titles
755					 SearchBox.val(''); // Clear the search text box
756					 SearchBox.attr('placeholder','Type your search text here');
757					 SearchBox.attr("autocomplete","off");
758					 MediaControls.show(); // make the search controls show.
759				 }
760			 }
761        } else {
762          SystemSlice.find('ul.media_recording_details li:nth-child(2)').each(function(){
763          	var T = $(this);
764            var S = T.text().replace('Recorded: ','');
765            var H = '<div class="MobileRecorded">' + S + '</div>';
766            $(H).insertAfter(T.parent().parent().prev().children('div.media_recording_descr'));
767          });
768        }
769	} 
770
771	// Fix calendar mobile page. Add a class to days we want to hide on the mobile/list view.
772	if (PageType === '_calendar_month_aspx') {
773      	var C = SystemSlice.find('select.group-selector');
774      	var H = SystemSlice.find('div#calendar_header');
775      	C.insertAfter(H.children().eq(0));
776      	$('<div class="Line"></div>').insertAfter(H.children().eq(1));
777      	var S = SystemSlice.find('span.calendar_children_select');
778      	S.insertAfter(H.children().eq(2));
779	}
780
781} // end of bOnHomePage or bOnSystemPage if-block
782                               
783// Sort out login/logout/register/web-office links
784var SB = BodyTag.find('div.HiddenStatusBar');
785if (SB.length === 1) {
786	if (bUserLoggedIn) {
787		var bWebOfficeActive = (SB.find('a.weboffice_link').length === 1);
788		if (!bWebOfficeActive) { // Need to hide WO links.
789			BodyTag.find('header a[href="/admin"]').hide();
790			BodyTag.find('header a[href="/Admin/Default.aspx"]').hide();
791			BodyTag.find('section.slice_FixedSideLinks a[href="/admin"]').hide();
792		}
793	} else {
794		var SBRL = SB.find('a.register_link');
795		if (SBRL.length === 0) { // Need to hide the register links. Need TWO versions for case changes.
796			BodyTag.find('header a[href="/User/Registration.aspx"]').hide();
797			BodyTag.find('header a[href="/user/registration.aspx"]').hide();
798			BodyTag.find('section.slice_FixedSideLinks a[href="/User/Registration.aspx"]').hide();
799			BodyTag.find('section.slice_FixedSideLinks a[href="/user/registration.aspx"]').hide();
800		} else {
801			var RegLink = SBRL.attr('href');
802			if (RegLink !== "/User/Registration.aspx") {
803				BodyTag.find('header a[href="/User/Registration.aspx"]').attr('href',RegLink);
804				BodyTag.find('header a[href="/user/registration.aspx"]').attr('href',RegLink);
805				BodyTag.find('section.slice_FixedSideLinks a[href="/User/Registration.aspx"]').attr('href',RegLink);
806				BodyTag.find('section.slice_FixedSideLinks a[href="/user/registration.aspx"]').attr('href',RegLink);
807			}
808		}
809	}
810}
811 
812// Fix Footer
813var LW = BodyTag.find('footer div.LogoWrapper');
814 if(LW.length === 0){
815 	var FSG = BodyTag.find('footer div.FooterSafeGuarding');
816   if(FSG.length === 1){
817     FSG.addClass('BottomBorder');
818   }
819 }
820 
821// Fix the cookies slice
822HeaderSlice = BodyTag.find('header');
823var CS = HeaderSlice.find('div.slice_Cookies');
824 if (CS.length === 1) {
825   	var IMG = CS.find('img');
826   	IMG.attr('src','/Images/Content/2823/Templates/56063/images/IconClose.png');
827     IMG.click(function(){
828     	HeaderSlice.removeClass('HasCookieBar');
829     });
830    HeaderSlice.addClass('HasCookieBar');
831 }
832 
833// Sticky header
834// We need iYforHeaderTintDown - iYforHeaderTintUp to be larger than the difference between heights
835// for the large and small headers.
836var bHeaderTintOn = false, iYforHeaderTintDown = 50,  iYforHeaderTintUp = 2;
837function PollScrollDownChanges() { // This routine must be very streamlined. Called every 250ms.
838
839	var iY = window.pageYOffset;
840
841	if (!bHeaderTintOn && iY >= iYforHeaderTintDown) {
842		if (window.innerWidth > 991) { // only apply if screen is of desktop size.
843			HeaderSlice.addClass('HeaderSmall');
844			bHeaderTintOn = true;
845		}
846	}
847	if (bHeaderTintOn && iY < iYforHeaderTintUp) {
848        HeaderSlice.removeClass('HeaderSmall');
849		bHeaderTintOn = false;
850	}
851}
852
853// If the screen is resized, then we have to click shut the SlickNav Menu, if it is open.
854var iLastWidth = 0;
855function ShutSlickNav() {
856	var iWidth = window.innerWidth;
857	if (iWidth !== iLastWidth) { // don't run code if it looks like we just have the browser top menu appearing and disappearing.
858		iLastWidth = iWidth;
859		if (bDesktopScreenPossible) {
860			if (SlickNavBtn.hasClass('slicknav_open')){
861				SlickNavBtn.click();
862			}
863			if (bOnHomePage && iWidth < 992 && HeaderSlice.hasClass('HeaderSmall')) { 
864				HeaderSlice.removeClass('HeaderSmall');
865				bHeaderTintOn = false;
866			}
867		}
868	}
869}
870
871window.addEventListener("resize", function(){ShutSlickNav();}, false); 
872if (bDesktopScreenPossible) {
873	window.setInterval(function(){PollScrollDownChanges();}, 100); // poll to see if user has scrolled down.
874}
875 
876// SlickNav poll - for the top level, when you open a sub-menu up, the others close up.
877var SL = BodyTag.find('header ul.slicknav_nav');
878var LI = SL.children('li.slicknav_parent'); // these are the only top-links with a sub-menu
879var iOpen = -1;
880var iOpenMax = LI.length - 1;
881var bSwitch = true;
882LI.eq(0).click(function(){if(bSwitch){iOpen=0;}});
883LI.eq(1).click(function(){if(bSwitch){iOpen=1;}});
884LI.eq(2).click(function(){if(bSwitch){iOpen=2;}});
885LI.eq(3).click(function(){if(bSwitch){iOpen=3;}});
886LI.eq(4).click(function(){if(bSwitch){iOpen=4;}});
887LI.eq(5).click(function(){if(bSwitch){iOpen=5;}});
888LI.eq(6).click(function(){if(bSwitch){iOpen=6;}});
889LI.eq(7).click(function(){if(bSwitch){iOpen=7;}});
890LI.eq(8).click(function(){if(bSwitch){iOpen=8;}});
891LI.eq(9).click(function(){if(bSwitch){iOpen=9;}});
892LI.eq(10).click(function(){if(bSwitch){iOpen=10;}});
893LI.eq(11).click(function(){if(bSwitch){iOpen=11;}}); // enough code for 12 sub-menus.
894 
895 function SlickNavPoll() {   
896   if(iOpen !== -1){
897    var i;
898    for (i = 0; i <= iOpenMax; i++) {
899      if(i !== iOpen){
900        if(LI.eq(i).hasClass('slicknav_open')){
901          bSwitch = false;
902          LI.eq(i).children('a').click();
903          bSwitch = true;
904      	}
905      }
906    } // end for       
907   }
908 }
909window.setInterval(function(){SlickNavPoll();}, 250);
910
911});

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.