PageSourceSearch

https://shop.charlevoixrunning.com/assets/scripts/scripts.js?v=1.2.0

js charlevoixrunning.com collected 2026-09-29 10:00:24 UTC 54,883 bytes, 1,403 lines download raw bytes

1var mr_firstSectionHeight,
2    mr_nav,
3    mr_fixedAt,
4    mr_navOuterHeight,
5    mr_navScrolled = false,
6    mr_navFixed = false,
7    mr_outOfSight = false,
8    mr_floatingProjectSections,
9    mr_scrollTop = 0;
10
11$(document).ready(function() { 
12    "use strict";
13    const urlParams = new URLSearchParams(window.location.search); 
14    if (urlParams.has("framed")) {
15        $(".nav-container").hide();
16        $("footer").hide();
17    }
18
19	$(".toggler").click((e) => {
20		if ($(e.currentTarget).hasClass("on")) $(e.currentTarget).removeClass("on");
21		else $(e.currentTarget).addClass("on");
22    });
23
24    // Smooth scroll to inner links
25        var innerLinks = $('a.inner-link');
26
27        if(innerLinks.length){
28            innerLinks.each(function(){
29                var link = $(this);
30                var href = link.attr('href');
31                if(href.charAt(0) !== "#"){
32                    link.removeClass('inner-link');
33                }
34            });
35
36            var offset = 0;
37            if($('body[data-smooth-scroll-offset]').length){
38                offset = $('body').attr('data-smooth-scroll-offset');
39                offset = offset*1;
40            }
41            
42            smoothScroll.init({
43                selector: '.inner-link',
44                selectorHeader: null,
45                speed: 750,
46                easing: 'easeInOutCubic',
47                offset: offset
48            });
49        }
50
51    // Update scroll variable for scrolling functions
52
53    addEventListener('scroll', function() {
54        mr_scrollTop = window.pageYOffset;
55    }, false);
56
57    // Append .background-image-holder <img>'s as CSS backgrounds
58
59    $('.background-image-holder').each(function() {
60        if ($(this).closest('section').hasClass('dynamic')) return;
61        var imgSrc = $(this).children('img').attr('src');
62        if (imgSrc) {
63            $(this).css('background-image', 'url("' + imgSrc + '")');
64            $(this).children('img').hide();
65            $(this).css('background-position', 'initial');
66        }
67    });
68
69    // Fade in background images
70
71    setTimeout(function() {
72        $('.background-image-holder').each(function() {
73            $(this).addClass('fadeIn');
74        });
75    }, 200);
76
77    // Initialize Tooltips
78
79    $('[data-toggle="tooltip"]').tooltip();
80
81    // Icon bulleted lists
82
83    $('ul[data-bullet]').each(function(){
84        var bullet = $(this).attr('data-bullet');
85        $(this).find('li').prepend('<i class="'+bullet+'"></i>');
86    });
87
88    // Progress Bars
89
90    $('.progress-bar').each(function() {
91        $(this).css('width', $(this).attr('data-progress') + '%');
92    });
93
94    // Navigation
95
96    if (!$('nav').hasClass('fixed') && !$('nav').hasClass('absolute')) {
97
98        // Make nav container height of nav
99
100        $('.nav-container').css('min-height', $('nav').outerHeight(true));
101
102        $(window).resize(function() {
103            $('.nav-container').css('min-height', $('nav').outerHeight(true));
104        });
105
106        // Compensate the height of parallax element for inline nav
107
108        if ($(window).width() > 768) {
109            $('.parallax:nth-of-type(1) .background-image-holder').css('top', -($('nav').outerHeight(true)));
110        }
111
112        // Adjust fullscreen elements
113
114        if ($(window).width() > 768) {
115            $('section.fullscreen:nth-of-type(1)').css('height', ($(window).height() - $('nav').outerHeight(true)));
116        }
117
118    } else {
119        $('body').addClass('nav-is-overlay');
120    }
121
122    if ($('nav').hasClass('bg-dark')) {
123        $('.nav-container').addClass('bg-dark');
124    }
125
126
127    // Fix nav to top while scrolling
128
129    mr_nav = $('body .nav-container nav:first');
130    mr_navOuterHeight = $('body .nav-container nav:first').outerHeight();
131        mr_fixedAt = typeof mr_nav.attr('data-fixed-at') !== typeof undefined ? parseInt(mr_nav.attr('data-fixed-at').replace('px', '')) : parseInt($('section:nth-of-type(1)').outerHeight());
132    window.addEventListener("scroll", updateNav, false);
133
134    // Menu dropdown positioning
135
136    $('.menu > li > ul').each(function() {
137        var menu = $(this).offset();
138        var farRight = menu.left + $(this).outerWidth(true);
139        if (farRight > $(window).width() && !$(this).hasClass('mega-menu')) {
140            $(this).addClass('make-right');
141        } else if (farRight > $(window).width() && $(this).hasClass('mega-menu')) {
142            var isOnScreen = $(window).width() - menu.left;
143            var difference = $(this).outerWidth(true) - isOnScreen;
144            $(this).css('margin-left', -(difference));
145        }
146    });
147
148    // Mobile Menu
149
150$('.mobile-toggle').click(function() {
151    $('.nav-bar').toggleClass('nav-open');
152    $(this).toggleClass('active');
153    $(this).find('i').toggleClass('icon-Main-Menu icon-x');
154});
155
156    $('.menu li').click(function(e) {
157        if (!e) e = window.event;
158        e.stopPropagation();
159        if ($(this).find('ul').length) {
160            $(this).toggleClass('toggle-sub');
161        } else {
162            $(this).parents('.toggle-sub').removeClass('toggle-sub');
163        }
164    });
165
166    $('.menu li a').click(function() {
167        if ($(this).hasClass('inner-link')){
168            $(this).closest('.nav-bar').removeClass('nav-open');
169        }
170    });
171
172    $('.module.widget-handle').click(function() {
173        $(this).toggleClass('toggle-widget-handle');
174    });
175
176    $('.search-widget-handle .search-form input').click(function(e){
177        if (!e) e = window.event;
178        e.stopPropagation();
179    });
180    
181    // Offscreen Nav
182    
183    if($('.offscreen-toggle').length){
184    	$('body').addClass('has-offscreen-nav');
185    }
186    else{
187        $('body').removeClass('has-offscreen-nav');
188    }
189    
190    $('.offscreen-toggle').click(function(){
191    	$('.main-container').toggleClass('reveal-nav');
192    	$('nav').toggleClass('reveal-nav');
193    	$('.offscreen-container').toggleClass('reveal-nav');
194    });
195    
196    $('.main-container').click(function(){
197    	if($(this).hasClass('reveal-nav')){
198    		$(this).removeClass('reveal-nav');
199    		$('.offscreen-container').removeClass('reveal-nav');
200    		$('nav').removeClass('reveal-nav');
201    	}
202    });
203    
204    $('.offscreen-container a').click(function(){
205    	$('.offscreen-container').removeClass('reveal-nav');
206    	$('.main-container').removeClass('reveal-nav');
207    	$('nav').removeClass('reveal-nav');
208    });
209
210    // Populate filters
211    
212    $('.projects').each(function() {
213
214        var filters = "";
215
216        $(this).find('.project').each(function() {
217
218            var filterTags = $(this).attr('data-filter').split(',');
219
220            filterTags.forEach(function(tagName) {
221                if (filters.indexOf(tagName) == -1) {
222                    filters += '<li data-filter="' + tagName + '">' + capitaliseFirstLetter(tagName) + '</li>';
223                }
224            });
225            $(this).closest('.projects')
226                .find('ul.filters').empty().append('<li data-filter="all" class="active">All</li>').append(filters);
227        });
228    });
229
230    $('.filters li').click(function() {
231        var filter = $(this).attr('data-filter');
232        $(this).closest('.filters').find('li').removeClass('active');
233        $(this).addClass('active');
234
235        $(this).closest('.projects').find('.project').each(function() {
236            var filters = $(this).attr('data-filter');
237
238            if (filters.indexOf(filter) == -1) {
239                $(this).addClass('inactive');
240            } else {
241                $(this).removeClass('inactive');
242            }
243        });
244
245        if (filter == 'all') {
246            $(this).closest('.projects').find('.project').removeClass('inactive');
247        }
248    });
249
250    // Twitter Feed
251       $('.tweets-feed').each(function(index) {
252           jQuery(this).attr('id', 'tweets-' + index);
253       }).each(function(index) {
254           var element = $('#tweets-' + index);
255           var TweetConfig = {
256               "domId": '',
257               "maxTweets": element.attr('data-amount'),
258               "enableLinks": true,
259               "showUser": true,
260               "showTime": true,
261               "dateFunction": '',
262               "showRetweet": false,
263               "customCallback": handleTweets
264           };
265
266           if(typeof element.attr('data-widget-id') !== typeof undefined){
267                TweetConfig.id = element.attr('data-widget-id');
268            }else if(typeof element.attr('data-feed-name') !== typeof undefined && element.attr('data-feed-name') !== "" ){
269                TweetConfig.profile = {"screenName": element.attr('data-feed-name').replace('@', '')};
270            }else{
271                TweetConfig.profile = {"screenName": 'twitter'};
272            }
273
274           function handleTweets(tweets) {
275               var x = tweets.length;
276               var n = 0;
277               var element = document.getElementById('tweets-' + index);
278               var html = '<ul class="slides">';
279               while (n < x) {
280                   html += '<li>' + tweets[n] + '</li>';
281                   n++;
282               }
283               html += '</ul>';
284               element.innerHTML = html;
285
286               if ($('.tweets-slider').length) {
287                    $('.tweets-slider').flexslider({
288                        directionNav: false,
289                        controlNav: false
290                    });
291                }       
292               return html;
293           }
294           twitterFetcher.fetch(TweetConfig);
295      });
296
297    // Instagram Feed
298    
299    if($('.instafeed').length){
300    	jQuery.fn.spectragram.accessData = {
301			accessToken: '1406933036.dc95b96.2ed56eddc62f41cbb22c1573d58625a2',
302			clientID: '87e6d2b8a0ef4c7ab8bc45e80ddd0c6a'
303		};	
304
305        $('.instafeed').each(function() {
306            var feedID = $(this).attr('data-user-name');
307            $(this).children('ul').spectragram('getUserFeed', {
308                query: feedID,
309                max: 12
310            });
311        });
312    }   
313
314   
315
316    // Flickr Feeds
317
318    if($('.flickr-feed').length){
319        $('.flickr-feed').each(function(){
320            var userID = $(this).attr('data-user-id');
321            var albumID = $(this).attr('data-album-id');
322            $(this).flickrPhotoStream({ id: userID, setId: albumID, container: '<li class="masonry-item" />' });   
323            setTimeout(function(){
324                initializeMasonry();
325                window.dispatchEvent(new Event('resize'));
326            }, 1000); 
327        });
328
329    }
330
331    // Image Sliders
332    if($('.slider-all-controls, .slider-paging-controls, .slider-arrow-controls, .slider-thumb-controls, .logo-carousel').length){
333        $('.slider-all-controls').flexslider({
334            start: function(slider){
335                if(slider.find('.slides li:first-child').find('.fs-vid-background video').length){
336                   slider.find('.slides li:first-child').find('.fs-vid-background video').get(0).play(); 
337                }
338            },
339            after: function(slider){
340                if(slider.find('.fs-vid-background video').length){
341                    if(slider.find('li:not(.flex-active-slide)').find('.fs-vid-background video').length){
342                        slider.find('li:not(.flex-active-slide)').find('.fs-vid-background video').get(0).pause();
343                    }
344                    if(slider.find('.flex-active-slide').find('.fs-vid-background video').length){
345                        slider.find('.flex-active-slide').find('.fs-vid-background video').get(0).play();
346                    }
347                }
348            }
349        });
350        $('.slider-paging-controls').flexslider({
351            animation: "slide",
352            directionNav: false
353        });
354        $('.slider-arrow-controls').flexslider({
355            controlNav: false
356        });
357        $('.slider-thumb-controls .slides li').each(function() {
358            var imgSrc = $(this).find('img').attr('src');
359            $(this).attr('data-thumb', imgSrc);
360        });
361        $('.slider-thumb-controls').flexslider({
362            animation: "slide",
363            controlNav: "thumbnails",
364            directionNav: true
365        });
366        $('.logo-carousel').flexslider({
367            minItems: 1,
368            maxItems: 4,
369            move: 1,
370            itemWidth: 200,
371            itemMargin: 0,
372            animation: "slide",
373            slideshow: true,
374            slideshowSpeed: 3000,
375            directionNav: false,
376            controlNav: false
377        });
378    }
379    
380    // Lightbox gallery titles
381    
382    $('.lightbox-grid li a').each(function(){
383    	var galleryTitle = $(this).closest('.lightbox-grid').attr('data-gallery-title');
384    	$(this).attr('data-lightbox', galleryTitle);
385    });
386
387    // Prepare embedded video modals
388
389    $('iframe[data-provider]').each(function(){
390        var provider = jQuery(this).attr('data-provider');
391        var videoID = jQuery(this).attr('data-video-id');
392        var autoplay = jQuery(this).attr('data-autoplay');
393        var vidURL = '';
394
395        if(provider == 'vimeo'){
396            vidURL = "http://player.vimeo.com/video/"+videoID+"?badge=0&title=0&byline=0&title=0&autoplay="+autoplay;
397            $(this).attr('data-src', vidURL);
398        }else if (provider == 'youtube'){
399            vidURL = "https://www.youtube.com/embed/"+videoID+"?showinfo=0&autoplay="+autoplay;
400            $(this).attr('data-src', vidURL);
401        }else{
402            console.log('Only Vimeo and Youtube videos are supported at this time');
403        }
404    });
405    
406    // Multipurpose Modals
407    
408    jQuery('.foundry_modal[modal-link]').remove();
409
410    if($('.foundry_modal').length && (!jQuery('.modal-screen').length)){
411        // Add a div.modal-screen if there isn't already one there.
412        var modalScreen = jQuery('<div />').addClass('modal-screen').appendTo('body');
413
414    }
415
416    jQuery('.foundry_modal').click(function(){
417        jQuery(this).addClass('modal-acknowledged');
418    });
419
420    jQuery(document).on('wheel mousewheel scroll', '.foundry_modal, .modal-screen', function(evt){
421        $(this).get(0).scrollTop += (evt.originalEvent.deltaY); 
422        return false;
423    });
424    
425    $('.modal-container:not([modal-link])').each(function(index) {
426        if(jQuery(this).find('iframe[src]').length){
427        	jQuery(this).find('.foundry_modal').addClass('iframe-modal');
428        	var iframe = jQuery(this).find('iframe');
429        	iframe.attr('data-src',iframe.attr('src'));
430            iframe.attr('src', '');
431
432        }
433        jQuery(this).find('.btn-modal').attr('modal-link', index);
434
435        // Only clone and append to body if there isn't already one there
436        if(!jQuery('.foundry_modal[modal-link="'+index+'"]').length){
437            jQuery(this).find('.foundry_modal').clone().appendTo('body').attr('modal-link', index).prepend(jQuery('<i class="ti-close close-modal">'));
438        }
439    });
440    
441    $('.btn-modal').unbind('click').click(function(){
442    	var linkedModal = jQuery('.foundry_modal[modal-link="' + jQuery(this).attr('modal-link') + '"]'),
443            autoplayMsg = "";
444        jQuery('.modal-screen').toggleClass('reveal-modal');
445        if(linkedModal.find('iframe').length){
446            if(linkedModal.find('iframe').attr('data-autoplay') === '1'){
447                var autoplayMsg = '&autoplay=1'
448            }
449        	linkedModal.find('iframe').attr('src', (linkedModal.find('iframe').attr('data-src') + autoplayMsg));
450        }
451        if(linkedModal.find('video').length){
452            linkedModal.find('video').get(0).play();
453        }
454        linkedModal.toggleClass('reveal-modal');
455        return false; 
456    });
457    
458    // Autoshow modals
459	
460	$('.foundry_modal[data-time-delay]').each(function(){
461		var modal = $(this);
462		var delay = modal.attr('data-time-delay');
463		modal.prepend($('<i class="ti-close close-modal">'));
464    	if(typeof modal.attr('data-cookie') != "undefined"){
465        	if(!mr_cookies.hasItem(modal.attr('data-cookie'))){
466                setTimeout(function(){
467        			modal.addClass('reveal-modal');
468        			$('.modal-screen').addClass('reveal-modal');
469        		},delay);
470            }
471        }else{
472            setTimeout(function(){
473                modal.addClass('reveal-modal');
474                $('.modal-screen').addClass('reveal-modal');
475            },delay);
476        }
477	});
478
479    // Exit modals
480    $('.foundry_modal[data-show-on-exit]').each(function(){
481        var modal = $(this);
482        var exitSelector = $(modal.attr('data-show-on-exit'));
483        // If a valid selector is found, attach leave event to show modal.
484        if($(exitSelector).length){
485            modal.prepend($('<i class="ti-close close-modal">'));
486            $(document).on('mouseleave', exitSelector, function(){
487                if(!$('body .reveal-modal').length){
488                    if(typeof modal.attr('data-cookie') !== typeof undefined){
489                        if(!mr_cookies.hasItem(modal.attr('data-cookie'))){
490                            modal.addClass('reveal-modal');
491                            $('.modal-screen').addClass('reveal-modal');
492                        }
493                    }else{
494                        modal.addClass('reveal-modal');
495                        $('.modal-screen').addClass('reveal-modal');
496                    }
497                }
498            });
499        }
500    });
501
502    // Autoclose modals
503
504    $('.foundry_modal[data-hide-after]').each(function(){
505        var modal = $(this);
506        var delay = modal.attr('data-hide-after');
507        if(typeof modal.attr('data-cookie') != "undefined"){
508            if(!mr_cookies.hasItem(modal.attr('data-cookie'))){
509                setTimeout(function(){
510                if(!modal.hasClass('modal-acknowledged')){
511                    modal.removeClass('reveal-modal');
512                    $('.modal-screen').removeClass('reveal-modal');
513                }
514                },delay); 
515            }
516        }else{
517            setTimeout(function(){
518                if(!modal.hasClass('modal-acknowledged')){
519                    modal.removeClass('reveal-modal');
520                    $('.modal-screen').removeClass('reveal-modal');
521                }
522            },delay); 
523        }
524    });
525    
526    jQuery('.close-modal:not(.modal-strip .close-modal)').unbind('click').click(function(){
527    	var modal = jQuery(this).closest('.foundry_modal');
528        modal.toggleClass('reveal-modal');
529        if(typeof modal.attr('data-cookie') !== "undefined"){
530            mr_cookies.setItem(modal.attr('data-cookie'), "true", Infinity);
531        }
532    	if(modal.find('iframe').length){
533            modal.find('iframe').attr('src', '');
534        }
535        jQuery('.modal-screen').removeClass('reveal-modal');
536    });
537    
538    jQuery('.modal-screen').unbind('click').click(function(){
539        if(jQuery('.foundry_modal.reveal-modal').find('iframe').length){
540            jQuery('.foundry_modal.reveal-modal').find('iframe').attr('src', '');
541        }
542    	jQuery('.foundry_modal.reveal-modal').toggleClass('reveal-modal');
543    	jQuery(this).toggleClass('reveal-modal');
544    });
545    
546    jQuery(document).keyup(function(e) {
547		 if (e.keyCode == 27) { // escape key maps to keycode `27`
548            if(jQuery('.foundry_modal').find('iframe').length){
549                jQuery('.foundry_modal').find('iframe').attr('src', '');
550            }
551			jQuery('.foundry_modal').removeClass('reveal-modal');
552			jQuery('.modal-screen').removeClass('reveal-modal');
553		}
554	});
555    
556    // Modal Strips
557    
558    jQuery('.modal-strip').each(function(){
559    	if(!jQuery(this).find('.close-modal').length){
560    		jQuery(this).append(jQuery('<i class="ti-close close-modal">'));
561    	}
562    	var modal = jQuery(this);
563
564        if(typeof modal.attr('data-cookie') != "undefined"){
565           
566            if(!mr_cookies.hasItem(modal.attr('data-cookie'))){
567            	setTimeout(function(){
568            		modal.addClass('reveal-modal');
569            	},1000);
570            }
571        }else{
572            setTimeout(function(){
573                    modal.addClass('reveal-modal');
574            },1000);
575        }
576    });
577    
578    jQuery('.modal-strip .close-modal').click(function(){
579        var modal = jQuery(this).closest('.modal-strip');
580        if(typeof modal.attr('data-cookie') != "undefined"){
581            mr_cookies.setItem(modal.attr('data-cookie'), "true", Infinity);
582        }
583    	jQuery(this).closest('.modal-strip').removeClass('reveal-modal');
584    	return false;
585    });
586
587
588    // Video Modals
589
590    jQuery('.close-iframe').click(function() {
591        jQuery(this).closest('.modal-video').removeClass('reveal-modal');
592        jQuery(this).siblings('iframe').attr('src', '');
593        jQuery(this).siblings('video').get(0).pause();
594    });
595
596    // Checkboxes
597
598    $('.checkbox-option').on("click",function() {
599        $(this).toggleClass('checked');
600        var checkbox = $(this).find('input');
601        if (checkbox.prop('checked') === false) {
602            checkbox.prop('checked', true);
603        } else {
604            checkbox.prop('checked', false);
605        }
606    });
607
608    // Radio Buttons
609
610    $('.radio-option').click(function() {
611
612        var checked = $(this).hasClass('checked'); // Get the current status of the radio
613
614        var name = $(this).find('input').attr('name'); // Get the name of the input clicked
615
616        if (!checked) {
617
618            $('input[name="'+name+'"]').parent().removeClass('checked');
619
620            $(this).addClass('checked');
621
622            $(this).find('input').prop('checked', true);
623
624        }
625
626    });
627
628
629    // Accordions
630
631    $('.accordion li').click(function() {
632        if ($(this).closest('.accordion').hasClass('one-open')) {
633            $(this).closest('.accordion').find('li').removeClass('active');
634            $(this).addClass('active');
635        } else {
636            $(this).toggleClass('active');
637        }
638        if(typeof window.mr_parallax !== "undefined"){
639            setTimeout(mr_parallax.windowLoad, 500);
640        }
641    });
642
643    // Tabbed Content
644
645    $('.tabbed-content').each(function() {
646        $(this).append('<ul class="content"></ul>');
647    });
648
649    $('.tabs li').each(function() {
650        var originalTab = $(this),
651            activeClass = "";
652        if (originalTab.is('.tabs>li:first-child')) {
653            activeClass = ' class="active"';
654        }
655        var tabContent = originalTab.find('.tab-content').detach().wrap('<li' + activeClass + '></li>').parent();
656        originalTab.closest('.tabbed-content').find('.content').append(tabContent);
657    });
658
659    $('.tabs li').click(function() {
660        $(this).closest('.tabs').find('li').removeClass('active');
661        $(this).addClass('active');
662        var liIndex = $(this).index() + 1;
663        $(this).closest('.tabbed-content').find('.content>li').removeClass('active');
664        $(this).closest('.tabbed-content').find('.content>li:nth-of-type(' + liIndex + ')').addClass('active');
665    });
666
667    // Local Videos
668
669    $('section').closest('body').find('.local-video-container .play-button').click(function() {
670        $(this).siblings('.background-image-holder').removeClass('fadeIn');
671        $(this).siblings('.background-image-holder').css('z-index', -1);
672        $(this).css('opacity', 0);
673        $(this).siblings('video').get(0).play();
674    });
675
676    // Youtube Videos
677
678    $('section').closest('body').find('.player').each(function() {
679        var section = $(this).closest('section');
680        section.find('.container').addClass('fadeOut');
681        var src = $(this).attr('data-video-id');
682        var startat = $(this).attr('data-start-at');
683        $(this).attr('data-property', "{videoURL:'http://youtu.be/" + src + "',containment:'self',autoPlay:true, mute:true, startAt:" + startat + ", opacity:1, showControls:false}");
684    });
685
686	if($('.player').length){
687        $('.player').each(function(){
688
689            var section = $(this).closest('section');
690            var player = section.find('.player');
691            player.YTPlayer();
692            player.on("YTPStart",function(e){
693                section.find('.container').removeClass('fadeOut');
694                section.find('.masonry-loader').addClass('fadeOut');
695            });
696
697        });
698    }
699
700    // Interact with Map once the user has clicked (to prevent scrolling the page = zooming the map
701
702    $('.map-holder').click(function() {
703        $(this).addClass('interact');
704    });
705    
706    if($('.map-holder').length){
707    	$(window).scroll(function() {
708			if ($('.map-holder.interact').length) {
709				$('.map-holder.interact').removeClass('interact');
710			}
711		});
712    }
713    
714    // Countdown Timers
715
716    if ($('.countdown').length) {
717        $('.countdown').each(function() {
718            var date = $(this).attr('data-date');
719            $(this).countdown(date, function(event) {
720                $(this).text(
721                    event.strftime('%D days %H:%M:%S')
722                );
723            });
724        });
725    }
726    
727    //                                                            //
728    //                                                            //
729    // Contact form code                                          //
730    //                                                            //
731    //                                                            //
732
733    $('form.form-email, form.form-newsletter').submit(function(e) {
734
735        // return false so form submits through jQuery rather than reloading page.
736        if (e.preventDefault) e.preventDefault();
737        else e.returnValue = false;
738
739        var thisForm = $(this).closest('form.form-email, form.form-newsletter'),
740            submitButton = thisForm.find('button[type="submit"]'),
741            error = 0,
742            originalError = thisForm.attr('original-error'),
743            preparedForm, iFrame, userEmail, userFullName, userFirstName, userLastName, successRedirect, formError, formSuccess;
744
745        // Mailchimp/Campaign Monitor Mail List Form Scripts
746        iFrame = $(thisForm).find('iframe.mail-list-form');
747
748        thisForm.find('.form-error, .form-success').remove();
749        submitButton.attr('data-text', submitButton.text());
750        thisForm.append('<div class="form-error" style="display: none;">' + thisForm.attr('data-error') + '</div>');
751        thisForm.append('<div class="form-success" style="display: none;">' + thisForm.attr('data-success') + '</div>');
752        formError = thisForm.find('.form-error');
753        formSuccess = thisForm.find('.form-success');
754        thisForm.addClass('attempted-submit');
755
756        // Do this if there is an iframe, and it contains usable Mail Chimp / Campaign Monitor iframe embed code
757        if ((iFrame.length) && (typeof iFrame.attr('srcdoc') !== "undefined") && (iFrame.attr('srcdoc') !== "")) {
758
759            console.log('Mail list form signup detected.');
760            if (typeof originalError !== typeof undefined && originalError !== false) {
761                formError.html(originalError);
762            }
763            userEmail = $(thisForm).find('.signup-email-field').val();
764            userFullName = $(thisForm).find('.signup-name-field').val();
765            if ($(thisForm).find('input.signup-first-name-field').length) {
766                userFirstName = $(thisForm).find('input.signup-first-name-field').val();
767            } else {
768                userFirstName = $(thisForm).find('.signup-name-field').val();
769            }
770            userLastName = $(thisForm).find('.signup-last-name-field').val();
771
772            // validateFields returns 1 on error;
773            if (validateFields(thisForm) !== 1) {
774                preparedForm = prepareSignup(iFrame);
775
776                preparedForm.find('#mce-EMAIL, #fieldEmail').val(userEmail);
777                preparedForm.find('#mce-LNAME, #fieldLastName').val(userLastName);
778                preparedForm.find('#mce-FNAME, #fieldFirstName').val(userFirstName);
779                preparedForm.find('#mce-NAME, #fieldName').val(userFullName);
780                thisForm.removeClass('attempted-submit');
781
782                // Hide the error if one was shown
783                formError.fadeOut(200);
784                // Create a new loading spinner in the submit button.
785                submitButton.html(jQuery('<div />').addClass('form-loading')).attr('disabled', 'disabled');
786                
787                try{
788                    $.ajax({
789                        url: preparedForm.attr('action'),
790                        crossDomain: true,
791                        data: preparedForm.serialize(),
792                        method: "GET",
793                        cache: false,
794                        dataType: 'json',
795                        contentType: 'application/json; charset=utf-8',
796                        success: function(data){
797                            // Request was a success, what was the response?
798                            if (data.result != "success" && data.Status != 200) {
799                                
800                                // Error from Mail Chimp or Campaign Monitor
801
802                                // Keep the current error text in a data attribute on the form
803                                formError.attr('original-error', formError.text());
804                                // Show the error with the returned error text.
805                                formError.html(data.msg).fadeIn(1000);
806                                formSuccess.fadeOut(1000);
807
808                                submitButton.html(submitButton.attr('data-text')).removeAttr('disabled');
809                            } else {
810                                
811                                // Got Success from Mail Chimp
812                                
813                                submitButton.html(submitButton.attr('data-text')).removeAttr('disabled');
814
815                                successRedirect = thisForm.attr('success-redirect');
816                                // For some browsers, if empty `successRedirect` is undefined; for others,
817                                // `successRedirect` is false.  Check for both.
818                                if (typeof successRedirect !== typeof undefined && successRedirect !== false && successRedirect !== "") {
819                                    window.location = successRedirect;
820                                }
821
822                                thisForm.find('input[type="text"]').val("");
823                                thisForm.find('textarea').val("");
824                                formSuccess.fadeIn(1000);
825
826                                formError.fadeOut(1000);
827                                setTimeout(function() {
828                                    formSuccess.fadeOut(500);
829                                }, 5000);
830                            }
831                        }
832                    });
833                }catch(err){
834                    // Keep the current error text in a data attribute on the form
835                    formError.attr('original-error', formError.text());
836                    // Show the error with the returned error text.
837                    formError.html(err.message).fadeIn(1000);
838                    formSuccess.fadeOut(1000);
839                    setTimeout(function() {
840                        formError.fadeOut(500);
841                    }, 5000);
842
843                    submitButton.html(submitButton.attr('data-text')).removeAttr('disabled');
844                }
845            
846
847                
848            } else {
849                formError.fadeIn(1000);
850                setTimeout(function() {
851                    formError.fadeOut(500);
852                }, 5000);
853            }
854        } else {
855            // If no iframe detected then this is treated as an email form instead.
856            console.log('Send email form detected.');
857            if (typeof originalError !== typeof undefined && originalError !== false) {
858                formError.text(originalError);
859            }
860
861            error = validateFields(thisForm);
862
863            if (error === 1) {
864                formError.fadeIn(200);
865                setTimeout(function() {
866                    formError.fadeOut(500);
867                }, 3000);
868            } else {
869
870                thisForm.removeClass('attempted-submit');
871
872                // Hide the error if one was shown
873                formError.fadeOut(200);
874                
875                // Create a new loading spinner in the submit button.
876                submitButton.html(jQuery('<div />').addClass('form-loading')).attr('disabled', 'disabled');
877
878                jQuery.ajax({
879                    type: "POST",
880                    url: "mail/mail.php",
881                    data: thisForm.serialize()+"&url="+window.location.href,
882                    success: function(response) {
883                        // Swiftmailer always sends back a number representing numner of emails sent.
884                        // If this is numeric (not Swift Mailer error text) AND greater than 0 then show success message.
885
886                        submitButton.html(submitButton.attr('data-text')).removeAttr('disabled');
887
888                        if ($.isNumeric(response)) {
889                            if (parseInt(response) > 0) {
890                                // For some browsers, if empty 'successRedirect' is undefined; for others,
891                                // 'successRedirect' is false.  Check for both.
892                                successRedirect = thisForm.attr('success-redirect');
893                                if (typeof successRedirect !== typeof undefined && successRedirect !== false && successRedirect !== "") {
894                                    window.location = successRedirect;
895                                }
896
897
898                                thisForm.find('input[type="text"]').val("");
899                                thisForm.find('textarea').val("");
900                                thisForm.find('.form-success').fadeIn(1000);
901
902                                formError.fadeOut(1000);
903                                setTimeout(function() {
904                                    formSuccess.fadeOut(500);
905                                }, 5000);
906                            }
907                        }
908                        // If error text was returned, put the text in the .form-error div and show it.
909                        else {
910                            // Keep the current error text in a data attribute on the form
911                            formError.attr('original-error', formError.text());
912                            // Show the error with the returned error text.
913                            formError.text(response).fadeIn(1000);
914                            formSuccess.fadeOut(1000);
915                        }
916                    },
917                    error: function(errorObject, errorText, errorHTTP) {
918                        // Keep the current error text in a data attribute on the form
919                        formError.attr('original-error', formError.text());
920                        // Show the error with the returned error text.
921                        formError.text(errorHTTP).fadeIn(1000);
922                        formSuccess.fadeOut(1000);
923                        submitButton.html(submitButton.attr('data-text')).removeAttr('disabled');
924                    }
925                });
926            }
927        }
928        return false;
929    });
930
931    $('.validate-required, .validate-email').on('blur change', function() {
932        validateFields($(this).closest('form'));
933    });
934
935    $('form').each(function() {
936        if ($(this).find('.form-error').length) {
937            $(this).attr('original-error', $(this).find('.form-error').text());
938        }
939    });
940
941    function validateFields(form) {
942            var name, error, originalErrorMessage;
943
944            $(form).find('.validate-required[type="checkbox"]').each(function() {
945                if (!$('[name="' + $(this).attr('name') + '"]:checked').length) {
946                    error = 1;
947                    name = $(this).attr('name').replace('[]', '');
948                    form.find('.form-error').text('Please tick at least one ' + name + ' box.');
949                }
950            });
951
952            $(form).find('.validate-required').each(function() {
953                if ($(this).val() === '') {
954                    $(this).addClass('field-error');
955                    error = 1;
956                } else {
957                    $(this).removeClass('field-error');
958                }
959            });
960
961            $(form).find('.validate-email').each(function() {
962                if (!(/(.+)@(.+){2,}\.(.+){2,}/.test($(this).val()))) {
963                    $(this).addClass('field-error');
964                    error = 1;
965                } else {
966                    $(this).removeClass('field-error');
967                }
968            });
969
970            if (!form.find('.field-error').length) {
971                form.find('.form-error').fadeOut(1000);
972            }
973
974            return error;
975        }
976
977    //
978    //    
979    // End contact form code
980    //
981    //
982
983
984    // Get referrer from URL string 
985    if (getURLParameter("ref")) {
986        $('form.form-email').append('<input type="text" name="referrer" class="hidden" value="' + getURLParameter("ref") + '"/>');
987    }
988
989    function getURLParameter(name) {
990        return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search) || [, ""])[1].replace(/\+/g, '%20')) || null;
991    }
992
993    // Disable parallax on mobile
994
995    if ((/Android|iPhone|iPad|iPod|BlackBerry|Windows Phone/i).test(navigator.userAgent || navigator.vendor || window.opera)) {
996        $('section').removeClass('parallax');
997    }
998    
999    // Disqus Comments
1000    
1001    if($('.disqus-comments').length){
1002		/* * * CONFIGURATION VARIABLES * * */
1003		var disqus_shortname = $('.disqus-comments').attr('data-shortname');
1004
1005		/* * * DON'T EDIT BELOW THIS LINE * * */
1006		(function() {
1007			var dsq = document.createElement('script'); dsq.type = 'text/javascript'; dsq.async = true;
1008			dsq.src = '//' + disqus_shortname + '.disqus.com/embed.js';
1009			(document.getElementsByTagName('head')[0] || document.getElementsByTagName('body')[0]).appendChild(dsq);
1010		})();
1011    }
1012
1013    // Load Google MAP API JS with callback to initialise when fully loaded
1014    if(document.querySelector('[data-maps-api-key]') && !document.querySelector('.gMapsAPI')){
1015        if($('[data-maps-api-key]').length){
1016            var script = document.createElement('script');
1017            var apiKey = $('[data-maps-api-key]:first').attr('data-maps-api-key');
1018            script.type = 'text/javascript';
1019            script.src = 'https://maps.googleapis.com/maps/api/js?key='+apiKey+'&callback=initializeMaps';
1020            script.className = 'gMapsAPI';
1021            document.body.appendChild(script);  
1022        } 
1023    }
1024
1025}); 
1026
1027$(window).on("load", function() { 
1028    "use strict";
1029
1030    // Initialize Masonry
1031
1032    setTimeout(initializeMasonry, 1000);
1033   
1034
1035    mr_firstSectionHeight = $('.main-container section:nth-of-type(1)').outerHeight(true);
1036
1037
1038}); 
1039function updateNav() {
1040
1041    var scrollY = mr_scrollTop;
1042
1043    if (scrollY <= 0) {
1044        if (mr_navFixed) {
1045            mr_navFixed = false;
1046            mr_nav.removeClass('fixed');
1047        }
1048        if (mr_outOfSight) {
1049            mr_outOfSight = false;
1050            mr_nav.removeClass('outOfSight');
1051        }
1052        if (mr_navScrolled) {
1053            mr_navScrolled = false;
1054            mr_nav.removeClass('scrolled');
1055        }
1056        return;
1057    }
1058
1059    if (scrollY > mr_navOuterHeight + mr_fixedAt) {
1060        if (!mr_navScrolled) {
1061            mr_nav.addClass('scrolled');
1062            mr_navScrolled = true;
1063            return;
1064        }
1065    } else {
1066        if (scrollY > mr_navOuterHeight) {
1067           if (!mr_navFixed) {
1068                mr_nav.addClass('fixed');
1069                mr_navFixed = true;
1070            }
1071
1072            if (scrollY > mr_navOuterHeight +10) {
1073                if (!mr_outOfSight) {
1074                    mr_nav.addClass('outOfSight');
1075                    mr_outOfSight = true;
1076                }
1077            } else {
1078                if (mr_outOfSight) {
1079                    mr_outOfSight = false;
1080                    mr_nav.removeClass('outOfSight');
1081                }
1082            }
1083        } else {
1084            if (mr_navFixed) {
1085                mr_navFixed = false;
1086                mr_nav.removeClass('fixed');
1087            }
1088            if (mr_outOfSight) {
1089                mr_outOfSight = false;
1090                mr_nav.removeClass('outOfSight');
1091            }
1092        }
1093
1094        if (mr_navScrolled) {
1095            mr_navScrolled = false;
1096            mr_nav.removeClass('scrolled');
1097        }
1098
1099    }
1100}
1101
1102
1103function capitaliseFirstLetter(string) {
1104    return string.charAt(0).toUpperCase() + string.slice(1);
1105}
1106
1107function initializeMasonry(){
1108    $('.masonry').each(function(){
1109        var container = $(this).get(0);
1110        var msnry = new Masonry(container, {
1111            itemSelector: '.masonry-item'
1112        });
1113
1114        msnry.on('layoutComplete', function() {
1115
1116            mr_firstSectionHeight = $('.main-container section:nth-of-type(1)').outerHeight(true);
1117
1118            // Fix floating project filters to bottom of projects container
1119
1120            if ($('.filters.floating').length) {
1121                setupFloatingProjectFilters();
1122                updateFloatingFilters();
1123                window.addEventListener("scroll", updateFloatingFilters, false);
1124            }
1125
1126            $('.masonry').addClass('fadeIn');
1127            $('.masonry-loader').addClass('fadeOut');
1128            if ($('.masonryFlyIn').length) {
1129                masonryFlyIn();
1130            }
1131        });
1132
1133        msnry.layout();
1134    });
1135}
1136
1137function masonryFlyIn() {
1138    var $items = $('.masonryFlyIn .masonry-item');
1139    var time = 0;
1140
1141    $items.each(function() {
1142        var item = $(this);
1143        setTimeout(function() {
1144            item.addClass('fadeIn');
1145        }, time);
1146        time += 170;
1147    });
1148}
1149
1150function setupFloatingProjectFilters() {
1151    mr_floatingProjectSections = [];
1152    $('.filters.floating').closest('section').each(function() {
1153        var section = $(this);
1154
1155        mr_floatingProjectSections.push({
1156            section: section.get(0),
1157            outerHeight: section.outerHeight(),
1158            elemTop: section.offset().top,
1159            elemBottom: section.offset().top + section.outerHeight(),
1160            filters: section.find('.filters.floating'),
1161            filersHeight: section.find('.filters.floating').outerHeight(true)
1162        });
1163    });
1164}
1165
1166function updateFloatingFilters() {
1167    var l = mr_floatingProjectSections.length;
1168    while (l--) {
1169        var section = mr_floatingProjectSections[l];
1170
1171        if ((section.elemTop < mr_scrollTop) && typeof window.mr_variant == "undefined" ) {
1172            section.filters.css({
1173                position: 'fixed',
1174                top: '16px',
1175                bottom: 'auto'
1176            });
1177            if (mr_navScrolled) {
1178                section.filters.css({
1179                    transform: 'translate3d(-50%,48px,0)'
1180                });
1181            }
1182            if (mr_scrollTop > (section.elemBottom - 70)) {
1183                section.filters.css({
1184                    position: 'absolute',
1185                    bottom: '16px',
1186                    top: 'auto'
1187                });
1188                section.filters.css({
1189                    transform: 'translate3d(-50%,0,0)'
1190                });
1191            }
1192        } else {
1193            section.filters.css({
1194                position: 'absolute',
1195                transform: 'translate3d(-50%,0,0)'
1196            });
1197        }
1198    }
1199}
1200
1201window.initializeMaps = function(){
1202    if(typeof google !== "undefined"){
1203        if(typeof google.maps !== "undefined"){
1204            $('.map-canvas[data-maps-api-key]').each(function(){
1205                    var mapInstance   = this,
1206                        mapJSON       = typeof $(this).attr('data-map-style') !== "undefined" ? $(this).attr('data-map-style'): false,
1207                        mapStyle      = JSON.parse(mapJSON) || [{"featureType":"landscape","stylers":[{"saturation":-100},{"lightness":65},{"visibility":"on"}]},{"featureType":"poi","stylers":[{"saturation":-100},{"lightness":51},{"visibility":"simplified"}]},{"featureType":"road.highway","stylers":[{"saturation":-100},{"visibility":"simplified"}]},{"featureType":"road.arterial","stylers":[{"saturation":-100},{"lightness":30},{"visibility":"on"}]},{"featureType":"road.local","stylers":[{"saturation":-100},{"lightness":40},{"visibility":"on"}]},{"featureType":"transit","stylers":[{"saturation":-100},{"visibility":"simplified"}]},{"featureType":"administrative.province","stylers":[{"visibility":"off"}]},{"featureType":"water","elementType":"labels","stylers":[{"visibility":"on"},{"lightness":-25},{"saturation":-100}]},{"featureType":"water","elementType":"geometry","stylers":[{"hue":"#ffff00"},{"lightness":-25},{"saturation":-97}]}],
1208                        zoomLevel     = (typeof $(this).attr('data-map-zoom') !== "undefined" && $(this).attr('data-map-zoom') !== "") ? $(this).attr('data-map-zoom') * 1: 17,
1209                        latlong       = typeof $(this).attr('data-latlong') != "undefined" ? $(this).attr('data-latlong') : false,
1210                        latitude      = latlong ? 1 *latlong.substr(0, latlong.indexOf(',')) : false,
1211                        longitude     = latlong ? 1 * latlong.substr(latlong.indexOf(",") + 1) : false,
1212                        geocoder      = new google.maps.Geocoder(),
1213                        address       = typeof $(this).attr('data-address') !== "undefined" ? $(this).attr('data-address').split(';'): [""],
1214                        markerTitle   = "We Are Here",
1215                        isDraggable = $(document).width() > 766 ? true : false,
1216                        map, marker, markerImage,
1217                        mapOptions = {
1218                            draggable: isDraggable,
1219                            scrollwheel: false,
1220                            zoom: zoomLevel,
1221                            disableDefaultUI: true,
1222                            styles: mapStyle
1223                        };
1224
1225                    if($(this).attr('data-marker-title') != undefined && $(this).attr('data-marker-title') != "" )
1226                    {
1227                        markerTitle = $(this).attr('data-marker-title');
1228                    }
1229
1230                    if(address != undefined && address[0] != ""){
1231                            geocoder.geocode( { 'address': address[0].replace('[nomarker]','')}, function(results, status) {
1232                                if (status == google.maps.GeocoderStatus.OK) {
1233                                var map = new google.maps.Map(mapInstance, mapOptions); 
1234                                map.setCenter(results[0].geometry.location);
1235                                
1236                                address.forEach(function(address){
1237                                    var markerGeoCoder;
1238                                    
1239                                    markerImage = {url: window.mr_variant == undefined ? 'img/mapmarker.png' : '../img/mapmarker.png', size: new google.maps.Size(50,50), scaledSize: new google.maps.Size(50,50)};
1240                                    if(/(\-?\d+(\.\d+)?),\s*(\-?\d+(\.\d+)?)/.test(address) ){
1241                                        var latlong = address.split(','),
1242                                        marker = new google.maps.Marker({
1243                                                        position: { lat: 1*latlong[0], lng: 1*latlong[1] },
1244                                                        map: map,
1245                                                        icon: markerImage,
1246                                                        title: markerTitle,
1247                                                        optimised: fal
1247se
1248                                                    });
1249                                    }
1250                                    else if(address.indexOf('[nomarker]') < 0){
1251                                        markerGeoCoder = new google.maps.Geocoder();
1252                                        markerGeoCoder.geocode( { 'address': address.replace('[nomarker]','')}, function(results, status) {
1253                                            if (status == google.maps.GeocoderStatus.OK) {
1254                                                marker = new google.maps.Marker({
1255                                                    map: map,
1256                                                    icon: markerImage,
1257                                                    title: markerTitle,
1258                                                    position: results[0].geometry.location,
1259                                                    optimised: false
1260                                                });
1261                                            }
1262                                        });
1263                                    }
1264
1265                                });
1266                            } else {
1267                                console.log('There was a problem geocoding the address.');
1268                            }
1269                        });
1270                    }
1271                    else if(latitude != undefined && latitude != "" && latitude != false && longitude != undefined && longitude != "" && longitude != false ){
1272                        mapOptions.center   = { lat: latitude, lng: longitude};
1273                        map = new google.maps.Map(mapInstance, mapOptions); 
1274                        marker              = new google.maps.Marker({
1275                                                    position: { lat: latitude, lng: longitude },
1276                                                    map: map,
1277                                                    icon: markerImage,
1278                                                    title: markerTitle
1279                                                });
1280
1281                    }
1282
1283                }); 
1284        }
1285    }
1286}
1287initializeMaps();
1288
1289// End of Maps
1290
1291
1292
1293
1294// Prepare Signup Form - It is used to retrieve form details from an iframe Mail Chimp or Campaign Monitor form.
1295
1296function prepareSignup(iFrame){
1297    var form   = jQuery('<form />'),
1298        div    = jQuery('<div />'),
1299        action;
1300
1301    jQuery(div).html(iFrame.attr('srcdoc'));
1302    action = jQuery(div).find('form').attr('action');
1303
1304
1305
1306    // Alter action for a Mail Chimp-compatible ajax request url.
1307    if(/list-manage\.com/.test(action)){
1308       action = action.replace('/post?', '/post-json?') + "&c=?";
1309       if(action.substr(0,2) == "//"){
1310           action = 'http:' + action;
1311       }
1312    }
1313
1314    // Alter action for a Campaign Monitor-compatible ajax request url.
1315    if(/createsend\.com/.test(action)){
1316       action = action + '?callback=?';
1317    }
1318
1319
1320    // Set action on the form
1321    form.attr('action', action);
1322
1323    // Clone form input fields from 
1324    jQuery(div).find('input, select, textarea').not('input[type="submit"]').each(function(){
1325        jQuery(this).clone().appendTo(form);
1326
1327    });
1328
1329    return form;
1330        
1331
1332}
1333
1334
1335
1336/*\
1337|*|  COOKIE LIBRARY THANKS TO MDN
1338|*|
1339|*|  A complete cookies reader/writer framework with full unicode support.
1340|*|
1341|*|  Revision #1 - September 4, 2014
1342|*|
1343|*|  https://developer.mozilla.org/en-US/docs/Web/API/document.cookie
1344|*|  https://developer.mozilla.org/User:fusionchess
1345|*|
1346|*|  This framework is released under the GNU Public License, version 3 or later.
1347|*|  http://www.gnu.org/licenses/gpl-3.0-standalone.html
1348|*|
1349|*|  Syntaxes:
1350|*|
1351|*|  * mr_cookies.setItem(name, value[, end[, path[, domain[, secure]]]])
1352|*|  * mr_cookies.getItem(name)
1353|*|  * mr_cookies.removeItem(name[, path[, domain]])
1354|*|  * mr_cookies.hasItem(name)
1355|*|  * mr_cookies.keys()
1356|*|
1357\*/
1358
1359var mr_cookies = {
1360  getItem: function (sKey) {
1361    if (!sKey) { return null; }
1362    return decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")) || null;
1363  },
1364  setItem: function (sKey, sValue, vEnd, sPath, sDomain, bSecure) {
1365    if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) { return false; }
1366    var sExpires = "";
1367    if (vEnd) {
1368      switch (vEnd.constructor) {
1369        case Number:
1370          sExpires = vEnd === Infinity ? "; expires=Fri, 31 Dec 9999 23:59:59 GMT" : "; max-age=" + vEnd;
1371          break;
1372        case String:
1373          sExpires = "; expires=" + vEnd;
1374          break;
1375        case Date:
1376          sExpires = "; expires=" + vEnd.toUTCString();
1377          break;
1378      }
1379    }
1380    document.cookie = encodeURIComponent(sKey) + "=" + encodeURIComponent(sValue) + sExpires + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "") + (bSecure ? "; secure" : "");
1381    return true;
1382  },
1383  removeItem: function (sKey, sPath, sDomain) {
1384    if (!this.hasItem(sKey)) { return false; }
1385    document.cookie = encodeURIComponent(sKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT" + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "");
1386    return true;
1387  },
1388  hasItem: function (sKey) {
1389    if (!sKey) { return false; }
1390    return (new RegExp("(?:^|;\\s*)" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=")).test(document.cookie);
1391  },
1392  keys: function () {
1393    var aKeys = document.cookie.replace(/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g, "").split(/\s*(?:\=[^;]*)?;\s*/);
1394    for (var nLen = aKeys.length, nIdx = 0; nIdx < nLen; nIdx++) { aKeys[nIdx] = decodeURIComponent(aKeys[nIdx]); }
1395    return aKeys;
1396  }
1397};
1398
1399/*\
1400|*|  END COOKIE LIBRARY
1401\*/
1402
1403

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.