PageSourceSearch

https://coulsdon.ac.uk/wp-content/themes/C4/C4/js/script.js?v2

js coulsdon.ac.uk collected 2026-09-24 21:40:20 UTC 9,862 bytes, 351 lines download raw bytes

1// --- Header toggle on scroll ---
2  function toggleHeader() {
3    if (window.scrollY > 100) {
4      document.body.classList.add("fixedHeader");
5    } else {
6      document.body.classList.remove("fixedHeader");
7    }
8  }
9
10window.addEventListener("scroll", toggleHeader, { passive: true });
11document.addEventListener("DOMContentLoaded", () => {
12  // Run once on load
13  toggleHeader();
14});
15
16
17
18
19$(function () {
20  $('header#masthead .top_bar nav#headerMenu ul li > button')
21    .on('click', function (e) {
22      e.preventDefault(); // optional, if the button shouldn't submit anything
23
24      $(this)
25        .closest('li')
26        .toggleClass('open');
27    });
28});
29
30
31
32
33// Function for audience menu smaller screens carousel
34$(function () {
35    
36    
37    
38    const $owl_audience = $('#audienceMenu .audience-carousel.owl-carousel');
39
40    // safety: ensure plugin is loaded
41    if (!$owl_audience.owlCarousel) {
42    console.error('OwlCarousel plugin not found');
43    return;
44    }
45    
46    
47    $owl_audience.on('initialized.owl.carousel', function () {
48  
49    $('#audienceMenu .audience-carousel.owl-carousel').css('opacity',1);
50});
51
52
53    $owl_audience.owlCarousel({
54    loop: false,
55    responsiveClass: true,
56    nav: true,
57    margin: 0,
58    dots: false,
59    responsive: {
60        0:   { items: 1}, // (consider 1 for phones)
61        700: { items: 2},
62        1100:{ items: 3 }
63    }
64    });
65});
66
67
68// --- Search open/close (jQuery with overlay fade + click-away) ---
69$(function () {
70  const $body   = $('body');
71  const $search = $('#search');
72  const $input  = $('#search-website'); // adjust if your ID differs
73  let $lastOpener = null;
74
75  // ensure initial state is truly hidden (in case markup forgot it)
76  $search.prop('hidden', true).removeClass('open');
77  $body.removeClass('searchOpen');
78
79  function openSearch() {
80    // make it exist for keyboard/AT
81    $search.prop('hidden', false).addClass('open');
82    $body.addClass('searchOpen');
83
84    // reflect state for AT on the opener
85    if ($lastOpener && $lastOpener.length) {
86      $lastOpener.attr('aria-expanded', 'true');
87    }
88
89    // focus into the search field once visible
90    requestAnimationFrame(() => {
91      if ($input.length) $input.trigger('focus');
92    });
93  }
94
95  function closeSearch() {
96    $search.removeClass('open').prop('hidden', true);
97    $body.removeClass('searchOpen');
98
99    if ($lastOpener && $lastOpener.length) {
100      $lastOpener.attr('aria-expanded', 'false');
101      $lastOpener.trigger('focus');
102    }
103  }
104
105  // Open on button click (Enter on a button triggers click automatically)
106  $(document).on('click', 'button.searchOpener', function (e) {
107    e.preventDefault();
108    $lastOpener = $(this);
109    openSearch();
110  });
111
112  // Close on .close inside #search
113  $(document).on('click', '#search .closeBTN', function (e) {
114    e.preventDefault();
115    closeSearch();
116  });
117
118  // Close with Escape key
119  $(document).on('keydown', function (e) {
120    if (e.key === 'Escape' && $body.hasClass('searchOpen')) {
121      e.preventDefault();
122      closeSearch();
123    }
124  });
125
126  // Close when clicking/tapping outside #search (and not on the opener)
127  $(document).on('mousedown touchstart', function (e) {
128    if (!$body.hasClass('searchOpen')) return; // only when open
129    const $t = $(e.target);
130    if ($t.closest('#search, button.searchOpener').length) return;
131    closeSearch();
132  });
133});
134
135
136
137
138// function for course category listing title
139$(function () {
140  $('.subjects a .title').matchHeight();
141})
142
143
144
145
146// Function for news section carousel
147$(function () {
148    const $owl_news = $('.news .stacked.owl-carousel');
149
150    // safety: ensure plugin is loaded
151    if (!$owl_news.owlCarousel) {
152    console.error('OwlCarousel plugin not found');
153    return;
154    }
155
156    $owl_news.owlCarousel({
157    loop: false,
158    responsiveClass: true,
159    nav: false,
160    margin: 0,
161    dots: false,
162    responsive: {
163        0:   { items: 1, margin: 10, nav: true}, // (consider 1 for phones)
164        768: { items: 2, margin: 20, nav: true},
165        1200:{ items: 2, mouseDrag: false, touchDrag: false, pullDrag: false,margin: 0 }
166    }
167    });
168});
169
170
171
172
173
174// Function for menu sidebar menu
175(function () {
176  function initSidebarAccordion() {
177    var $root = $('#sidebar-region nav');
178    if (!$root.length) return;
179
180    // Add holder buttons to anchors that don't already have one
181    $root
182      .find('ul li.has-sub > a')
183      .filter(function () { return !$(this).children('.holder').length; })
184      .prepend('<button type="button" class="holder" aria-label="Click or spacebar to open sub menu" aria-expanded="false"></button>');
185
186    // Click handler (event delegation so it works even if items are added later)
187    $root.on('click', 'li.has-sub .holder', function (event) {
188      event.preventDefault();
189      event.stopPropagation();
190
191      var $btn = $(this);
192      var $element = $btn.closest('li');
193
194      if ($element.hasClass('open')) {
195        // close current
196        $element.removeClass('open');
197        $btn.attr('aria-expanded', 'false');
198        $element.find('li').removeClass('open').find('.holder').attr('aria-expanded', 'false');
199        $element.find('ul').stop(true, true).slideUp();
200      } else {
201        // open current
202        $element.addClass('open');
203        $btn.attr('aria-expanded', 'true');
204        $element.children('ul').stop(true, true).slideDown();
205
206        // close siblings
207        var $siblings = $element.siblings('li');
208        $siblings.removeClass('open')
209          .find('.holder').attr('aria-expanded', 'false');
210        $siblings.children('ul').stop(true, true).slideUp();
211        $siblings.find('li').removeClass('open').end().find('ul').slideUp();
212      }
213    });
214  }
215
216  // Run now if DOM is ready; otherwise, wait for DOMContentLoaded
217  if (document.readyState === 'loading') {
218    document.addEventListener('DOMContentLoaded', initSidebarAccordion, { once: true });
219  } else {
220    initSidebarAccordion();
221  }
222})();
223
224
225
226// Expose as a global so you can call it whenever.
227window.setupSidebarSectionMenu = function setupSidebarSectionMenu() {
228  var $ = window.jQuery;
229  if (!$) { console.error('jQuery not found'); return false; }
230
231  var $container = $('#sidebar-region');
232  if (!$container.length) { return false; }
233
234  // Remove old handlers to avoid duplicates when called multiple times
235  $container.off('click.sectionMenu', 'button.sidebarMenu');
236
237  // Delegate so elements can exist before or after this runs
238  $container.on('click.sectionMenu', 'button.sidebarMenu', function (e) {
239    e.preventDefault();
240    var $nav  = $container.find('#sidebar-navigation');
241    var $btns = $container.find('button.sidebarMenu');
242
243    $nav.stop(true, true).slideToggle(200);
244    $btns.toggleClass('sectionMenuOpen');
245
246    var isOpen = $btns.first().hasClass('sectionMenuOpen');
247    $btns.attr('aria-expanded', String(isOpen));
248  });
249
250  // Sync initial ARIA once (optional)
251  var $nav0 = $container.find('#sidebar-navigation');
252  var $btn0 = $container.find('button.sidebarMenu');
253  if ($nav0.length && $btn0.length) $btn0.attr('aria-expanded', $nav0.is(':visible'));
254  return true;
255};
256
257// Auto-init the sidebar section menu once the DOM exists
258(function autoInitSectionMenu () {
259  if (document.readyState === 'loading') {
260    document.addEventListener('DOMContentLoaded', setupSidebarSectionMenu, { once: true });
261  } else {
262    setupSidebarSectionMenu();
263  }
264})();
265
266
267
268// Function for Logo Carousel
269window.addEventListener('load', () => {
270    const track     = document.getElementById('logoTrack');
271    const container = track.parentElement;
272    const originals = Array.from(track.children);
273
274    // 1) measure one set’s width
275    const singleSetWidth = originals.reduce((sum, el) => {
276      const style = getComputedStyle(el);
277      return sum + el.offsetWidth + parseFloat(style.marginRight);
278    }, 0);
279
280    // 2) clone until we have at least 2× container’s width
281    let totalW;
282    do {
283      originals.forEach(el => track.appendChild(el.cloneNode(true)));
284      totalW = track.scrollWidth;
285    } while (totalW < container.offsetWidth * 2);
286
287    // 3) set CSS var & start
288    track.style.setProperty('--scroll-width', `${singleSetWidth}px`);
289    track.classList.add('playing');
290
291    // —— PAUSE / PLAY button logic —— 
292    const pauseBtn = document.getElementById('pause-carousel');
293    const playBtn  = document.getElementById('play-carousel');
294
295    // show only the pause button initially
296    playBtn.style.display = 'none';
297
298    pauseBtn.addEventListener('click', () => {
299      track.style.animationPlayState = 'paused';
300      pauseBtn.style.display = 'none';
301      playBtn.style.display = 'inline-block';
302    });
303
304    playBtn.addEventListener('click', () => {
305      track.style.animationPlayState = 'running';
306      playBtn.style.display = 'none';
307      pauseBtn.style.display = 'inline-block';
308    });
309});
310
311
312
313$(function () {
314  const $els = $('.events-testimonials .inner_container .column.events .event_carousel a .event_information');
315
316  function applyMatchHeight() {
317    if (window.innerWidth < 768) {
318      $els.matchHeight();
319    } else {
320      // reset any heights matchHeight applied
321      $els.matchHeight({ remove: true });
322      $els.css('height', '');
323    }
324  }
325
326  applyMatchHeight();
327  $(window).on('resize orientationchange', applyMatchHeight);
328});
329
330
331
332
333$(function () {
334    // Match Height function for event info
335    $('#mainContent #content-area .newsListing a .content').matchHeight();
336});
337
338
339
340$(document).on('click', 'a.mobileMenuBTN, header#masthead a.searchOpener', function (e) {
341  const href = this.getAttribute('href');
342  if (!href || href === '#' || href === 'javascript:void(0)') e.preventDefault();
343
344  if (window.scrollY > 0) {
345    // instant jump to top
346    window.scrollTo(0, 0);
347    // (optional extra safety for very old browsers)
348    document.documentElement.scrollTop = 0;
349    document.body.scrollTop = 0;
350  }
351});

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.