PageSourceSearch

https://my.cazloyd.com/Content/isg/Content/nav/js/main.js

js cazloyd.com collected 2026-10-01 14:47:46 UTC 23,074 bytes, 647 lines download raw bytes

1/**
2 * Global main.js file
3 * For all pages.
4 */
5
6
7/**
8 * Namespace
9 * All objects & methods are attached to this global object SF.
10 * Any JS files for this theme should start by scoping this object.
11 */
12var SF = window.SF || {};
13
14
15/**
16 * Scoping jQuery $
17 */
18(function($) {
19
20
21    /** 
22     * (window) READY SET GO
23     */
24    $(window).load(function() {
25
26        // Initialise our RoyalSliders after
27        // everything else has been loaded,
28        // to keep initial load light.
29        SF.initRoyalSliders();
30    });
31    // ------------------------------------------------------
32
33
34    /** 
35     * (domready) READY SET GO
36     */
37    $(function() {
38
39        SF.fancyboxVideos();
40
41        SF.initMegaDropdowns();
42
43        SF.bindAccordionEvents();
44
45        SF.bindTabEvents();
46
47        SF.jRespond();
48
49        $('.meeting-info').hide();
50
51        $('.info-meeting .meeting-loc').click(function() {
52            /* Act on the event */
53            $(this).parent().find('.meeting-info').toggle();
54            if ($(this).find('i').hasClass('icon-caret-right')) {
55                $(this).find('i').removeClass('icon-caret-right')
56                $(this).find('i').addClass('icon-caret-down');
57            } else {
58                $(this).find('i').removeClass('icon-caret-down')
59                $(this).find('i').addClass('icon-caret-right');
60            }
61            ;
62
63        });
64
65        $('#student_email').focusout(function() {
66            if (validateMail($(this).val())) {
67                console.log("this val" + $(this).val());
68                
69                var _url = '/site/query_mail';
70                var _mail = $(this).val();
71                console.log(" _mail" + _mail);
72                $.ajax({
73                    type: 'GET',
74                    url: _url,
75                    data: {
76                        mail: _mail
77                    },
78                    success: function(response) {
79                        $('#student_message').html('Your account already exists, please <a href="' + response + '" title="MySummerfuel" target="_blank">Log In</a>.');
80                        $(".applyForm2 :input").attr("disabled", true);
81                        $('#submit_continue').css('background-image', 'url(../img/legacy/submit-continue-disabled.png)');
82                        $("#student_email").attr("disabled", false);
83                    },
84                    error: function(jqXHR, textStatus, errorThrown) {
85                        if (jqXHR.status == 404) {
86                            $('#student_message').html('');
87                            $(".applyForm2 :input").attr("disabled", false);
88                            $('#submit_continue').css('background-image', 'url(../img/legacy/submit-continue.png)');
89                        } else {
90                            var message = '<h4>Some errors prohibited this email from being evaluated:</h4><ul>';
91                            message += '<li>' + jqXHR.responseText + '</li>';
92                            message += '</ul>';
93                            $('#student_message').html(message);
94                        }
95                    }
96                });
97            } else if ($(this).val() == '') {
98                $('#student_message').html('');
99                $(".applyForm2 :input").attr("disabled", false);
100                $('#student_first_name').val('');
101                $('#student_last_name').val('');
102            }
103        });
104        var _parent = null;
105        $('#parent_email').focusout(function() {
106            if (validateMail($(this).val())) {
107                var _url = '/site/query_mail';
108                var _mail = $(this).val();
109                $.ajax({
110                    type: 'GET',
111                    url: _url,
112                    dataType: 'json',
113                    data: {
114                        mail: _mail
115                    },
116                    success: function(response) {
117                        _parent = response;
118                        $('#parent_message').html('Parent already exists, a connection with the student will be created.');
119                        $('#parent_first_name').val(_parent.first_name);
120                        $('#parent_last_name').val(_parent.last_name);
121                        $('select[name="relationship_to_student"]').find('option[value="' + _parent.relation + '"]').attr("selected", true);
122                    },
123                    error: function(jqXHR, textStatus, errorThrown) {
124                        if (jqXHR.status == 404) {
125                            $('#parent_message').html('');
126                            console.log(_parent);
127                            if (typeof _parent !== 'undefined' && _parent) {
128                                $('#parent_first_name').val('');
129                                $('#parent_last_name').val('');
130                                $('option:selected', 'select[name="relationship_to_student"]').removeAttr('selected');
131                                _parent = null;
132                            }
133                        } else {
134                            var message = '<h4>Some errors prohibited this email being evaluated:</h4><ul>';
135                            message += '<li>' + jqXHR.responseText + '</li>';
136                            message += '</ul>';
137                            $('#parent_message').html(message);
138                        }
139                    }
140                });
141            } else if ($(this).val() == '') {
142                $('#parent_first_name').val('');
143                $('#parent_last_name').val('');
144                $('option:selected', 'select[name="relationship_to_student"]').removeAttr('selected');
145                $('#parent_message').html('');
146                _parent = null;
147            }
148        });
149
150    });
151    // ------------------------------------------------------
152
153
154    /**
155     * Handle video links by popping them into a fancybox
156     */
157    SF.fancyboxVideos = function() {
158        // open youtube in lightbox
159        var $fancyboxMe = $('a[href*="vimeo.com"],a[href*="youtube.com"],a[href*="youtu.be"]');
160
161        $.each($fancyboxMe, function(i) {
162            var $slf = $(this),
163                    $rsBlockParent = $slf.parents('.rsBlock'),
164                    $heroImageParent = $slf.parents('.hero-image');
165
166            $slf.addClass('playCta')
167                    .fancybox({
168                        padding: 0,
169                        helpers: {
170                            media: {
171                                youtube: {
172                                    params: {
173                                        autoplay: 0
174                                    }
175                                }
176                            }
177                        },
178                        width: 960,
179                        height: 540,
180                        aspectRatio: true,
181                        scrolling: 'no',
182                        beforeLoad: function() {
183
184                            // track a video play event
185                            _gaq.push(['_trackEvent', 'Videos', 'Play', $(this).attr('href')]);
186
187                            $('.royalSlider').each(function(i, e) {
188                                var slider = $(this).data('royalSlider');
189                                slider.stopAutoPlay();
190                            });
191                        },
192                        afterClose: function() {
193                            $('.royalSlider').each(function(i, e) {
194                                var slider = $(this).data('royalSlider');
195                                slider.startAutoPlay();
196                            });
197                        }
198                    });
199
200            if ($rsBlockParent.length > 0)
201            {
202                $rsBlockParent.addClass('rsBlockHasPlayCta');
203            }
204
205            if ($heroImageParent.length > 0)
206            {
207                $heroImageParent.addClass('heroImageHasPlayCta');
208            }
209        });
210    };
211
212
213    /** 
214     * refreshUI()
215     * Refresh JS components like Scrollspy, Affix.
216     * Will be called by other methods here.
217     */
218    SF.refreshUI = function() {
219        // this is temporarily commented out due to an issue with our location-navbar losing its affix/waypoint on window resize
220        // see this issue https://github.com/imakewebthings/jquery-waypoints/issues/64#issuecomment-5450902
221        //$.waypoints('refresh');
222
223        if ($('body').data('scrollspy'))
224        {
225            $('body').scrollspy('refresh');
226        }
227    };
228
229    // ------------------------------------------------------
230
231    /**
232     * jRespond()
233     * JS to trigger when entering/exiting responsive breakpoints
234     */
235    SF.jRespond = function() {
236        // refresh our UI on breakpoints
237        var jRes = jRespond([
238            {
239                label: 'handheld',
240                enter: 0,
241                exit: 767
242            }, {
243                label: 'tablet',
244                enter: 768,
245                exit: 979
246            }, {
247                label: 'desktop',
248                enter: 980,
249                exit: 10000
250            }
251        ]);
252
253        // redraw UI on every breakpoint entry
254        jRes.addFunc({
255            breakpoint: '*',
256            enter: function(b) {
257                SF.refreshUI();
258            }
259        });
260    };
261    // ------------------------------------------------------
262
263
264    /** 
265     * initRoyalSliders()
266     * init our various royalsliders
267     */
268    SF.initRoyalSliders = function() {
269
270        // create our default options object
271        function defaultOptions(obj) {
272            var options = {
273                slidesSpacing: 0,
274                imageScalePadding: 0,
275                imageScaleMode: 'fill',
276                autoScaleSlider: true,
277                fadeinLoadedSlide: false,
278                loop: true,
279                imagesToPreload: 1,
280                transitionSpeed: 800,
281                autoPlay: {
282                    enabled: true,
283                    pauseOnHover: true,
284                    delay: 10000
285                }
286            };
287
288            // Disable CSS3 animations for Chrome due to bug
289            // http://help.dimsemenov.com/discussions/problems/1153-chrome-scrolling-choppylags-when-a-lot-of-images-in-slideshow-plus-position-fixed
290            // Currently we are addressing this through a second option, in sf-content-wrapper.less
291            // But if that turns out to not help enough, fallback this route!
292            if ($.browser.chrome) {
293                options.allowCSS3 = false;
294            }
295
296            // have we be given a width & height
297            // to help with aspect ratio during resize?
298            if ($(obj).data('rsWidth'))
299            {
300                options.autoScaleSliderWidth = $(obj).data('rsWidth');
301            }
302
303            if ($(obj).data('rsHeight'))
304            {
305                options.autoScaleSliderHeight = $(obj).data('rsHeight');
306            }
307
308            // no navigation 'cause only one?
309            if ($(obj).find('.royalSlider').children().length < 2)
310            {
311                options.controlNavigation = '';
312            }
313
314            return options;
315        }
316
317        // our "default" royalsliders
318        // Full-width slideshows with bullets for navigation
319        // and optional "global" caption element
320        $('.rsSummerfuelDefault').each(function(i) {
321
322            var options = defaultOptions(this);
323
324            var first = $(this).find('.royalSlider').children().first();
325
326            if (first.find('.rsCaption').length > 0)
327            {
328                options.globalCaption = true;
329                $(this).addClass('globalCaption');
330            }
331
332            $(this).find('.royalSlider').royalSlider(options);
333        });
334
335        // "thumbnail" royalsliders on homepage
336        // Tiny slideshows, only bullets for navigation
337        $('.rsSummerfuelThumb').each(function(i) {
338
339            var options = defaultOptions(this);
340
341            options.transitionSpeed = 400;
342
343            $(this).find('.royalSlider').royalSlider(options);
344        });
345
346        // "timeline" royalsliders on program pages
347        // Rather complex - uses a separate UL dom
348        // as custom navigation.
349        // What's more confusing is that the first slide
350        // has no corresponding navigation element; it is
351        // shown as the first slide, and each navigation element
352        // slides to the others.  Hence why we play with the index & offset.
353        $('.rsSummerfuelTimeline').each(function(i) {
354
355            var options = defaultOptions(this);
356
357            var second = $(this).find('.royalSlider').children().eq(1);
358
359            if (second.find('.rsCaption').length > 0)
360            {
361                options.globalCaption = true;
362                $(this).addClass('globalCaption');
363            }
364
365            $(this).find('.royalSlider').royalSlider(options);
366
367            // grab the RoyalSlider API
368            var sliderAPI = $(this).find('.royalSlider').data('royalSlider'),
369                    // grab our thumbnails
370                    timelineThumbs = $(this).find('.nav li');
371
372            // when clicked, go to the corresponding slide
373            timelineThumbs.on('click', function(e) {
374                e.preventDefault();
375
376                // don't forget to go +1
377                sliderAPI.goTo(timelineThumbs.index(this) + 1);
378            });
379
380            // after a slide, set correct navigation element to "active"
381            sliderAPI.ev.on('rsAfterSlideChange', function() {
382                if (sliderAPI.currSlideId > 0)
383                {
384                    // don't forget to go -1
385                    timelineThumbs.eq(sliderAPI.currSlideId - 1).addClass('active');
386                }
387            });
388
389            // before any slide, remove all "active" class values
390            sliderAPI.ev.on('rsBeforeAnimStart', function() {
391                timelineThumbs.removeClass('active');
392            });
393
394            // move our caption!
395            $(this).find('.rsGCaption').detach().appendTo($(this));
396            SF.refreshUI();
397        });
398
399
400        // "hero" slideshow on homepage
401        // UPon first glance it looks like our "default" slideshow,
402        // without captions. However we manually "lazy load" our images,
403        // because we need to achieve a fluid width, fixed height design.
404        $('.rsSummerfuelHero').each(function(i) {
405
406            var options = defaultOptions(this);
407
408            options.autoScaleSlider = false;
409            options.autoPlay = {
410                // autoplay options go gere
411                enabled: true,
412                pauseOnHover: true,
413                delay: 10000
414            };
415
416            // fit our headline text
417            $(this).find('h1').fitText(1.1, {
418                minFontSize: 40,
419                maxFontSize: 100
420            });
421
422            // now lazyload our background images
423            $(this).find('.rsContent').each(function(i) {
424
425                var self = this,
426                        background = $(self).data('background');
427
428                if (background)
429                {
430                    var img = $('<img />', {
431                        src: background
432                    });
433
434                    // once our image has loaded, add it as the background image to our slide
435                    $(img).imagesLoaded(function() {
436                        $(self).css('background-image', 'url(' + background + ')');
437                    });
438                }
439
440            });
441
442            // init RoyalSlider
443            $(this).find('.royalSlider').royalSlider(options);
444
445            // trigger a window resize to ensure fittext runs
446            var rsApi = $(this).find('.royalSlider').data('royalSlider');
447            rsApi.ev.on('rsBeforeAnimStart', function(event) {
448                $(window).trigger('resize');
449            });
450
451        });
452    };
453    // ------------------------------------------------------
454
455
456    /** 
457     * bindAccordionEvents()
458     * Attach to accordion events
459     * This is basically to give us our toggling carats (down = open, right = closed)
460     *
461     * Nov 17, 2012 - Temporarily have moved hide & show events into hidden & shown,
462     * to work around conflict with Prototype.
463     */
464    SF.bindAccordionEvents = function() {
465
466        // for each element, do...
467        $('.accordion-body').each(function() {
468            $(this)
469                    .on('hide', function() {
470                        //$(this).closest('.accordion-group').find('.accordion-heading').removeClass('open');
471                    })
472                    .on('show', function() {
473                        //$(this).closest('.accordion-group').find('.accordion-heading').addClass('open');
474                    })
475                    .on('hidden', function() {
476                        $(this).closest('.accordion-group').find('.accordion-heading').removeClass('open');
477                        SF.refreshUI();
478                    })
479                    .on('shown', function() {
480                        $(this).closest('.accordion-group').find('.accordion-heading').addClass('open');
481                        SF.refreshUI();
482                    });
483        });
484    };
485    // ------------------------------------------------------
486
487
488    /** 
489     * bindTabEvents()
490     * Enable forward/back
491     */
492    SF.bindTabEvents = function() {
493
494        // if we have support of history, let's bind to it
495        if (Modernizr.history && $('.nav-tabs').length > 0)
496        {
497            // add a hash to the URL when the user clicks on a tab
498            $('a[data-toggle="tab"]').on('click', function(e) {
499
500                e.preventDefault();
501
502                history.pushState(null, null, $(this).attr('href'));
503
504                $(this).tab('show');
505
506            });
507
508            // navigate to a tab when the history changes
509            $(window).on('popstate', function(e) {
510                var activeTab = $('[href=' + location.hash + ']');
511                if (activeTab.length) {
512                    activeTab.tab('show');
513                } else {
514                    $('.nav-tabs a:first').tab('show');
515                }
516            }).trigger('popstate');
517        }
518    };
519    // ------------------------------------------------------
520
521
522    /** 
523     * initMegaDropdowns()
524     */
525    SF.initMegaDropdowns = function() {
526
527        // sanity check
528        SF.programNavbar = $('#program-navbar');
529        if (SF.programNavbar.length == 0)
530            return;
531
532        // our containing dom
533        SF.megaPopover = $('<div id="mega-dropdown-popover" class="hidden-phone" />');
534        SF.megaPopover
535                // determine top position for our mega dropdowns
536                .css('top', SF.programNavbar.offset().top + SF.programNavbar.innerHeight())
537                // inject
538                .appendTo($('body'));
539
540        // Our internal flag tells us which dropdown may be open
541        SF.megaDropdownOpen = false;
542        SF.programNavs = SF.programNavbar.find('.nav').first().children();
543        SF.activePage = SF.programNavs.filter('.active');
544
545        // "IN" function
546        SF.megaDropdownIn = function(el) {
547
548            clearTimeout(SF.megaDropdownOutTimeout);
549
550            SF.megaDropdownOpen = $(el).data('target');
551            var parent = $(el).closest('li');
552
553            // determine top position for our mega dropdowns
554            SF.megaPopover.css('top', $(el).offset().top + $(el).closest('.navbar').innerHeight());
555
556            // temp remove active state
557            if (SF.activePage.length > 0) {
558                SF.activePage.removeClass('active');
559            }
560
561            // move open class
562            SF.programNavs.filter('.open').not(parent).removeClass('open');
563            $(parent).addClass('open');
564
565            var clone = $(SF.megaDropdownOpen).clone();
566            SF.megaPopover.empty();
567            clone.appendTo(SF.megaPopover);
568
569            SF.megaPopover.height(clone.height());
570            clone.addClass('open');
571        };
572
573        // "OUT" function
574        SF.megaDropdownOut = function() {
575            SF.megaDropdownOpen = false;
576            SF.programNavs.filter('.open').removeClass('open');
577
578            // restore page active?
579            if (SF.activePage.length > 0)
580            {
581                SF.activePage.addClass('active');
582            }
583
584            SF.megaPopover.height(0);
585        };
586
587        // Bind to clicks
588        SF.programNavbar.find('.mega-dropdown-trigger').on('click', function(e) {
589
590            e.preventDefault();
591
592            if (Modernizr.touch)
593            {
594                if (!SF.megaDropdownOpen || SF.megaDropdownOpen != $(this).data('target'))
595                {
596                    SF.megaDropdownIn(this);
597                }
598                else
599                {
600                    SF.megaDropdownOut();
601                }
602            }
603        });
604
605        if (!Modernizr.touch)
606        {
607            // Bind to hovering
608            SF.programNavbar.find('.mega-dropdown-trigger').hoverIntent({
609                over: function(e) {
610                    SF.megaDropdownIn(this);
611                },
612                out: function(e) {
613                }
614            });
615
616            SF.programNavbar.on('mouseover', function(e) {
617                clearTimeout(SF.megaDropdownOutTimeout);
618            });
619
620            SF.megaPopover.on('mouseover', function(e) {
621                clearTimeout(SF.megaDropdownOutTimeout);
622            });
623
624            SF.programNavbar.on('mouseout', function(e) {
625                SF.megaDropdownOutTimeout = setTimeout(function() {
626                    SF.megaDropdownOut();
627                }, 300);
628            });
629
630            SF.megaPopover.on('mouseout', function(e) {
631                SF.megaDropdownOutTimeout = setTimeout(function() {
632                    SF.megaDropdownOut();
633                }, 300);
634            });
635        }
636    };
637    // ------------------------------------------------------
638
639})(jQuery);
640// ------------------------------------------------------
641
642// PRIVATE
643
644function validateMail(mailText) {
645    var pattern = new RegExp(/^((([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+(\.([a-z]|\d|[!#\$%&'\*\+\-\/=\?\^_`{\|}~]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])+)*)|((\x22)((((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(([\x01-\x08\x0b\x0c\x0e-\x1f\x7f]|\x21|[\x23-\x5b]|[\x5d-\x7e]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(\\([\x01-\x09\x0b\x0c\x0d-\x7f]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF]))))*(((\x20|\x09)*(\x0d\x0a))?(\x20|\x09)+)?(\x22)))@((([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|\d|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.)+(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])|(([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])([a-z]|\d|-|\.|_|~|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])*([a-z]|[\u00A0-\uD7FF\uF900-\uFDCF\uFDF0-\uFFEF])))\.?$/i);
646    return pattern.test(mailText);
647}

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.