PageSourceSearch

https://www.conestogac.on.ca/admissions/js/site.js?v=hruXd1yxWAWA3gQ_sX0JktXNRVWA-gkXyL19xe5PsxM

js conestogac.on.ca collected 2026-09-24 09:08:11 UTC 17,484 bytes, 525 lines download raw bytes

1$(document).ready(function () {
2    $('.searchcollapse').on('shown.bs.collapse', function () {
3        $("#text-search").focus();
4    });
5
6    var xy = document.getElementsByClassName(".full-search-btn");
7
8    $(xy).click(function (event) {
9        event.stopPropagation();
10        $('.searchcollapse').collapse('toggle');
11        $("#text-search").focus();
12    });
13
14    $(document).click(function (e) {
15        var searchbar = $(".searchcollapse");
16        var txtboxsearch = $("#text-search");
17        var btnsearch = $(".full-search-btn");
18
19        if (!searchbar.is(e.target) && !txtboxsearch.is(e.target) && !btnsearch.is(e.target)) {
20            $('.searchcollapse').collapse('hide')
21        }
22    });
23});
24
25// Main Site Nav
26$(function () {
27    $('[data-nav]').nav();
28});
29
30// Mobile nav
31document.addEventListener(
32    "DOMContentLoaded", () => {
33        new Mmenu("#offCanvasMenu", {
34            offCanvas: {
35                position: "right"
36            },
37            theme: "dark",
38            counters: {
39                add: true
40            },
41            scrollBugFix: false,
42        });
43    }
44);
45
46// Folder Nav Script
47(function (window, document, undefined) {
48    function closeMenu() {
49        $('.main-menu__open').removeClass('main-menu__open');
50    }
51
52    $(window).on('load', function () {
53        $('.menu-btn a').click(function (e) {
54            e.preventDefault();
55            e.stopPropagation();
56            $(this).toggleClass('main-menu__open')
57            $('.custom-navbar').toggleClass('main-menu__open');
58        });
59
60        $('.menu .menu-item--expanded').children('a').wrap("<div class='toggle_wrap'></div>").parent().append('<span class="menu-toggle icon ion-ios-plus-outline"></span>');
61
62        $('.block-expanded-menu-block .is-active').parents().each(function () {
63            if ($(this).hasClass('menu-item--expanded')) {
64                $(this).addClass('menu-item--active-trail menu-open');
65                $(this).children('.toggle_wrap').children('.menu-toggle').removeClass('ion-ios-plus-outline').addClass('ion-ios-minus-outline');
66            }
67        });
68
69        $('.menu-toggle').click(function () {
70            $parent = $(this).parent().parent();
71
72            if ($parent.hasClass('menu-open')) {
73                $parent.removeClass('menu-open');
74                $(this).removeClass('ion-ios-minus-outline').addClass('ion-ios-plus-outline');
75            }
76            else {
77                $parent.addClass('menu-open');
78                $(this).removeClass('ion-ios-plus-outline').addClass('ion-ios-minus-outline');
79            }
80        });
81
82        $(document).on('click', function (e) {
83            $('.menu--audience').removeClass('open');
84        });
85    });
86})(this, this.document);
87
88// Details and Summary
89const details = document.querySelectorAll("details");
90const detailsAnimationDuration = 300;
91const detailsAnimations = new WeakMap();
92
93const detailsOptions = (detail) => ({
94    animate: detail.dataset.detailsAnimate === "true",
95    collapseSiblings: detail.dataset.detailsCollapseSiblings !== "false",
96    scroll: detail.dataset.detailsScroll !== "false"
97});
98
99const resetDetailsContentStyles = (content) => {
100    content.style.height = "";
101    content.style.overflow = "";
102};
103
104const animateDetailsToggle = (detail, shouldOpen) => {
105    const summary = detail.querySelector("summary");
106
107    if (!summary || !summary.nextElementSibling) {
108        detail.open = shouldOpen;
109        return;
110    }
111
112    const content = summary.nextElementSibling;
113    const currentAnimation = detailsAnimations.get(detail);
114
115    if (currentAnimation) {
116        currentAnimation.cancel();
117    }
118
119    if (shouldOpen) {
120        detail.open = true;
121        content.style.height = "0";
122        content.style.overflow = "hidden";
123    }
124
125    const startHeight = shouldOpen ? 0 : content.offsetHeight;
126    const endHeight = shouldOpen ? content.scrollHeight : 0;
127    content.style.height = `${startHeight}px`;
128    content.style.overflow = "hidden";
129
130    const animation = content.animate(
131        [
132            { height: `${startHeight}px` },
133            { height: `${endHeight}px` }
134        ],
135        { duration: detailsAnimationDuration, easing: "ease-in-out" }
136    );
137
138    detailsAnimations.set(detail, animation);
139    animation.onfinish = () => {
140        detail.open = shouldOpen;
141        resetDetailsContentStyles(content);
142        detailsAnimations.delete(detail);
143    };
144    animation.oncancel = () => {
145        detailsAnimations.delete(detail);
146    };
147};
148
149details.forEach((targetDetail) => {
150    targetDetail.addEventListener("click", (event) => {
151        const options = detailsOptions(targetDetail);
152        const target = event.target instanceof Element ? event.target : null;
153        const summary = target ? target.closest("summary") : null;
154
155        if (options.animate && summary && summary.parentElement === targetDetail) {
156            event.preventDefault();
157            animateDetailsToggle(targetDetail, !targetDetail.open);
158        }
159
160        if (!options.scroll && !options.collapseSiblings) {
161            return;
162        }
163
164        details.forEach((detail) => {
165            if (detail == targetDetail && options.scroll) {
166                detail.scrollIntoView();
167            }
168            else if (detail !== targetDetail && options.collapseSiblings) {
169                detail.removeAttribute("open");
170            }
171        });
172    });
173});
174
175// Toggle open when URL fragment matches detail-summary identifier
176const openActiveDetail = (url) => {
177    let indexOfHash = url.indexOf("#");
178
179    if (indexOfHash !== -1) {
180        let hash = url.substring(indexOfHash).trim();
181
182        if (hash.length > 1) {
183            let summaryId = hash.substring(1);
184            let summary = document.querySelector(`summary#${summaryId}`);
185
186            if (summary !== null) {
187                let detail = summary.parentElement;
188                const options = detailsOptions(detail);
189
190                if (options.collapseSiblings) {
191                    this.document.querySelectorAll("details[open]").forEach((target) => {
192                        target.removeAttribute("open");
193                    });
194                }
195
196                if (details) {
197                    detail.open = true;
198
199                    if (options.scroll) {
200                        detail.scrollIntoView();
201                    }
202                }
203            }  
204        }
205    }
206};
207
208window.addEventListener("load", () => openActiveDetail(window.location.href));
209window.addEventListener("hashchange", (event) => openActiveDetail(event.newURL));
210
211// Carousel video pause
212function onYouTubeIframeAPIReady() {
213    const videoCarousels = document.querySelectorAll(".video-carousel");
214    videoCarousels.forEach((targetVideoCarousel) => {
215        const players = [];
216        const iframeSelector = "iframe[src^='https://www.youtube.com/embed']";
217        const iframes = targetVideoCarousel.querySelectorAll(iframeSelector);
218        iframes.forEach((iframe, index) => {
219            players[index] = new YT.Player(iframe, {
220                events: {
221                    "onReady": (event) => {
222                        event.target.pauseVideo();
223                    }
224                }
225            });
226        });
227        targetVideoCarousel.addEventListener("slide.bs.carousel", (e) => {
228            players.forEach((player) => {
229                player.pauseVideo();
230            });
231        });
232    });
233}
234
235// Card Scroller
236function setCardScroller(uniqueId) {
237    document.getElementById(`nextButton-${uniqueId}`).addEventListener('click', function () {
238        const cardsWrapper = document.querySelector(`#cardCarousel-${uniqueId} .cards-wrapper`);
239        const cardWidth = document.querySelector(`#cardCarousel-${uniqueId} .singlecard`).offsetWidth;
240        const scrollAmount = cardWidth * 1;
241        cardsWrapper.scrollBy({ left: scrollAmount, behavior: 'smooth' });
242    });
243
244    document.getElementById(`prevButton-${uniqueId}`).addEventListener('click', function () {
245        const cardsWrapper = document.querySelector(`#cardCarousel-${uniqueId} .cards-wrapper`);
246        const cardWidth = document.querySelector(`#cardCarousel-${uniqueId} .singlecard`).offsetWidth;
247        const scrollAmount = -cardWidth * 1;
248        cardsWrapper.scrollBy({ left: scrollAmount, behavior: 'smooth' });
249    });
250}
251
252// Program Listing: initializer
253(() => {
254  // Selectors and configuration
255  const SELECTOR = Object.freeze({
256    root: '.program-listing',
257    details: '.filter-accordion details',
258    summary: '.filter-accordion summary',
259    icon: 'summary .toggle-icon',
260    chip: '[data-program-chip]',
261    keywordInputName: 'KeyWords',
262    filterInput: 'input[data-program-filter-item]'
263  });
264
265  // Initialization guard
266  const isInitialized = (el) => el.hasAttribute('data-program-listing-init');
267  const markInitialized = (el) => el.setAttribute('data-program-listing-init', 'true');
268
269  // DOM helpers
270  const getDetails = (container) => Array.from(container.querySelectorAll(SELECTOR.details));
271  const getIcon = (detail) => detail.querySelector(SELECTOR.icon);
272  const escapeCss = (v) => (window.CSS && CSS.escape) ? CSS.escape(v) : String(v);
273
274  // Icon synchronization
275  const syncIcon = (detail) => {
276    const icon = getIcon(detail);
277    if (!icon) return;
278    icon.classList.toggle('fa-plus', !detail.open);
279    icon.classList.toggle('fa-minus', detail.open);
280  };
281  const syncAllIcons = (container) => getDetails(container).forEach(syncIcon);
282
283  // Accordion state management
284  const closeSiblings = (container, current) => getDetails(container).forEach((d) => { if (d !== current) d.removeAttribute('open'); });
285
286  // Prevent sitewide scroll for accordion interactions
287  function stopScrollIfAccordionClick(e, container) {
288    const target = e.target instanceof Element ? e.target : null;
289    if (!target) return false;
290    const summary = target.closest(SELECTOR.summary);
291    if (summary && container.contains(summary)) {
292      if (typeof e.stopImmediatePropagation === 'function') e.stopImmediatePropagation();
293      e.stopPropagation();
294      return true;
295    }
296    const detailsEl = target.closest(SELECTOR.details);
297    if (detailsEl && container.contains(detailsEl)) {
298      if (typeof e.stopImmediatePropagation === 'function') e.stopImmediatePropagation();
299      e.stopPropagation();
300      return true;
301    }
302    return false;
303  }
304
305  // Clear the filter represented by a chip
306  function clearChip(container, chip) {
307    const type = chip.getAttribute('data-program-chip');
308    const name = chip.getAttribute('data-filter-name');
309    const value = chip.getAttribute('data-filter-value');
310
311    if (type === 'keyword') {
312      const kw = container.querySelector(`input[name="${SELECTOR.keywordInputName}"]`);
313      if (kw) kw.value = '';
314      return;
315    }
316
317    if (type === 'filter' && name && value) {
318      const selector = `${SELECTOR.filterInput}[name="${escapeCss(name)}"][value="${escapeCss(value)}"]`;
319      const input = container.querySelector(selector);
320      if (input) input.checked = false;
321    }
322  }
323
324  // Toggle handler (capture)
325  function onToggleCapture(e, container) {
326    const detail = e.target;
327    if (!(detail instanceof HTMLElement) || detail.tagName.toLowerCase() !== 'details') return;
328    if (!container.contains(detail)) return;
329    if (detail.open) closeSiblings(container, detail);
330    syncAllIcons(container);
331  }
332
333  // Click handler (capture)
334  function onClickCapture(e, container) {
335    if (stopScrollIfAccordionClick(e, container)) return;
336    const target = e.target instanceof Element ? e.target : null;
337    if (!target) return;
338    const chip = target.closest(SELECTOR.chip);
339    if (chip && container.contains(chip)) clearChip(container, chip);
340  }
341
342  function initProgramListing() {
343    // Query containers
344    const containers = document.querySelectorAll(SELECTOR.root);
345
346    containers.forEach((container) => {
347      // Guard: skip if already initialized
348      if (!container || isInitialized(container)) return;
349      markInitialized(container);
350
351      // Initial icon sync
352      syncAllIcons(container);
353
354      // Register delegated handlers (capture)
355      container.addEventListener('toggle', (e) => onToggleCapture(e, container), true);
356      container.addEventListener('click', (e) => onClickCapture(e, container), true);
357    });
358  }
359
360  if (document.readyState === 'loading') {
361    // DOM-ready hook
362    document.addEventListener('DOMContentLoaded', () => initProgramListing());
363  } else {
364    // Initialize immediately if DOM already loaded
365    initProgramListing();
366  }
367
368  // Expose initializer for dynamic mounts
369  window.initProgramListing = initProgramListing;
370})();
371
372// Locations Map: initializer
373(function () {
374    // Map setup
375    function initMap() {
376        // Guard: ensure map container and Google Maps are available
377        var mapElement = document.getElementById('map');
378        if (!mapElement || !window.google || !google.maps) {
379            return;
380        }
381
382        // Parse payload
383        var locations = getLocations(mapElement);
384        if (!locations) {
385            return;
386        }
387
388        // Initialize map and shared UI state
389        var map = new google.maps.Map(mapElement, {
390            zoom: 9,
391            center: { lat: 43.263, lng: -80.330 }
392        });
393        var infoWindow = new google.maps.InfoWindow();
394        var markers = [];
395        var campusIcon = mapElement.dataset.campusIcon || '';
396        var housingIcon = mapElement.dataset.housingIcon || '';
397        var clusterIcon = mapElement.dataset.clusterIcon || '';
398
399        // Create a marker per location
400        locations.forEach(function (location) {
401            var marker = createMarker(location, map, infoWindow, campusIcon, housingIcon);
402            if (marker) {
403                markers.push(marker);
404            }
405        });
406
407        // Cluster markers if configured
408        createClusterer(map, markers, clusterIcon);
409    }
410
411    // Payload parsing
412    function getLocations(mapElement) {
413        // Parse the serialized payload from the DOM
414        var locationsJson = mapElement.dataset.locations;
415        if (!locationsJson) {
416            return null;
417        }
418
419        try {
420            var parsed = JSON.parse(locationsJson);
421            return Array.isArray(parsed) ? parsed : null;
422        } catch (error) {
423            console.error('Failed to parse locations map payload.', error);
424            return null;
425        }
426    }
427
428    // Marker creation
429    function createMarker(location, map, infoWindow, campusIcon, housingIcon) {
430        // Resolve marker details
431        var position = getLocationPosition(location);
432        var title = getMarkerTitle(location);
433        var icon = getMarkerIcon(location, campusIcon, housingIcon);
434
435        if (!position) {
436            console.error(`Invalid coordinates for ${title || 'unknown location'}`);
437            return null;
438        }
439
440        // Create marker and wire the click handler
441        var marker = new google.maps.Marker({
442            position: position,
443            map: map,
444            icon: icon,
445            title: title
446        });
447
448        marker.addListener('click', function () {
449            openInfoWindow(infoWindow, map, marker, location);
450        });
451
452        return marker;
453    }
454
455    // Position helpers
456    function getLocationPosition(location) {
457        // Validate lat/lng before building the position
458        var lat = Number(location.latitude);
459        var lng = Number(location.longitude);
460
461        if (!Number.isFinite(lat) || !Number.isFinite(lng)) {
462            return null;
463        }
464
465        return { lat: lat, lng: lng };
466    }
467
468    // Display helpers
469    function getMarkerTitle(location) {
470        // Favor a clean title string
471        return location.title || '';
472    }
473
474    function getMarkerIcon(location, campusIcon, housingIcon) {
475        // Select icon based on location type
476        return location.locationType === 'Housing' ? housingIcon : campusIcon;
477    }
478
479    function openInfoWindow(infoWindow, map, marker, location) {
480        // Skip empty info windows
481        if (!location.infoWindowHtml) {
482            return;
483        }
484
485        infoWindow.setContent(location.infoWindowHtml);
486        infoWindow.open(map, marker);
487    }
488
489    // Cluster helpers
490    function createClusterer(map, markers, clusterIcon) {
491        // Guard: clusterer must exist and be configured
492        if (typeof markerClusterer === 'undefined' || markers.length === 0 || !clusterIcon) {
493            return;
494        }
495
496        var renderer = {
497            render: function (options) {
498                if (options.count === 1) {
499                    return null;
500                }
501
502                return new google.maps.Marker({
503                    position: options.position,
504                    icon: {
505                        url: clusterIcon,
506                        scaledSize: new google.maps.Size(50, 50),
507                        labelOrigin: new google.maps.Point(25, 20)
508                    },
509                    label: {
510                        text: String(options.count),
511                        color: 'white',
512                        className: 'cluster-label',
513                        fontSize: '14px',
514                        fontWeight: 'bold'
515                    },
516                    zIndex: Number(google.maps.Marker.MAX_ZINDEX) + options.count
517                });
518            }
519        };
520
521        new markerClusterer.MarkerClusterer({ map, markers, renderer });
522    }
523
524    window.initMap = initMap;
525})();

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.