1function setCookie(cname, cvalue, exdays) { 2 var d = new Date(); 3 d.setTime(d.getTime() + (exdays * 24 * 60 * 60 * 1000)); 4 var expires = "expires=" + d.toUTCString(); 5 document.cookie = cname + "=" + cvalue + ";" + expires + ";path=/"; 6} 7function getCookie(cname) { 8 var name = cname + "="; 9 var decodedCookie = decodeURIComponent(document.cookie); 10 var ca = decodedCookie.split(';'); 11 for (var i = 0; i < ca.length; i++) { 12 var c = ca[i]; 13 while (c.charAt(0) == ' ') { 14 c = c.substring(1); 15 } 16 if (c.indexOf(name) == 0) { 17 return c.substring(name.length, c.length); 18 } 19 } 20 return ""; 21} 22 23 24 25 26$(document).ready(function () { 27 28 //Replace Stats 29 $(".stat-number").each(function (i) { 30 31 var text = $(this).text(); 32 // wrap characters ["+", "%", "-", "=", "#", "*", "$", "£"] in <sup><span></span></sup> 33 var newText = text.replace(/([\+\%\-\=\#\*\$\£])/g, "<span><sup>$1</sup></span>"); 34 35 // wrap character ["."] in <span></span> 36 newText = newText.replace(/(\.)/g, "<span>$1</span>"); 37 $(this).html(newText); 38 39 }); 40 41 42 43 $('.hero-slider > div').slick({ 44 dots: true, 45 arrows: false, 46 infinite: true, 47 speed: 800, 48 cssEase: 'cubic-bezier(.72,.38,.46,.96)', 49 autoplay: true, 50 autoplaySpeed: 6000, 51 pauseOnHover: false, 52 draggable: false, 53 responsive: [ 54 { 55 breakpoint: 1025, 56 settings: { 57 autoplay: false, 58 draggable: true 59 } 60 } 61 // You can unslick at a given breakpoint now by adding: 62 // settings: "unslick" 63 // instead of a settings object 64 ] 65 }); 66 67 $('.dropdown-submenu').on("click", function (e) { 68 $('.dropdown-submenu + ul').hide(); 69 $(this).attr('aria-expanded', function (i, attr) { 70 return attr == 'true' ? 'false' : 'true' 71 }); 72 $(this).next('ul').toggle(); 73 e.stopPropagation(); 74 e.preventDefault(); 75 }); 76 $('body').on("click", function (e) { 77 $('.dropdown-submenu').attr('aria-expanded', false); 78 $('.dropdown-submenu').next('ul').css('display', 'none'); 79 }); 80 81 function loadComparison(id, before, after) { 82 slider = new juxtapose.JXSlider('#' + id, 83 [ 84 { 85 src: before 86 }, 87 { 88 src: after 89 } 90 ], 91 { 92 animate: true, 93 showLabels: false, 94 showCredits: false, 95 startingPosition: "50%", 96 makeResponsive: true 97 }); 98 } 99 100 101 102 // Load Comparison 103 104 105 $(".image-comparison").each(function (i) { 106 var image1 = $(this).find("img").eq(0).attr("src"), 107 image2 = $(this).find("img").eq(1).attr("src"); 108 $(this).attr("id", "JXSlider" + i) 109 console.log(image1, image2); 110 loadComparison("JXSlider" + i, image1, image2); 111 $(this).find("img").remove(); 112 }); 113 114 115 116 // Search 117 const urlParams = new URLSearchParams(window.location.search); 118 const searchText = urlParams.get('searchtext'); 119 if (searchText != null && searchText != "") { 120 $(".search-text").val(searchText); 121 $(".search-term").text(searchText); 122 $(".search-term-container").show(); 123 } 124 else { 125 $(".search-term-container").hide(); 126 } 127 //console.log(searchText); 128 $(".search-text").on('keyup', function (e) { 129 if (e.key === 'Enter' || e.keyCode === 13) { 130 window.location.href = "/search?searchtext=" + this.value; 131 } 132 }); 133 $(".search-btn").on('click', function (e) { 134 if ($(this).closest(".search-form").length) { 135 window.location.href = "/search?searchtext=" + $(this).closest(".search-form").find(".search-text").val(); 136 } 137 if ($(this).closest(".search-form-modal").length) { 138 window.location.href = "/search?searchtext=" + $(this).closest(".search-form-modal").find(".search-text").val(); 139 } 140 });
141 142 143 /* Hero Animated Text */ 144 $(".two-col-hero .hero-text-col .hero-heading-box h1 span").addClass("animated"); 145 $(".two-col-hero .hero-text-col .hero-heading-box .btn").addClass("animated"); 146 ///////////////////////////// 147 148 if ($(".rellax").length) { 149 var rellax = new Rellax('.rellax'); 150 } 151 if ($(".subnav ul > li.active").length) { 152 var subnavactive = $(".subnav ul > li.active"); 153 var position = subnavactive.position(); 154 $(".subnav ul").scrollLeft(position.left - 50); 155 } 156 157 $('.center').slick({ 158 centerMode: true, 159 centerPadding: '60px', 160 slidesToShow: 1, 161 responsive: [ 162 { 163 breakpoint: 768, 164 settings: { 165 arrows: false, 166 centerMode: true, 167 centerPadding: '40px', 168 slidesToShow: 3 169 } 170 }, 171 { 172 breakpoint: 480, 173 settings: { 174 arrows: false, 175 centerMode: true, 176 centerPadding: '40px', 177 slidesToShow: 1 178 } 179 } 180 ] 181 }); 182 183 //Cookie Banner Check 184 var AllowCookies = getCookie("AllowCookies"); 185 if (AllowCookies == "") { 186 $("#cookiebanner").addClass('active'); 187 } 188 189 // Cookie Banner close 190 $("#cookiebanner .close").click(function (e) { 191 e.preventDefault(); 192 $(this).parent().parent().removeClass('active'); 193 setCookie("AllowCookies", "true", 365); 194 }); 195 196 // Ajax News load 197 198 if ($('#load-news').length) { 199 200 var preloadedNewsData = null; 201 202 // Preload news feed when the page loads 203 $(document).ready(function () { 204 $.get("/news-feed", function (data) { 205 preloadedNewsData = data; 206 }); 207 }); 208 209 $('#load-news').click(function (e) { 210 e.preventDefault(); 211 212 function processNewsData(data) { 213 var $html = $(data); 214 var $newsContainer = $("section.news-latest .container-fluid .news-articles-container"); 215 var count = 0; 216 217 // Loop through each news item in the returned HTML 218 $html.find("div[class^='col']").each(function () { 219 if (count >= 9) return false; // Stop after adding 9 items 220 221 var $newsItem = $(this), 222 id = $newsItem.data("id"); 223 224 // Add only if the item does not already exist 225 if ($newsContainer.find("[data-id='" + id + "']").length === 0) { 226 $newsContainer.append($newsItem); 227 count++; 228 } 229 }); 230 231 // Hide button if all items are loaded 232 setTimeout(function () { 233 var totalItems = $newsContainer.children("div[class^='col']").length; 234 var feedItemCount = $html.find("div[class^='col']").length; 235 if (totalItems === feedItemCount) { 236 $('#load-news').closest(".row").hide(); 237 } 238 }, 100); 239 } 240 241 if (preloadedNewsData) { 242 // If preloaded data is ready, use it 243 processNewsData(preloadedNewsData); 244 preloadedNewsData = null; // Prevent reuse, ensuring fresh content next time 245 } else { 246 // Otherwise, fetch it normally 247 $.get("/news-feed", function (data) { 248 processNewsData(data); 249 }); 250 } 251 }); 252 253} 254 255 256 257 // Ajax Photo load 258 var photoPage = 2; 259 $('#load-photos').click(function (e) { 260 e.preventDefault(); 261 // Hit the news feed page with the pager QS 262 $.get("/system/photo-feed/?page=" + photoPage, function (data) { 263 var $html = $(data).find('section.news-latest'); 264 var $row = $(".items .row"); 265 //Loop round each news item in the returned HTML 266 var $item = $html.find(".row > div[class^='col']"); 267 console.log("incoming " + $item.length); 268 $item.each(function (index) { 269 var $photoItem = $(this), 270 id = $photoItem.data("id"); 271 console.log(id); 272 // Check to see if the id of the incoming doc already exists on the page 273 console.log($("section.news-latest .container-fluid .items [data-id='+id+']").length) 274 if ($("section.news-latest .container-fluid .items [data-id='" + id + "']").length < 1) { 275 //Append item to the row 276 $row.append($photoItem); 277 } 278 else { 279 //Hide load button if there is nothing left to load 280 $('#load-photos').parents(".row").hide(); 281 } 282 283 }); 284 console.log("hey " + $item.length); 285 if ($item.length < 9) { 286 console.log("hey if " + $item.length); 287 $('#load-photos').parents(".row").hide(); 288 } 289 /* //Insert row onto the page 290 $("section.news-latest .container-fluid .items").append($row);*/ 291 292 console.log("items - " + $(".items .row > div[class^='col']").length); 293 setTimeout(function () { 294 if ($(".items .row > div[class^='col']").length == $("section.news-latest").attr("data-itemcount")) { 295 $('#load-photos').closest(".row").hide(); 296 } 297 }, 100); 298 }) 299 photoPage++; 300 301 if ($(".items .row > div[class^='col']").length == $("section.news-latest").attr("data-itemcount")) { 302 $('#load-photos').parents(".row").hide(); 303 } 304 });
305 306 307 /* 308 309 // Cache selectors 310 var lastId, 311 topMenu = $(".subnav"), 312 topMenuHeight = topMenu.outerHeight()+1, 313 // All list items 314 menuItems = topMenu.find("a"), 315 // Anchors corresponding to menu items 316 scrollItems = menuItems.map(function(){ 317 var item = $($(this).attr("href")); 318 if (item.length) { return item; } 319 }); 320 321 322 323 324 // Bind click handler to menu items 325 // so we can get a fancy scroll animation 326 menuItems.click(function(e){ 327 var href = $(this).attr("href"), 328 offsetTop = href === "#" ? 0 : $(href).offset().top-topMenuHeight+1; 329 $('html, body').stop().animate({ 330 scrollTop: offsetTop 331 }, 850); 332 e.preventDefault(); 333 }); 334 335 // Bind to scroll 336 $(window).scroll(function(){ 337 // Get container scroll position 338 var fromTop = $(this).scrollTop()+topMenuHeight; 339 340 // Get id of current scroll item 341 var cur = scrollItems.map(function(){ 342 if ($(this).offset().top < fromTop) 343 return this; 344 }); 345 // Get the id of the current element 346 cur = cur[cur.length-1]; 347 var id = cur && cur.length ? cur[0].id : ""; 348 349 if (lastId !== id) { 350 lastId = id; 351 // Set/remove active class 352 menuItems 353 .parent().removeClass("active") 354 .end().filter("[href=#"+id+"]").parent().addClass("active"); 355 } 356 }); 357 358 */ 359 360}); 361 362function validateDecimalPlaces(e) { 363var t = e.value; 364e.value = (t.indexOf(".") >= 0) ? (t.substr(0, t.indexOf(".")) + t.substr(t.indexOf("."), 3)) : t; 365} 366 367function isIE() { 368 return window.navigator.userAgent.match(/(MSIE|Trident)/); 369} 370 371//foreach polyfill 372if (window.NodeList && !NodeList.prototype.forEach) { 373 NodeList.prototype.forEach = Array.prototype.forEach; 374} 375if (window.HTMLCollection && !HTMLCollection.prototype.forEach) { 376 HTMLCollection.prototype.forEach = Array.prototype.forEach; 377} 378 379if (!Element.prototype.matches) { 380 Element.prototype.matches = 381 Element.prototype.msMatchesSelector || 382 Element.prototype.webkitMatchesSelector; 383} 384 385//closest polyfill 386if (!Element.prototype.closest) { 387 Element.prototype.closest = function (s) { 388 var el = this; 389 390 do { 391 if (Element.prototype.matches.call(el, s)) return el; 392 el = el.parentElement || el.parentNode; 393 } while (el !== null && el.nodeType === 1); 394 return null; 395 }; 396} 397 398//Array from polyfill 399if (!Array.from) { 400 Array.from = (function () { 401 var toStr = Object.prototype.toString; 402 var isCallable = function (fn) { 403 return typeof fn === 'function' || toStr.call(fn) === '[object Function]'; 404 }; 405 var toInteger = function (value) { 406 var number = Number(value); 407 if (isNaN(number)) { return 0; } 408 if (number === 0 || !isFinite(number)) { return number; } 409 return (number > 0 ? 1 : -1) * Math.floor(Math.abs(number)); 410 }; 411 var maxSafeInteger = Math.pow(2, 53) - 1; 412 var toLength = function (value) { 413 var len = toInteger(value); 414 return Math.min(Math.max(len, 0), maxSafeInteger); 415 }; 416 417 // The length property of the from method is 1. 418 return function from(arrayLike/*, mapFn, thisArg */) { 419 // 1. Let C be the this value. 420 var C = this; 421 422 // 2. Let items be ToObject(arrayLike). 423 var items = Object(arrayLike); 424 425 // 3. ReturnIfAbrupt(items). 426 if (arrayLike == null) { 427 throw new TypeError("Array.from requires an array-like object - not null or undefined"); 428 } 429 430 // 4. If mapfn is undefined, then let mapping be false. 431 var mapFn = arguments.length > 1 ? arguments[1] : void undefined; 432 var T; 433 if (typeof mapFn !== 'undefined') { 434 // 5. else 435 // 5. a If IsCallable(mapfn) is false, throw a TypeError exception. 436 if (!isCallable(mapFn)) { 437 throw new TypeError('Array.from: when provided, the second argument must be a function'); 438 } 439 440 // 5. b. If thisArg was supplied, let T be thisArg; else let T be undefined. 441 if (arguments.length > 2) { 442 T = arguments[2]; 443 } 444 } 445 446 // 10. Let lenValue be Get(items, "length"). 447 // 11. Let len be ToLength(lenValue). 448 var len = toLength(items.length); 449 450 // 13. If IsConstructor(C) is true, then 451 // 13. a. Let A be the result of calling the [[Construct]] internal method of C with an argument list containing the single item len. 452 // 14. a. Else, Let A be ArrayCreate(len). 453 var A = isCallable(C) ? Object(new C(len)) : new Array(len); 454 455 // 16. Let k be 0. 456 var k = 0; 457 // 17. Repeat, while k < len� (also steps a - h) 458 var kValue; 459 while (k < len) { 460 kValue = items[k]; 461 if (mapFn) { 462 A[k] = typeof T === 'undefined' ? mapFn(kValue, k) : mapFn.call(T, kValue, k); 463 } else { 464 A[k] = kValue; 465 } 466 k += 1; 467 } 468 // 18. Let putStatus be Put(A, "length", len, true). 469 A.length = len; 470 // 20. Return A. 471 return A; 472 }; 473 }()); 474} 475 476//Array find polyfill 477if (!Array.prototype.find) { 478 Array.prototype.find = function (predicate) { 479 if (this == null) { 480 throw new TypeError('Array.prototype.find called on null or undefined'); 481 } 482 if (typeof predicate !== 'function') { 483 throw new TypeError('predicate must be a function'); 484 } 485 var list = Object(this); 486 var length = list.length >>> 0; 487 var thisArg = arguments[1]; 488 var value; 489 490 for (var i = 0; i < length; i++) { 491 value = list[i]; 492 if (predicate.call(thisArg, value, i, list)) { 493 return value; 494 } 495 } 496 return undefined; 497 }; 498} 499 500 501 502 503// YouTube video loader
504function loadPosterImage() { 505 // Get all of the videos 506 let videos = document.querySelectorAll('[data-youtube]:not([data-done])'); 507 508 // Progressively enhance them 509 for (let video of videos) { 510 511 // Get the video ID 512 let id = new URL(video.href).searchParams.get('v'); 513 514 // Add the ID to the data-youtube attribute 515 video.setAttribute('data-youtube', id); 516 517 // Add a role of button 518 video.setAttribute('role', 'button'); 519 520 const videoTitle = video.querySelector(".video-title").textContent; 521 522 // Check for img. If no image then render fallback YouTube thumbnail 523 const hasImg = video.querySelector(".vid-thumbnail"); 524 525 if (!hasImg) { 526 video.innerHTML = 527 `<img alt="${videoTitle}" src="https://img.youtube.com/vi/${id}/hqdefault.jpg" loading="lazy" data-ot-ignore> 528<span class="sr-only video-title"> 529${videoTitle} 530</span>`; 531 } 532 533 // Mark as done 534 video.setAttribute('data-done', ''); 535 536 } 537} 538document.addEventListener('DOMContentLoaded', function () { 539 loadPosterImage(); 540 541 /** 542 * Handle click events on the video thumbnails 543 * param {Event} event The event object 544 */ 545 function videoClickHandler(event) { 546 547 // Get the video link 548 let link = event.target.closest('[data-youtube]'); 549 if (!link) return; 550 551 // Prevent the URL from redirecting users 552 event.preventDefault(); 553 554 // Get the video ID 555 let id = link.getAttribute('data-youtube'); 556 557 const videoTitle = link.querySelector(".video-title").textContent; 558 559 // Create the player 560 let player = document.createElement('div'); 561 player.innerHTML = `<iframe src="https://www.youtube-nocookie.com/embed/${id}?autoplay=1&rel=0&modestbranding=1" title="${videoTitle}" frameborder="0" allow="accelerometer; autoplay; clipboard-write; encrypted-media; gyroscope; picture-in-picture" allowfullscreen></iframe>`; 562 563 // Inject the player into the UI 564 link.replaceWith(player); 565 566 } 567 // Detect clicks on the video thumbnails 568 document.addEventListener('click', videoClickHandler); 569 570})
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.