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 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 if (Ref === '') { // allows us to return the section tag itself. 43 return SectionTag; 44 } else { 45 return SectionTag.find(Ref); 46 } 47 } else { 48 return Ref; 49 } 50} 51 52// A function to easily set JQuery toggles. 53// SectionTag is a $ variable. 54function ApplyToggleVisibilityOnClick(SectionTag, ClickRef, ToggleRef, iDelay, bShowToggleItemInitially) { 55 56 var ClickItem = GetRefItem(SectionTag, ClickRef); 57 var ToggleItem = GetRefItem(SectionTag, ToggleRef); 58 59 if (bShowToggleItemInitially) { 60 ToggleItem.show(0); 61 } else { 62 ToggleItem.hide(0); 63 } 64 // Note we add a function here. Since we are only using calling function arguements inside the function argument, 65 // variable scoping correctly works. 66 ClickItem.click(function () { 67 ToggleItem.toggle(iDelay); 68 }); 69} 70 71function ApplyHideOnClick(SectionTag, ClickRef, ToHideRef) { 72 73 var ClickItem = GetRefItem(SectionTag, ClickRef); 74 var ToHideItem = GetRefItem(SectionTag, ToHideRef); 75 76 ClickItem.click(function () { 77 ToHideItem.hide(0); 78 }); 79} 80 81// function to test if text exists. 82var sAttrText, sAttrText2, sAttrText3, sAttrText4; // Results come back in these variables. 83var DollarTextarea = $("<textarea/>"); // store this once. 84function TextExists(attrText, bSplit) { 85 86 if (attrText === undefined) {return false;} 87 if (attrText === null) {return false;} 88 89 var TextToProcess = attrText.trim(); 90 if (TextToProcess === '') {return false;} 91 92 // decode the text, so that &lt; becomes < etc. 93 // This works by turning into HTML and then turning back into text. 94 if (TextToProcess.indexOf('&') !== -1) { // we could use the .includes('&') method, but it is quite new, so some browsers can't cope. 95 TextToProcess = DollarTextarea.html(TextToProcess).text(); 96 } 97 if (TextToProcess === '') {return false;} 98 99 sAttrText = ''; // set return values to blank. 100 sAttrText2 = ''; 101 sAttrText3 = ''; 102 sAttrText4 = ''; 103 if (bSplit) { 104 var arrSplitText = TextToProcess.split('*'); 105 sAttrText = arrSplitText[0].trim(); 106 if (arrSplitText.length > 1) {sAttrText2 = arrSplitText[1].trim();} 107 if (arrSplitText.length > 2) {sAttrText3 = arrSplitText[2].trim();} 108 if (arrSplitText.length > 3) {sAttrText4 = arrSplitText[3].trim();} 109 } else { 110 sAttrText = TextToProcess; 111 } 112 113 return (sAttrText + sAttrText2 + sAttrText3 + sAttrText4 !== ''); 114} 115 116// Function to hide a column if it contains no images. 117var SystemSlice; 118function HideDivsIfAllEmpty(ColumnClass) { 119 var ImageWrappers = SystemSlice.find('div.' + ColumnClass); 120 if (ImageWrappers.find('img').length === 0) { // have to use find not children, as img tags can be inside <a> tags. 121 ImageWrappers.hide(0); 122 } 123} 124 125// ################### Slice activation functions go here. ######################### 126 127// All slide shows have the same defaults at present. 128var BxDefaultValues = { 129 mode: 'fade', 130 auto: true, 131 pause: 8000, 132 speed: 500, 133 pager: true, 134 controls: true, 135 preloadImages: 'all', 136 touchEnabled: false, 137 adaptiveHeight: true 138}; 139 140function ActivateBxSlider(SliceName) { 141 if (SectionTagExists(SliceName)) { // check if slice exists, and load into SectionTag if it does 142 143 var bannerSlides = SectionTag.find('div.bannerSlides'); // use a "find" here, as structure of slices varies. 144 var gallery_ul = bannerSlides.children('ul.gallery_ul'); 145 var ImageList = gallery_ul.find('img'); 146 if (ImageList.length === 0) {return;} // No images, so give up. 147 148 // ul.gallery_ul must be displayed before bx-slider can be applied. 149 // So since we hide it while the page was loading, we show it now. 150 bannerSlides.show(0); // show the slice now. It was hidden by CSS. 151 152 if (ImageList.length > 1) { // carry on as normal. 153 gallery_ul.bxSlider(BxDefaultValues); 154 } else { // Just 1 image, so we don't set up the slider, but do some minor adjustments to help the CSS. 155 gallery_ul.css('margin','0px'); 156 var S = '<div class="bx-wrapper"><div class="bx-viewport"></div></div>'; 157 gallery_ul.wrap(S); 158 } 159 160 // Code to enable user defined text to appear over banner slides. 161 ImageList.each(function() { 162 var ThisImg = $(this); 163 if (TextExists(ThisImg.attr('alt'), true)) { // check if there is any alt text. 164 var DarkenedClass = ''; 165 if (bAddDarkenedOverlayForSlideShowCaptions) {DarkenedClass = ' DarkenedOverlay';} 166 var title = '<div class="slideTitle' + DarkenedClass + '">' + sAttrText + '</div>'; 167 // even if the subtitle text is empty, we keep the div for styling reasons.
168 // If there is a long caption, reduce font weight from bold to normal. 169 var FontStyle = ''; 170 if (sAttrText2.length > 100) {FontStyle = ' style="font-weight:400;" ';} 171 var subtitle = '<div class="slideText' + DarkenedClass + '"' + FontStyle + '>' + sAttrText2 + '</div>'; 172 173 var ButtonLink = ''; 174 var ButtonText = sAttrText3; 175 if (ButtonText === '') {ButtonText = SlideShowDefaultButtonText;} 176 if (ButtonText !== '' && ButtonText !== 'none'){ 177 var ButtonColor = sAttrText4; 178 if (TextExists(ThisImg.parent().attr('href'), false)) { // check for href text. NOTE: sAttrTextX values are reset. 179 180 // add button colour if we have some colour data. 181 // Check for a " character, as that will spoil our HTML. 182 if (ButtonColor !== '' && ButtonColor.indexOf('"') === -1) { 183 ButtonColor = ' style="background-color:' + ButtonColor + ' !important;border-color:' + ButtonColor + ' !important;" '; 184 } 185 186 // build the completed button link. 187 ButtonLink = '<a class="slideButton" href="' + sAttrText + '"' + ButtonColor + '>' + ButtonText + '</a>'; 188 } 189 } 190 191 var caption = '<div class="caption">' + title + subtitle + ButtonLink + '</div>'; 192 $(caption).insertAfter(this); 193 } 194 ThisImg.removeAttr('title'); // remove the title attribute so that pop-up text does not appear. 195 }); 196 } 197} 198 199// define a function, so we can activate a SlickNav menu in a controlled way. 200function ActivateMenu(SliceName) { 201 if (SectionTagExists(SliceName)) { // check if slice exists, and load into SectionTag if it does 202 203 var SectionTagRef = GetSectionTagRef(SliceName); 204 var RootMenuDeskTop = SectionTag.children('div.nav-menu').children('ul.root_menu'); 205 206 RootMenuDeskTop.slicknav({ // activate SlickNav for this slice. 207 prependTo: SectionTagRef + '> div.SlickNav_Wrapper', 208 allowParentLinks: true, // Top level items can be links 209 label: 'Menu', 210 // Use hex escape characters here. 211 closedSymbol: '', // a logical OR "V" symbol 212 openedSymbol: '', // a nice up pointing ">" symbol 213 duplicate: bDesktopScreenPossible // only need to duplicate if the desktop menus are needed. 214 }); 215 216 var SlickNavLastItem = SectionTag.find('ul.slicknav_nav > li:last-child'); 217 //Add extra links onto the SlickNav menu manually, to replace top-link log-out buttons etc. 218 var ExtraLink_1, ExtraLink_2; 219 if (bUserLoggedIn) { 220 ExtraLink_1 = '<li class="ExtraLink"><a href="/User/Logout.aspx"><i class="journey-icon-login"></i>Logout</a></li>'; 221 ExtraLink_2 = '<li class="ExtraLink"><a href="/Admin/Default.aspx"><i class="journey-icon-register"></i>Web Office</a></li>'; 222 } else { 223 ExtraLink_1 = '<li class="ExtraLink"><a href="/user/login.aspx"><i class="journey-icon-login"></i>Login</a></li>'; 224 ExtraLink_2 = '<li class="ExtraLink"><a href="/User/Registration.aspx"><i class="journey-icon-register"></i>Register</a></li>'; 225 } 226 var ExtraLink_3 = '<li class="ExtraLink SearchOpen"><a><i class="journey-icon-search"></i>Search</a></li>'; 227 $(ExtraLink_1 + ExtraLink_2 + ExtraLink_3).insertAfter(SlickNavLastItem); 228 229 if (bOnTouchDevice && bDesktopScreenPossible) { // have to do more work on menus. 230 231 // Having made the SlickNav menu - delete what we don't want. 232 233 SectionTag.children("div.SlickNav_Wrapper").children("div.slicknav_menu").children('ul.slicknav_nav').find('li.SlickNavNotNeeded').remove(); 234 235 // deactivate the top level <a> tag in the desk-top version so touch-screens work correctly. 236 // The link goes nowhere, but retains all the styling. 237 RootMenuDeskTop.children("li.has_sub_menu").children('a').removeAttr("href"); 238 } 239 240 // Add a close menu icon into slickNav. 241 var SlickNavIcon = SectionTag.find('span.slicknav_icon'); 242 $('<div class="SlickNavCloseIcon"></div>').insertAfter(SlickNavIcon); 243 244 // apply all the visibility on-clicks to make the menu slice work. 245 246 // Find some commonly used items. 247 var SearchOverlay = SectionTag.find("div.search-overlay"); 248 var SlickNavBtn = SectionTag.find("a.slicknav_btn"); 249 250 ApplyToggleVisibilityOnClick(SectionTag, "li.ExtraLink.SearchOpen", SearchOverlay, 0, false);
251 ApplyToggleVisibilityOnClick(SectionTag, "div.top-link-wrapper a:last-child", SearchOverlay, 0, false); 252 ApplyHideOnClick(SectionTag, "a.search-close", SearchOverlay); 253 ApplyHideOnClick(undefined, SlickNavBtn, SearchOverlay); 254 // Toggles for menu-bars and menu-close icons 255 ApplyToggleVisibilityOnClick(undefined, SlickNavBtn, SlickNavIcon, 0, true); // no delay on the toggle. 256 ApplyToggleVisibilityOnClick(SectionTag, SlickNavBtn, "div.SlickNavCloseIcon", 0, false); // no delay on the toggle. 257 258 // Need autocomplete="off" to be added to the search box <input> tag. 259 // This stops horrible browser autocomplete text from appearing. 260 SectionTag.find('div.search_div input').attr("autocomplete","off"); 261 262 } 263} 264 265function ActivateFooter(SliceName) { 266 if (bSplitFooterAddressAtSecondComma) { 267 if (SectionTagExists(SliceName)) { // check if slice exists, and load into SectionTag if it does 268 // .footer-column-2 can be a div or a span, so just look for the class. 269 var FooterAddress = SectionTag.find('.footer-column-2'); 270 if (FooterAddress.children('*').length === 0) { // only proceed if there are no html tags within this element. 271 if (TextExists(FooterAddress.text(), false)) { 272 var AddressText = sAttrText; 273 if (AddressText.indexOf(',') !== -1) { 274 AddressText = AddressText.replace(/\,/, "¬"); // change first comma 275 if (AddressText.indexOf(',') !== -1) { 276 AddressText = AddressText.replace(/\,/, ",<br>"); // now break at the 2nd comma 277 AddressText = AddressText.replace(/¬/, ","); // put back first comma 278 FooterAddress.html(AddressText); // have to use html() here, as there is a <br> tag. 279 } 280 } 281 } 282 } 283 } 284 } 285} 286 287function ActivateArticleList4(SliceName) { 288 if (SectionTagExists(SliceName)) { // check if slice exists, and load into SectionTag if it does 289 290 // Get the summaries 291 var Summarys = SectionTag.find('div.articleListSummary span'); 292 293 // Create the links at the bottom of the article cards. 294 var j=0; 295 SectionTag.find('div.articleListTitle a').each(function () { 296 var ThisAtag = $(this); 297 var titleLink = ThisAtag.attr("href"); 298 var articleListLink = ThisAtag.parent().parent().children('.articleListLink'); 299 // See if we have new link text. 300 if (TextExists(Summarys.eq(j).text(), true)) { 301 if (sAttrText2 !== '') { 302 articleListLink.text(sAttrText2); 303 } 304 } 305 articleListLink.wrapInner('<a href="' + titleLink + '">'); 306 j++; 307 }); 308 309 Summarys.each(function () { 310 var ThisSummary = $(this); 311 var S = ThisSummary.text(); 312 if (TextExists(S, true)) { 313 sAttrText = sAttrText.replace(/\\/g,'<br>'); 314 if (S !== sAttrText) { 315 ThisSummary.html(sAttrText); 316 } 317 } 318 }); 319 } 320} 321 322function ActivateBlockImages(SliceName) { 323 if (SectionTagExists(SliceName)) { // check if slice exists, and load into SectionTag if it does 324 SectionTag.find("div.image_blocks img" ).each(function() { 325 if (TextExists($(this).attr('alt'), true)) { // check if there is any alt text. 326 var cardGridCaption = '<div class="image_block_title_wrapper"><div class="image_block_title">' + sAttrText + '</div><div class="image_block_text">' + sAttrText2 + '</div></div>'; 327 $(cardGridCaption).insertAfter( this ); 328 } 329 $(this).removeAttr('title'); // remove the title attribute so that pop-up text does not appear. 330 }); 331 } 332} 333 334function ActivateBannerImage(SliceName) { 335 if (SectionTagExists(SliceName)) { // check if slice exists, and load into SectionTag if it does 336 337 var bImageApplied = false; 338 var GnValues = SectionTag.find("span.groupnotes_value"); 339 if (GnValues.length > 0) { 340 341 if (TextExists(GnValues.eq(0).find("a").attr('href'), false)) { // assume first note is banner image. 342 343 SectionTag.css('background-image','url(' + sAttrText + ')'); 344 bImageApplied = true; 345 346 // background image applied, so add group name, if available. 347 if (TextExists($('head meta[name="Group Name"]').attr('content'), false)) { 348 SectionTag.find('h1').text(sAttrText); 349 } 350 351 // Apply css background-position if available. 352 if (GnValues.length > 1) { 353 var GnNames = SectionTag.find("span.groupnotes_name"); 354 TextExists(GnNames.eq(1).text(), false); 355 if (sAttrText.indexOf('Banner Image Position') !== -1) { // check if the second note is this. 356 if (TextExists(GnValues.eq(1).text(), false)) { 357 SectionTag.css('background-position', sAttrText); 358 } 359 } 360 } 361 } 362 } 363 if (!bImageApplied) { // Didn't find background image, so hide the whole slice. 364 SectionTag.hide(); 365 if (SectionTagExists('slice_content_page')) { // add a grey border to the content slice. 366 SectionTag.addClass('AddTopBorder'); 367 } 368 } 369 } 370} 371 372function BuildArticleSlider(SliderSliceName, SliderBlogName) { 373 if (SectionTagExists(SliderSliceName)) { // check if slice exists, and load into SectionTag if it does 374 var Slider = SectionTag; 375 if (SectionTagExists(SliderBlogName)) { // check if slice exists, and load into SectionTag if it does 376 var Blog = SectionTag; 377 var BlogArticles = Blog.find('div.blogcomponent_articlediv div.ArticleBody'); 378 if (BlogArticles.length === 0) {SectionTag.hide();return;} 379 var ulGallery = Slider.find('ul.gallery_ul'); 380 var Li = ulGallery.children('li'); 381 // First build the <li> in the gallery 382 var i; 383 for (i = 2; i <= BlogArticles.length; i++) { 384 Li.clone().appendTo(ulGallery); 385 } 386 // Now add all the blog articles as image captions. 387 var Img = ulGallery.find('img'); 388 var S; 389 i = 0; 390 BlogArticles.each(function() { 391 // Add in section.slice_Testimony to pick up some styles. 392 S = '<div class="caption"><section class="slice_Testimony">' + $(this).html() + '</section></div>'; 393 $(S).insertAfter(Img.eq(i)); 394 i++; 395 }); 396 397 // Turn into a slider 398 var BxOptions = { 399 mode: 'fade',
400 auto: false, 401 pause: 5000, 402 speed: 500, 403 pager: true, 404 controls: true, 405 preloadImages: 'visible', // all images are the same. 406 touchEnabled: false, 407 adaptiveHeight: false // all images are the same. 408 }; 409 Slider.find('div.bannerSlides').show(0); 410 ulGallery.bxSlider(BxOptions); 411 } 412 } 413} 414 415function ActivateLandingArticles(SliceName) { 416 /* this code does an intelligent layout change for a article list, depending on the number of articles */ 417 if (SectionTagExists(SliceName)) { // check if slice exists, and load into SectionTag if it does 418 var rMarginWidth = 1.28866 * 2.0, rCleverWidth; 419 var Articles = SectionTag.find('div.article_cards > div'); 420 var iArticles = Articles.length; 421 switch(iArticles) { 422 case 1: 423 rCleverWidth = 100.0 - rMarginWidth; break; 424 case 2: 425 rCleverWidth = 50.0 - rMarginWidth; break; 426 case 3: case 5: case 6: case 9: 427 rCleverWidth = 33.33333 - rMarginWidth; break; 428 case 4: case 7: case 8: case 10: case 11: case 12: 429 rCleverWidth = 25.0 - rMarginWidth; break; 430 //case 5: 431 //rCleverWidth = 20.0 - rMarginWidth; break; 432 default: 433 rCleverWidth = 25.0 - rMarginWidth; break; 434 } 435 Articles.css('width', rCleverWidth + '%'); 436 } 437} 438 439 function ActivateLandingList(SliceName) { 440 if (SectionTagExists(SliceName)) { // check if slice exists, and load into SectionTag if it does 441 442 // Create the links at the bottom of the article cards. 443 SectionTag.find('div.articleListTitle a').each(function () { 444 var ThisAtag = $(this); 445 var titleLink = ThisAtag.attr("href"); 446 var articleListLink = ThisAtag.parent().parent().children('.articleListLink'); 447 articleListLink.wrapInner('<a href="' + titleLink + '">'); 448 }); 449 } 450} 451 452 function ActivateRedBanner(SliceName) { 453 if (SectionTagExists(SliceName)) { // check if slice exists, and load into SectionTag if it does 454 if(SectionTag.find('div.ArticleBody').length > 0){SectionTag.removeClass('HideElement');} 455 } 456 } 457 458// ########################## Check various conditions ############################# 459 460var bOnTouchDevice = ('ontouchstart' in window) || (navigator.maxTouchPoints > 0) || (navigator.msMaxTouchPoints > 0); 461var iDeskTopWidth = 992; 462var iMobileScreenAllowence = 64; // Because of other stuff on a screen, you have to assume the browser window could get bigger on a rotation. 463var bDesktopScreenPossible = ((screen.width + iMobileScreenAllowence) >= iDeskTopWidth || (screen.height + iMobileScreenAllowence) >= iDeskTopWidth); 464 465var BodyTag = $('body'); 466var bOnSystemPopupPage = BodyTag.hasClass('system_popup') || (window.location.href.toLowerCase().indexOf('popup=yes') !== -1); 467var bUserLoggedIn = BodyTag.hasClass('logged_in_user'); 468 469SectionTags = BodyTag.find('section'); // Store all the section tags to speed up later code. 470var bOnContentPage = SectionTags.hasClass('slice_content_page'); 471var bOnSystemPage = SectionTags.hasClass('slice_system_page'); 472var bOnHomePage = SectionTags.hasClass('slice_SlidesFullWidth'); 473var bOnLandingPage = SectionTags.hasClass('slice_LandingArticles'); 474 475ActivateBannerImage('slice_BannerImage'); 476 477// Activate the slide shows first as they are usually near the top of the visible screen. 478if (bOnHomePage) { 479 480 // ############################################################## 481 // # js for Slide Shows slices. We use BX-slider V4.2.5 482 // ############################################################## 483 484 // The slide-shows are hidden via CSS when the page first loads, to give a smoother page-load experience. 485 // All slide-show CI modules must have a class "bannerSlides" defined within them. 486 487 // Activate all the slide-shows. Do in sensible order, so any visible ones are done first. 488 ActivateBxSlider('slice_SlidesFullWidth'); 489 ActivateRedBanner('RedBanner'); 490} 491 492// ####################################### 493// # Menu data changes 494// ####################################### 495 496// We make the required adjustments to the one set of menu HTML on the page, before cloning it and activating all the copies. 497 498var ulModuleRootMenu = BodyTag.find('ul.root_menu'); 499var bMenuPresent = (ulModuleRootMenu.length !== 0); 500if (bMenuPresent) { 501 502 /* remove sub menus from Home */ 503 // This assumes that the home menu is the first item with a sub menu. 504 var HomeMenuLi = ulModuleRootMenu.children('li:first-child'); 505 HomeMenuLi.children('ul').remove(); 506 HomeMenuLi.removeClass('has_sub_menu'); // remove class 507 508 // Set up the search icon in the search box. 509 var DeskTopSearchBox = BodyTag.find('header div.top-link-wrapper div.search-form'); 510 $('<i class="journey-icon-search"></i>
510').appendTo(DeskTopSearchBox); 511 var HiddenSearchBox = DeskTopSearchBox.find('input.button'); 512 DeskTopSearchBox.find('i').click(function(){HiddenSearchBox.click();}); // set up the click. 513 514 if (bUserLoggedIn) { 515 //ulModuleRootMenu.children('li:last-child').children('ul').remove(); // delete submenus of Myarea. 516 BodyTag.find('header div.top-link-wrapper a.Login').attr('href','/user/logout.aspx').text('LOGOUT'); 517 BodyTag.find('header div.top-link-wrapper a.Bookings').attr('href','/admin').text('WEB OFFICE'); 518 } 519 520 // remove copies of 1st item elements in dropdown sub-menu. 521 ulModuleRootMenu.find('li.menu_item_level_2:first-child').each(function() { 522 523 var ThisLi = $(this); 524 if(ThisLi.children("a[href^='/MyArea/']").length === 0) { // only if not a link into /MyArea/... 525 526 if(ThisLi.siblings().length === 0) { // no other <li> so it is the only entry 527 var ul = ThisLi.parent(); 528 ul.parent().removeClass('has_sub_menu'); // remove class from the <li> at the level above 529 ul.remove(); // delete whole parent <ul> 530 531 } else { 532 if (bOnTouchDevice && bDesktopScreenPossible) { 533 // On a touch device, the copies of the level one links at the 2nd level have to be kept for the desktop menus. 534 // But in the SlickNav menus, these 2nd level links are not needed. 535 // So we mark the items so we can delete them later, after data is copied into the SlickNav menu. 536 ThisLi.addClass('SlickNavNotNeeded'); // Mark the 2nd level <li> tag. 537 } else { 538 // Not on a touch screen, so Desktop and SlickNav menus will be the structurally the same. 539 ThisLi.remove(); // so just remove this <li> tag 540 } 541 } 542 } 543 }); 544 545 // Make sure the online bible goes to a fresh tab/page. 546 ulModuleRootMenu.find('a[href$="/Online_Bible.aspx"]').attr("target","_blank"); 547 548 // ####################################### 549 // # SlickNav menus V1.0.10 550 // ####################################### 551 552 ActivateMenu('slice_Header_L'); 553 554 // ######## Footer Slice code #################### 555 556 // If there is a header, then there is probably a footer. 557 // This is the footer top. There is no need to clone this HTML. 558 559 ActivateFooter("slice_FooterTop_L"); 560 561} // end of if bNeedMenus 562 563// Here do things ONLY needed on a home page. 564if (bOnHomePage) { 565 566 // Article list - 4 in a row on desktop 567 ActivateArticleList4('slice_WelcomeArticles'); 568 569 // image blocks 570 ActivateBlockImages('slice_image_blocks_4'); 571 572 // Article slider 573 BuildArticleSlider('slice_WhatPeopleSay','slice_HiddenWhatPeopleSayBlog'); 574 575} else if (bOnContentPage) { 576 577 // code to try and make content images work on mobile phones. Set max-width css property is if has not already been set. 578 // If width and height attributes are both set, then the image is compressed horizontally, but that is still better than it overflowing. 579 var ContentImages = BodyTag.find('section.slice_content_page div.ArticleBody img'); 580 ContentImages.each(function() { 581 var Img = $(this); 582 if (Img.css('max-width') === 'none') { 583 Img.css('max-width','100%'); 584 } 585 }); 586 587} else if (bOnLandingPage) { 588 589 ActivateLandingList('slice_LandingArticles'); 590 ActivateLandingArticles('slice_LandingArticles'); 591 592} else if (bOnSystemPage || bOnSystemPopupPage) { 593 594 // work out what kind of page we are on. 595 var PageType = window.location.pathname.toLowerCase(); 596 if (PageType.endsWith(".aspx")) { 597 PageType = PageType.substring(0, PageType.indexOf(".aspx")); 598 PageType = PageType.replace(/\//g, "_"); // replace all / to _ Have to use \/ to get a / in the reg-ex. The g denotes a global exchange. 599 PageType = PageType + "_aspx"; 600 } else if (PageType.indexOf(".html") === (PageType.length - 5)) { 601 // Assume we are on a local machine. 602 PageType = '_user_registration_aspx'; 603 } 604 //alert(PageType); 605 606 /* Possible page types are now: 607 '_calendar_month_aspx' 608 '_media_allmedia_aspx' 609 '_user_registration_aspx' 610 '_user_copyright_aspx' 611 '_user_termsandconditions_aspx' 612 '_user_privacypolicy_aspx' 613 '_user_help_aspx' 614 '_publisher_search_aspx' - this is search results. 615 '_paymentgroup_registration_aspx' 616 '_myarea_walletitem_aspx' 617 */ 618 619 if (SectionTagExists("slice_system_page")) { // check if slice exists, and load into SectionTag if it does 620 SystemSlice = SectionTag; 621 SystemSlice.addClass(PageType); // add class onto <section> tag, so CSS can locate it. 622 } else { 623 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. 624 BodyTag.addClass('system_popup'); // add this in case it is not on. 625 } 626 627 if (PageType === '_media_allmedia_aspx' || PageType === '_publisher_search_aspx') { 628 629 // Add a toggle for the media controls.
630 var MediaControls = SystemSlice.find('div#media_controls'); // these media controls are on the search page too. 631 if (MediaControls.length !== 0) { 632 $('<a class="system_toggle_advanced">Advanced Options</a>').insertBefore(MediaControls); 633 ApplyToggleVisibilityOnClick(SystemSlice, "a.system_toggle_advanced", MediaControls, 0, false); 634 } 635 636 HideDivsIfAllEmpty('media_summary_image'); // Hide some empty columns, if needed. 637 638 if (PageType === '_publisher_search_aspx') { // Extra things to do on the search page. 639 640 HideDivsIfAllEmpty('search_article_image'); // Hide some empty columns, if needed. 641 HideDivsIfAllEmpty('search_event_image'); // Hide some empty columns, if needed. 642 643 // If we have been sent to the search page explicitly then prepare the page for searching. 644 var SearchBox = SystemSlice.find('input[id$="_txtSearchStringTemplate"]'); 645 if (SearchBox.length === 1) { 646 if (SearchBox.val() === 'Activate_Search') { 647 SystemSlice.find('h2').hide(); // hide the search result titles 648 SearchBox.val(''); // Clear the search text box 649 SearchBox.attr('placeholder','Type your search text here'); 650 SearchBox.attr("autocomplete","off"); 651 MediaControls.show(); // make the search controls show. 652 } 653 } 654 655 // If no data is found then, print a message, rather than have a blank page. 656 if (SystemSlice.find('div.system_section').length === 0) { 657 var HTML = '<span>No data found.<br><br>Please use the advanced options to refine your search.</span>'; 658 $(HTML).appendTo(SystemSlice.find('div.system_body')); 659 MediaControls.show(); // make the search controls show. 660 } 661 } 662 } 663 664 // Fix calendar mobile page. Add a class to days we want to hide on the mobile/list view. 665 if (PageType === '_calendar_month_aspx') { 666 var DivToday = SystemSlice.find('div.calendar_day_wrapper_today'); 667 if (DivToday.length !== 0) { // we are on a calendar page with today's date. 668 var NoEvents = SystemSlice.find('div#calendar_no_events'); 669 if (NoEvents.length === 0) { // only bother if there are some events. 670 DivToday.prevAll().addClass('CalendarHideOnListView'); // so we can hide days earlier in the current week. 671 var DivThisWeek = DivToday.parent(); 672 DivThisWeek.prevAll().addClass('CalendarHideOnListView'); // so we can hide earlier weeks. 673 // If no events are visible, then tell the user. 674 var AllDaysInVisibleWeeks = SystemSlice.find('div.calendar_week:not(".CalendarHideOnListView") div.calendar_day_wrapper'); 675 var iDaysVisible = AllDaysInVisibleWeeks.not('.calendar_day_wrapper_empty').not('.CalendarHideOnListView').length; 676 if (iDaysVisible === 0) { 677 $('<div id="calendar_no_events">There are no events in the selected month.</div>').insertAfter(SystemSlice.find('div.calendar')); 678 } 679 } 680 } 681 } 682 683} // end of bOnHomePage or bOnSystemPage if-block 684 685// Corrections for various hardware/browsers 686var P = navigator.platform; 687var bSmallAppleDevice = (P === 'iPhone' || P === 'iPad' || P === 'iPod'); 688//var bAppleDevice = (P === 'MacIntel' || bSmallAppleDevice); 689 690var UA = navigator.userAgent; 691// See https://developer.mozilla.org/en-US/docs/Web/HTTP/Browser_detection_using_the_user_agent for details. 692var bOnSafari = (UA.indexOf('Safari/') !== -1 && UA.indexOf('Chrome/') === -1 && UA.indexOf('Chromium/') === -1); 693 694//alert(P + ' # ' + UA); // DEBUGGING line. 695 696if (bOnSafari) { 697 // Fix the twitter feed on Safari. Need to replace height:100% with a fixed height, to prevent a near infinite scroll. 698 // We can't just add a class on the <iframe>, as it is created dynamically by Twitter js. 699 // So instead we add a class on the wrapper div, just before where the iframe will appear. 700 SectionTags.find('div.WhatsOnTwitter').addClass('OnAppleDevice'); 701} 702if (bSmallAppleDevice) { 703 // Parallex images are often a mess on small apple devices, so add a tag onto the <body> tag so we can take evasive action. 704 BodyTag.addClass('OnSmallAppleDevice'); 705} 706 707// Warnings. 708var iNumSwitchFastParallexOnSlices = SectionTags.filter('.SwitchFastParallexOn').length; 709if (iNumSwitchFastParallexOnSlices > 1) { 710 alert('WARNING: Theme has ' + iNumSwitchFastParallexOnSlices + ' SwitchFastParallexOn slices.'); 711} 712 713// Code to make sure anchor links do not dissappear behind a fixed header (used on Quainton School). 714if (bOnContentPage) { 715 var iHeaderHeight = 0; 716 if (SectionTagExists('slice_Header_L')) { 717 var CssPosition = SectionTag.css('position'); 718 if (CssPosition === 'fixed'){ // only do if we have a fixed header. 719 iHeaderHeight = SectionTag.outerHeight(true); 720 } 721 } 722 if (iHeaderHeight > 0 && SectionTagExists('slice_content_page')) { 723 var HashLinks = SectionTag.find('a:not([href="#"])[href^="#"]'); 724 HashLinks.click(function(){ 725 window.setTimeout(function(){window.scrollBy(0, -iHeaderHeight);}, 500); // wait 500ms, then scroll down, so link is not under the header. 726 }); 727 } 728} 729 730// Sort out login/logout/register/web-office links 731var SB = BodyTag.find('div.HiddenStatusBar'); 732if (SB.length === 1) { 733 if (bUserLoggedIn) { 734 var bWebOfficeActive = (SB.find('a.weboffice_link').length === 1); 735 if (!bWebOfficeActive) { // Need to hide WO links. 736 BodyTag.find('header a[href="/admin"]').hide(); 737 BodyTag.find('header a[href="/Admin/Default.aspx"]').hide(); 738 BodyTag.find('section.slice_FixedSideLinks a[href="/admin"]').hide(); 739 } 740 } else { 741 var SBRL = SB.find('a.register_link'); 742 if (SBRL.length === 0) { // Need to hide the register links. Need TWO versions for case changes. 743 BodyTag.find('header a[href="/User/Registration.aspx"]').hide(); 744 BodyTag.find('header a[href="/user/registration.aspx"]').hide(); 745 BodyTag.find('section.slice_FixedSideLinks a[href="/User/Registration.aspx"]').hide(); 746 BodyTag.find('section.slice_FixedSideLinks a[href="/user/registration.aspx"]').hide(); 747 } else { 748 var RegLink = SBRL.attr('href'); 749 if (RegLink !== "/User/Registration.aspx") { 750 BodyTag.find('header a[href="/User/Registration.aspx"]').attr('href',RegLink); 751 BodyTag.find('header a[href="/user/registration.aspx"]').attr('href',RegLink); 752 BodyTag.find('section.slice_FixedSideLinks a[href="/User/Registration.aspx"]').attr('href',RegLink); 753 BodyTag.find('section.slice_FixedSideLinks a[href="/user/registration.aspx"]').attr('href',RegLink); 754 } 755 } 756 } 757} 758 759});
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.