PageSourceSearch

https://www.shimoda-yamatokan.co.jp/english/js/scripts.js

js shimoda-yamatokan.co.jp collected 2026-10-02 16:35:19 UTC 102,296 bytes, 2,789 lines download raw bytes

1
2var mr = (function ($, window, document){
3    "use strict";
4
5    var mr         = {},
6        components = {documentReady: [],documentReadyDeferred: [], windowLoad: [], windowLoadDeferred: []};
7
8
9    $(document).ready(documentReady);
10    $(window).on("load", windowLoad);
11
12    function documentReady(context){
13        
14        context = typeof context === typeof undefined ? $ : context;
15        components.documentReady.concat(components.documentReadyDeferred).forEach(function(component){
16            component(context);
17        });
18    }
19
20    function windowLoad(context){
21        
22        context = typeof context === "object" ? $ : context;
23        components.windowLoad.concat(components.windowLoadDeferred).forEach(function(component){
24           component(context);
25        });
26    }
27
28    mr.setContext = function (contextSelector){
29        var context = $;
30        if(typeof contextSelector !== typeof undefined){
31            return function(selector){
32                return $(contextSelector).find(selector);
33            };
34        }
35        return context;
36    };
37
38    mr.components    = components;
39    mr.documentReady = documentReady;
40    mr.windowLoad    = windowLoad;
41
42    return mr;
43}(jQuery, window, document));
44
45
46//////////////// Utility Functions
47mr = (function (mr, $, window, document){
48    "use strict";
49    mr.util = {};
50
51    mr.util.requestAnimationFrame    = window.requestAnimationFrame || 
52                                       window.mozRequestAnimationFrame || 
53                                       window.webkitRequestAnimationFrame ||
54                                       window.msRequestAnimationFrame;
55
56    mr.util.documentReady = function($){
57        var today = new Date();
58        var year = today.getFullYear();
59        $('.update-year').text(year);
60    };
61
62    mr.util.windowLoad = function($){
63        $('[data-delay-src]').each(function(){
64            var $el = $(this);
65            $el.attr('src', $el.attr('data-delay-src'));
66            $el.removeAttr('data-delay-src');
67        });
68    };
69
70    mr.util.getURLParameter = function(name) {
71        return decodeURIComponent((new RegExp('[?|&]' + name + '=' + '([^&;]+?)(&|#|;|$)').exec(location.search) || [undefined, ""])[1].replace(/\+/g, '%20')) || null;
72    };
73
74
75    mr.util.capitaliseFirstLetter = function(string) {
76        return string.charAt(0).toUpperCase() + string.slice(1);
77    };
78
79    mr.util.slugify = function(text, spacesOnly){
80        if(typeof spacesOnly !== typeof undefined){
81            return text.replace(/ +/g, '');
82        }else{
83            return text
84                .toLowerCase()
85                .replace(/[\~\!\@\#\$\%\^\&\*\(\)\-\_\=\+\]\[\}\{\'\"\;\\\:\?\/\>\<\.\,]+/g, '')
86                .replace(/ +/g, '-');
87        }
88    };
89
90    mr.util.sortChildrenByText = function(parentElement, reverse){
91        var $parentElement = $(parentElement);
92        var items          = $parentElement.children().get();
93        var order          = -1;
94        var order2         = 1;
95        if(typeof reverse !== typeof undefined){order = 1; order2 = -1;}
96
97        items.sort(function(a,b){
98          var keyA = $(a).text();
99          var keyB = $(b).text();
100
101          if (keyA < keyB) return order;
102          if (keyA > keyB) return order2;
103          return 0;
104        });
105        
106        // Append back into place
107        $parentElement.empty();
108        $(items).each(function(i, itm){
109          $parentElement.append(itm);
110        });
111    };
112    
113    // Set data-src attribute of element from src to be restored later
114    mr.util.idleSrc = function(context, selector){
115        
116            selector  = (typeof selector !== typeof undefined) ? selector : '';
117            var elems = context.is(selector+'[src]') ? context : context.find(selector+'[src]');
118
119        elems.each(function(index, elem){
120            elem           = $(elem);
121            var currentSrc = elem.attr('src'),
122                dataSrc    = elem.attr('data-src');
123
124            // If there is no data-src, save current source to it
125            if(typeof dataSrc === typeof undefined){
126                elem.attr('data-src', currentSrc);
127            }
128
129            // Clear the src attribute
130            elem.attr('src', '');    
131            
132        });
133    };
134
135    // Set src attribute of element from its data-src where it was temporarily stored earlier
136    mr.util.activateIdleSrc = function(context, selector){
137        
138        selector     = (typeof selector !== typeof undefined) ? selector : '';
139        var elems    = context.is(selector+'[src]') ? context : context.find(selector+'[src]');
140
141        elems.each(function(index, elem){
142            elem = $(elem);
143            var dataSrc    = elem.attr('data-src');
144
145            // If there is no data-src, save current source to it
146            if(typeof dataSrc !== typeof undefined){
147                elem.attr('src', dataSrc);
148            }
149        });
150    };
151
152    mr.util.pauseVideo = function(context){
153        var elems = context.is('video') ? context : context.find('video');
154
155        elems.each(function(index, video){
156            var playingVideo = $(video).get(0);
157            playingVideo.pause();
158        });
159    };
160
161    // Take a text value in either px (eg. 150px) or vh (eg. 65vh) and return a number in pixels.
162    mr.util.parsePixels = function(text){
163        var windowHeight = $(window).height(), value;
164        
165        // Text text against regular expression for px value.
166        if(/^[1-9]{1}[0-9]*[p][x]$/.test(text)){
167            return parseInt(text.replace('px', ''),10);
168        }
169        // Otherwise it is vh value.
170        else if(/^[1-9]{1}[0-9]*[v][h]$/.test(text)){
171            value = parseInt(text.replace('vh', ''),10);
172            // Return conversion to percentage of window height.
173            return windowHeight * (value/100);
174        }else{
175            // If it is not proper text, return -1 to indicate bad value.
176            return -1;
177        }
178    };
179
180    mr.components.documentReady.push(mr.util.documentReady);
181    mr.components.windowLoad.push(mr.util.windowLoad);
182    return mr;
183
184}(mr, jQuery, window, document));
185
186//////////////// Window Functions
187mr = (function (mr, $, window, document){
188    "use strict";
189
190    mr.window = {};
191    mr.window.height = $(window).height();
192    mr.window.width = $(window).width();
193
194    $(window).on('resize',function(){
195        mr.window.height = $(window).height();
196        mr.window.width = $(window).width();
197    });
198
199    return mr;
200}(mr, jQuery, window, document));
201
202
203//////////////// Scroll Functions
204mr = (function (mr, $, window, document){
205    "use strict";
206
207    
208    mr.scroll           = {};
209    var raf             = window.requestAnimationFrame || 
210                          window.mozRequestAnimationFrame || 
211                          window.webkitRequestAnimationFrame ||
212                          window.msRequestAnimationFrame;
213    mr.scroll.listeners = [];
214    mr.scroll.busy      = false;
215    mr.scroll.y         = 0;
216    mr.scroll.x         = 0;
217    
218    var documentReady = function($){
219
220        //////////////// Capture Scroll Event and fire scroll function
221        jQuery(window).off('scroll.mr');    
222        jQuery(window).on('scroll.mr', function(evt) {
223                if(mr.scroll.busy === false){
224                    
225                    mr.scroll.busy = true;
226                    raf(function(evt){  
227                        mr.scroll.update(evt);
228                    });
229                    
230                }
231                if(evt.stopPropagation){
232                    evt.stopPropagation();
233                }
234        });
235        
236    };
237
238    mr.scroll.update = function(event){
239        
240        // Loop through all mr scroll listeners
241        var parallax = typeof window.mr_parallax !== typeof undefined ? true : false;
242        mr.scroll.y = (parallax ? mr_parallax.mr_getScrollPosition() : window.pageYOffset);
243        mr.scroll.busy = false;
244        if(parallax){
245            mr_parallax.mr_parallaxBackground();
246        }
247
248
249        if(mr.scroll.listeners.length > 0){
250            for (var i = 0, l = mr.scroll.listeners.length; i < l; i++) {
251               mr.scroll.listeners[i](event);
252            }
253        }
254        
255    };
256
257    mr.scroll.documentReady = documentReady;
258
259    mr.components.documentReady.push(documentReady);
260
261    return mr;
262
263}(mr, jQuery, window, document));
264
265
266//////////////// Scroll Class Modifier
267mr = (function (mr, $, window, document){
268    "use strict";
269
270    mr.scroll.classModifiers = {};
271    // Globally accessible list of elements/rules
272    mr.scroll.classModifiers.rules = [];
273
274    mr.scroll.classModifiers.parseScrollRules = function(element){
275        var text  = element.attr('data-scroll-class'),
276            rules = text.split(";");
277
278        rules.forEach(function(rule){
279            var ruleComponents, scrollPoint, ruleObject = {};
280            ruleComponents = rule.replace(/\s/g, "").split(':');
281            if(ruleComponents.length === 2){
282                scrollPoint = mr.util.parsePixels(ruleComponents[0]);
283                if(scrollPoint > -1){
284                    ruleObject.scrollPoint = scrollPoint;
285                    if(ruleComponents[1].length){
286                        var toggleClass = ruleComponents[1];
287                        ruleObject.toggleClass = toggleClass;
288                        // Set variable in object to indicate that element already has class applied
289                        ruleObject.hasClass = element.hasClass(toggleClass);
290                        ruleObject.element = element.get(0);
291                        mr.scroll.classModifiers.rules.push(ruleObject);
292                    }else{
293                        // Error: toggleClass component does not exist.
294                        //console.log('Error - toggle class not found.');
295                        return false;
296                    }
297                }else{
298                    // Error: scrollpoint component was malformed
299                    //console.log('Error - Scrollpoint not found.');
300                    return false;
301                }
302            }   
303        });
304        
305        if(mr.scroll.classModifiers.rules.length){
306            return true;
307        }else{
308            return false;
309        }
310    };
311
312    mr.scroll.classModifiers.update = function(event){
313        var currentScroll = mr.scroll.y,
314            scrollRules   = mr.scroll.classModifiers.rules,
315            l             = scrollRules.length,
316            currentRule;
317        
318        // Given the current scrollPoint, check for necessary changes 
319        while(l--) {
320            
321            currentRule = scrollRules[l];
322            
323            if(currentScroll > currentRule.scrollPoint && !currentRule.hasClass){
324                // Set local copy and glogal copy at the same time;
325                currentRule.element.classList.add(currentRule.toggleClass);
326                currentRule.hasClass = mr.scroll.classModifiers.rules[l].hasClass = true;
327            }
328            if(currentScroll < currentRule.scrollPoint && currentRule.hasClass){
329                // Set local copy and glogal copy at the same time;
330                currentRule.element.classList.remove(currentRule.toggleClass);
331                currentRule.hasClass = mr.scroll.classModifiers.rules[l].hasClass = false;
332            }
333        }
334    };
335
336    var fixedElementSizes = function(){
337        $('.main-container [data-scroll-class*="pos-fixed"]').each(function(){
338            var element = $(this);
339            element.css('max-width',element.parent().outerWidth());
340            element.parent().css('min-height',element.outerHeight());
341        });
342    };
343
344    var documentReady = function($){
345        // Collect info on all elements that require class modification at load time
346        // Each element has data-scroll-class with a formatted value to represent class to add/remove at a particular scroll point.
347        $('[data-scroll-class]').each(function(){
348            var element  = $(this);
349                
350            // Test the rules to be added to an array of rules.
351            if(!mr.scroll.classModifiers.parseScrollRules(element)){
352                console.log('Error parsing scroll rules on: '+element);
353            }
354        });
355
356        // For 'position fixed' elements, give them a max-width for correct fixing behaviour
357        fixedElementSizes();
358        $(window).on('resize', fixedElementSizes);
359        
360        // If there are valid scroll rules add classModifiers update function to the scroll event processing queue.
361        if(mr.scroll.classModifiers.rules.length){
362            mr.scroll.listeners.push(mr.scroll.classModifiers.update);
363        }
364    };
365
366    mr.components.documentReady.push(documentReady);
367    mr.scroll.classModifiers.documentReady = documentReady;    
368
369    
370
371    return mr;
372
373}(mr, jQuery, window, document));
374
375
376//////////////// Accordions
377mr = (function (mr, $, window, document){
378    "use strict";
379
380    mr.accordions = {};
381
382    
383    mr.accordions.documentReady = function($){
384        $('.accordion__title').on('click', function(){
385            mr.accordions.activatePanel($(this));
386        });
387
388        $('.accordion').each(function(){
389            var accordion = $(this);
390            var minHeight = accordion.outerHeight(true);
391            accordion.css('min-height',minHeight);
392        });
393
394        if(window.location.hash !== ''){
395             mr.accordions.activatePanelById(window.location.hash, true);
396        }
397
398        $('a[href^="#"]').on('click', function(){
399             mr.accordions.activatePanelById($(this).attr('href'), true);
400        });
401    };
402
403    
404
405    mr.accordions.activatePanel = function(panel, forceOpen){
406        var $panel    = $(panel),
407            accordion = $panel.closest('.accordion'),
408            li        = $panel.closest('li'),
409            openEvent = document.createEvent('Event'),
410            closeEvent = document.createEvent('Event');
411            
412            openEvent.initEvent('panelOpened.accordions.mr', true, true);
413            closeEvent.initEvent('panelClosed.accordions.mr', true, true);
414        
415        if(li.hasClass('active')){
416            if(forceOpen !== true){
417                li.removeClass('active');
418                $panel.trigger('panelClosed.accordions.mr').get(0).dispatchEvent(closeEvent);
419            }
420        }else{
421            if(accordion.hasClass('accordion--oneopen')){
422                var wasActive = accordion.find('li.active');
423                wasActive.removeClass('active');
424                wasActive.trigger('panelClosed.accordions.mr').get(0).dispatchEvent(closeEvent);
425                li.addClass('active');
426                li.trigger('panelOpened.accordions.mr').get(0).dispatchEvent(openEvent);
427                
428            }else{
429                if(!li.is('.active')){
430                    li.trigger('panelOpened.accordions.mr').get(0).dispatchEvent(openEvent);
431                }
432                li.addClass('active');
433            }
434        }
435    }
436
437    mr.accordions.activatePanelById = function(id, forceOpen){
438        var panel;
439
440        if(id !== '' && id !== '#'){
441            panel = $('.accordion > li > .accordion__title#'+id.replace('#', ''));
442            if(panel.length){
443                $('html, body').stop(true).animate({
444                    scrollTop: (panel.offset().top - 50)
445                }, 1200);
446                mr.accordions.activatePanel(panel, forceOpen);
447            }
448        }
449    };
450
451    mr.components.documentReady.push(mr.accordions.documentReady);
452    return mr;
453
454}(mr, jQuery, window, document));
455
456
457//////////////// Alerts
458mr = (function (mr, $, window, document){
459    "use strict";
460    
461    var documentReady = function($){
462        $('.alert__close').on('click touchstart', function(){
463            jQuery(this).closest('.alert').addClass('alert--dismissed');
464        });
465    };
466
467    mr.alerts = {
468        documentReady : documentReady        
469    };
470
471    mr.components.documentReady.push(documentReady);
472    return mr;
473
474}(mr, jQuery, window, document));
475
476
477//////////////// Backgrounds
478mr = (function (mr, $, window, document){
479    "use strict";
480    
481    var documentReady = function($){
482        
483        //////////////// Append .background-image-holder <img>'s as CSS backgrounds
484
485	    $('.background-image-holder').each(function() {
486	        var imgSrc = $(this).children('img').attr('src');
487	        $(this).css('background', 'url("' + imgSrc + '")').css('background-position', 'initial').css('opacity','1');
488	    });
489    };
490
491    mr.backgrounds = {
492        documentReady : documentReady        
493    };
494
495    mr.components.documentReady.push(documentReady);
496    return mr;
497
498}(mr, jQuery, window, document));
499
500//////////////// Bars
501mr = (function (mr, $, window, document){
502    "use strict";
503    
504    var documentReady = function($){
505        $('.nav-container .bar[data-scroll-class*="fixed"]:not(.bar--absolute)').each(function(){
506            var bar = $(this),
507                barHeight = bar.outerHeight(true);
508            bar.closest('.nav-container').css('min-height',barHeight);
509        });
510    };
511
512    mr.bars = {
513        documentReady : documentReady        
514    };
515
516    mr.components.documentReady.push(documentReady);
517    return mr;
518
519}(mr, jQuery, window, document));
520
521//////////////// Cookies
522mr = (function (mr, $, window, document){
523    "use strict";
524    
525    mr.cookies = {
526
527        getItem: function (sKey) {
528            if (!sKey) { return null; }
529            return decodeURIComponent(document.cookie.replace(new RegExp("(?:(?:^|.*;)\\s*" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=\\s*([^;]*).*$)|^.*$"), "$1")) || null;
530        },
531        setItem: function (sKey, sValue, vEnd, sPath, sDomain, bSecure) {
532            if (!sKey || /^(?:expires|max\-age|path|domain|secure)$/i.test(sKey)) { return false; }
533                var sExpires = "";
534                if (vEnd) {
535                  switch (vEnd.constructor) {
536                    case Number:
537                      sExpires = vEnd === Infinity ? "; expires=Fri, 31 Dec 9999 23:59:59 GMT" : "; max-age=" + vEnd;
538                      break;
539                    case String:
540                      sExpires = "; expires=" + vEnd;
541                      break;
542                    case Date:
543                      sExpires = "; expires=" + vEnd.toUTCString();
544                      break;
545                }
546            }
547            document.cookie = encodeURIComponent(sKey) + "=" + encodeURIComponent(sValue) + sExpires + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "") + (bSecure ? "; secure" : "");
548            return true;
549        },
550        removeItem: function (sKey, sPath, sDomain) {
551            if (!this.hasItem(sKey)) { return false; }
552            document.cookie = encodeURIComponent(sKey) + "=; expires=Thu, 01 Jan 1970 00:00:00 GMT" + (sDomain ? "; domain=" + sDomain : "") + (sPath ? "; path=" + sPath : "");
553            return true;
554        },
555        hasItem: function (sKey) {
556            if (!sKey) { return false; }
557            return (new RegExp("(?:^|;\\s*)" + encodeURIComponent(sKey).replace(/[\-\.\+\*]/g, "\\$&") + "\\s*\\=")).test(document.cookie);
558        },
559        keys: function () {
560            var aKeys = document.cookie.replace(/((?:^|\s*;)[^\=]+)(?=;|$)|^\s*|\s*(?:\=[^;]*)?(?:\1|$)/g, "").split(/\s*(?:\=[^;]*)?;\s*/);
561            for (var nLen = aKeys.length, nIdx = 0; nIdx < nLen; nIdx++) { aKeys[nIdx] = decodeURIComponent(aKeys[nIdx]); }
562            return aKeys;
563        }
564    };
565
566    return mr;
567
568}(mr, jQuery, window, document));
569
570//////////////// Countdown
571mr = (function (mr, $, window, document){
572    "use strict";
573    
574    var documentReady = function($){
575
576        $('.countdown[data-date]').each(function(){
577            var element      = $(this),
578                date         = element.attr('data-date'),
579                daysText     = "days",
580                fallback;
581
582            if(typeof element.attr('data-date-fallback') !== typeof undefined){
583                fallback = element.attr('data-date-fallback');
584            }
585
586            if(typeof element.attr('data-days-text') !== typeof undefined){
587                daysText = element.attr('data-days-text');
588            }
589
590            element.countdown(date, function(event) {
591                if(event.elapsed){
592                    element.text(fallback);
593                }else{
594                    element.text(
595                      event.strftime('%D '+daysText+' %H:%M:%S')
596                    );
597                }
598            });
599        });
600        
601    };
602
603    mr.countdown = {
604      documentReady : documentReady        
605    };
606
607    mr.components.documentReadyDeferred.push(documentReady);
608    return mr;
609
610}(mr, jQuery, window, document));
611
612//////////////// Datepicker
613mr = (function (mr, $, window, document){
614    "use strict";
615
616    var documentReady = function($){
617        if($('.datepicker').length){
618            $('.datepicker').pickadate();
619        }
620    };
621
622    mr.components.documentReadyDeferred.push(documentReady);
623    return mr;
624
625}(mr, jQuery, window, document));
626
627//////////////// Dropdowns
628mr = (function (mr, $, window, document){
629    "use strict";
630    mr.dropdowns = {};
631    mr.dropdowns.done = false;
632    
633    var documentReady = function($){
634
635        var rtl = false;
636
637        if($('html[dir="rtl"]').length){
638            rtl = true;
639        }
640
641        if(!mr.dropdowns.done){
642            jQuery(document).on('click','body:not(.dropdowns--hover) .dropdown:not(.dropdown--hover), body.dropdowns--hover .dropdown.dropdown--click',function(event){
643                var dropdown = jQuery(this);
644                if(jQuery(event.target).is('.dropdown--active > .dropdown__trigger')){
645                    dropdown.siblings().removeClass('dropdown--active').find('.dropdown').removeClass('dropdown--active');
646                    dropdown.toggleClass('dropdown--active');
647                }else{
648                    $('.dropdown--active').removeClass('dropdown--active');
649                    dropdown.addClass('dropdown--active');
650                }
651            });
652            jQuery(document).on('click touchstart', 'body:not(.dropdowns--hover)', function(event){
653                if(!jQuery(event.target).is('[class*="dropdown"], [class*="dropdown"] *')){
654                    $('.dropdown--active').removeClass('dropdown--active');
655                }
656            });
657            jQuery('body.dropdowns--hover .dropdown').on('click', function(event){
658                event.stopPropagation();
659                var hoverDropdown = jQuery(this);
660                hoverDropdown.toggleClass('dropdown--active');
661            });
662
663            // Append a container to the body for measuring purposes
664            jQuery('body').append('<div class="container containerMeasure" style="opacity:0;pointer-events:none;"></div>');
665
666            
667        
668
669            // Menu dropdown positioning
670            if(rtl === false){
671                repositionDropdowns($);
672                jQuery(window).on('resize', function(){repositionDropdowns($);});
673            }else{
674                repositionDropdownsRtl($);
675                jQuery(window).on('resize', function(){repositionDropdownsRtl($);});
676            }
677
678            mr.dropdowns.done = true;
679        }
680    };
681
682    function repositionDropdowns($){
683        $('.dropdown__container').each(function(){
684            var container, containerOffset, masterOffset, menuItem, content;
685
686                jQuery(this).css('left', '');
687
688                container       = jQuery(this);  
689                containerOffset = container.offset().left;
690                masterOffset    = jQuery('.containerMeasure').offset().left;
691                menuItem        = container.closest('.dropdown').offset().left;
692                content         = null;
693                
694                container.css('left',((-containerOffset)+(masterOffset)));
695
696                if(container.find('.dropdown__content:not([class*="md-12"])').length){
697                    content = container.find('.dropdown__content');
698                    content.css('left', ((menuItem)-(masterOffset)));
699                }
700                
701        });
702        $('.dropdown__content').each(function(){
703            var dropdown, offset, width, offsetRight, winWidth, leftCorrect;
704
705                dropdown    = jQuery(this);
706                offset      = dropdown.offset().left;
707                width       = dropdown.outerWidth(true);
708                offsetRight = offset + width;
709                winWidth    = jQuery(window).outerWidth(true);
710                leftCorrect = jQuery('.containerMeasure').outerWidth() - width;
711
712            if(offsetRight > winWidth){
713                dropdown.css('left', leftCorrect);
714            }
715
716        });
717    }
718
719    function repositionDropdownsRtl($){
720
721        var windowWidth = jQuery(window).width();
722
723        $('.dropdown__container').each(function(){
724            var container, containerOffset, masterOffset, menuItem, content;
725 
726                jQuery(this).css('left', '');
727
728                container   = jQuery(this);
729                containerOffset = windowWidth - (container.offset().left + container.outerWidth(true));
730                masterOffset    = jQuery('.containerMeasure').offset().left;
731                menuItem        = windowWidth - (container.closest('.dropdown').offset().left + container.closest('.dropdown').outerWidth(true));
732                content         = null;
733                
734                container.css('right',((-containerOffset)+(masterOffset)));
735
736                if(container.find('.dropdown__content:not([class*="md-12"])').length){
737                    content = container.find('.dropdown__content');
738                    content.css('right', ((menuItem)-(masterOffset)));
739                }
740        });
741        $('.dropdown__content').each(function(){
742            var dropdown, offset, width, offsetRight, winWidth, rightCorrect;
743
744                dropdown    = jQuery(this);
745                offset      = windowWidth - (dropdown.offset().left + dropdown.outerWidth(true));
746                width       = dropdown.outerWidth(true);
747                offsetRight = offset + width;
748                winWidth    = jQuery(window).outerWidth(true);
749                rightCorrect = jQuery('.containerMeasure').outerWidth() - width;
750
751            if(offsetRight > winWidth){
752               dropdown.css('right', rightCorrect);
753            }
754
755        });
756    }
757
758    mr.dropdowns.documentReady = documentReady;
759    
760
761    mr.components.documentReady.push(documentReady);
762    return mr;
763
764}(mr, jQuery, window, document));
765
766//////////////// Forms
767
768mr = (function (mr, $, window, document){
769    "use strict";
770    
771    mr.forms = {};
772    mr.forms.captcha         = {};
773    mr.forms.captcha.widgets = [];
774    mr.forms.captcha.done    = false;
775
776    var documentReady = function($){
777
778        mr.forms.captcha.widgets = [];
779
780        /// Checkbox & Radio Inputs
781
782        $('.input-checkbox input[type="checkbox"], .input-radio input[type="radio"]').each(function(index){
783            var input = $(this),
784                label = input.siblings('label'),
785                id    = "input-assigned-"+index;
786            if(typeof input.attr('id') === typeof undefined || input.attr('id') === ""){
787                input.attr('id',id);
788                label.attr('for',id);
789            }else{
790                id = input.attr('id');
791                label.attr('for',id);
792            }
793        });
794
795        //////////////// Number Inputs
796
797        $('.input-number__controls > span').off('click.mr').on('click.mr',function(){
798            var control = jQuery(this),
799                parent   = control.closest('.input-number'),
800                input    = parent.find('input[type="number"]'),
801                max      = input.attr('max'),
802                min      = input.attr('min'),
803                step     = 1,
804                current  = parseInt(input.attr('value'),10);
805
806            if(parent.is('[data-step]')){
807                step = parseInt(parent.attr('data-step'),10);
808            }
809
810            if(control.hasClass('input-number__increase')){
811                if((current+step) <= max){
812                    input.attr('value',current+step);
813                }
814            }else{
815                if((current-step) >= min){
816                    input.attr('value',current-step);
817                }
818            }
819        });
820
821
822        //////////////// File Uploads
823
824        $('.input-file .btn').off('click.mr').on('click.mr',function(){
825            $(this).siblings('input').trigger('click');
826            return false;
827        });
828        
829        //////////////// Handle Form Submit
830
831        $('form.form-email, form[action*="list-manage.com"], form[action*="createsend.com"]').attr('novalidate', true).off('submit').on('submit', mr.forms.submit);
832
833        //////////////// Handle Form Submit
834        $(document).on('change, input, paste, keyup', '.attempted-submit .field-error', function(){
835            $(this).removeClass('field-error');
836        });
837
838         //////////////// Check forms for Google reCaptcha site keys
839
840        $('form[data-recaptcha-sitekey]:not([data-recaptcha-sitekey=""])').each(function(){
841            var $thisForm    = jQuery(this),
842                $captchaDiv  = $thisForm.find('div.recaptcha'),
843                $insertBefore, $column, widgetObject,  $script, scriptSrc, widgetColourTheme, widgetSize;
844
845            widgetColourTheme = $thisForm.attr('data-recaptcha-theme');
846            widgetColourTheme = typeof widgetColourTheme !== typeof undefined ? widgetColourTheme : '';
847
848            widgetSize = $thisForm.attr('data-recaptcha-size');
849            widgetSize = typeof widgetSize !== typeof undefined ? widgetSize : '';
850
851            // Store the site key for later use
852            mr.forms.captcha.sitekey = $thisForm.attr('data-recaptcha-sitekey');
853
854            if($captchaDiv.length){
855                // If a div.recaptcha was already present on this form, do nothing at this stage,
856                // It will be populated with a captcha widget later.
857            }else{
858                // Create a captcha div and insert it before the submit button.
859                $insertBefore = $thisForm.find('button[type=submit]').closest('[class*="col-"]');
860                $captchaDiv   = jQuery('<div>').addClass('recaptcha');
861                $column       = jQuery('<div>').addClass('col-xs-12').append($captchaDiv);
862                $column.insertBefore($insertBefore);
863            }
864
865       
866            // Add the widget div to the widgets array
867            widgetObject = {
868                element:    $captchaDiv.get(0),
869                parentForm: $thisForm,
870                theme:      widgetColourTheme,
871                size:       widgetSize,
872            };
873
874          
875
876            mr.forms.captcha.widgets.push(widgetObject);
877
878            // mr.forms.captcha.done indicates whether the api script has been appended yet.
879            if(mr.forms.captcha.done === false){
880                if(!jQuery('script[src*="recaptcha/api.js"]').length){
881                    $script   = jQuery('<script async defer>');
882                    scriptSrc = 'https://www.google.com/recaptcha/api.js?onload=mrFormsCaptchaInit&render=explicit';
883                    $script.attr('src', scriptSrc);
884                    jQuery('body').append($script);
885                    mr.forms.captcha.done = true;
886                }
887            }else{
888                if(typeof grecaptcha !== typeof undefined){
889                    mr.forms.captcha.renderWidgets();    
890                }
891            }
892
893        });
894
895
896    };
897
898    mr.forms.documentReady = documentReady;
899
900   
901
902    
903    mr.forms.submit = function(e){
904        // return false so form submits through jQuery rather than reloading page.
905        if (e.preventDefault) e.preventDefault();
906        else e.returnValue = false;
907
908        var body          = $('body'),
909            thisForm      = $(e.target).closest('form'),
910            formAction    = typeof thisForm.attr('action') !== typeof undefined ? thisForm.attr('action') : "",
911            submitButton  = thisForm.find('button[type="submit"], input[type="submit"]'),
912            error         = 0,
913            originalError = thisForm.attr('original-error'),
914            captchaUsed   = thisForm.find('div.recaptcha').length ? true:false,
915            successRedirect, formError, formSuccess, errorText, successText;
916
917        body.find('.form-error, .form-success').remove();
918        submitButton.attr('data-text', submitButton.text());
919        errorText = thisForm.attr('data-error') ? thisForm.attr('data-error') : "Please fill all fields correctly";
920        successText = thisForm.attr('data-success') ? thisForm.attr('data-success') : "Thanks, we'll be in touch shortly";
921        body.append('<div class="form-error" style="display: none;">' + errorText + '</div>');
922        body.append('<div class="form-success" style="display: none;">
922' + successText + '</div>');
923        formError = body.find('.form-error');
924        formSuccess = body.find('.form-success');
925        thisForm.addClass('attempted-submit');
926
927        // Do this if the form is intended to be submitted to MailChimp or Campaign Monitor
928        if (formAction.indexOf('createsend.com') !== -1 || formAction.indexOf('list-manage.com') !== -1 ) {
929
930            console.log('Mail list form signup detected.');
931            if (typeof originalError !== typeof undefined && originalError !== false) {
932                formError.html(originalError);
933            }
934            
935            // validateFields returns 1 on error;
936            if (mr.forms.validateFields(thisForm) !== 1) {
937               
938                thisForm.removeClass('attempted-submit');
939
940                // Hide the error if one was shown
941                formError.fadeOut(200);
942                // Create a new loading spinner in the submit button.
943                submitButton.addClass('btn--loading');
944                
945                try{
946                    $.ajax({
947                        url: thisForm.attr('action'),
948                        crossDomain: true,
949                        data: thisForm.serialize(),
950                        method: "GET",
951                        cache: false,
952                        dataType: 'json',
953                        contentType: 'application/json; charset=utf-8',
954                        success: function(data){
955                            // Request was a success, what was the response?
956
957                            if (data.result !== "success" && data.Status !== 200) {
958                                
959                                // Got an error from Mail Chimp or Campaign Monitor
960
961                                // Keep the current error text in a data attribute on the form
962                                formError.attr('original-error', formError.text());
963                                // Show the error with the returned error text.
964                                formError.html(data.msg).stop(true).fadeIn(1000);
965                                formSuccess.stop(true).fadeOut(1000);
966
967                                submitButton.removeClass('btn--loading');
968                            } else {
969                                
970                                // Got success from Mail Chimp or Campaign Monitor
971                                
972                                submitButton.removeClass('btn--loading');
973
974                                successRedirect = thisForm.attr('data-success-redirect');
975                                // For some browsers, if empty `successRedirect` is undefined; for others,
976                                // `successRedirect` is false.  Check for both.
977                                if (typeof successRedirect !== typeof undefined && successRedirect !== false && successRedirect !== "") {
978                                    window.location = successRedirect;
979                                }else{
980                                    mr.forms.resetForm(thisForm);
981                                    mr.forms.showFormSuccess(formSuccess, formError, 1000, 5000, 500);
982                                }
983                            }
984                        }
985                    });
986                }catch(err){
987                    // Keep the current error text in a data attribute on the form
988                    formError.attr('original-error', formError.text());
989                    // Show the error with the returned error text.
990                    formError.html(err.message);
991                    mr.forms.showFormError(formSuccess, formError, 1000, 5000, 500);
992
993                    submitButton.removeClass('btn--loading');
994                }
995            
996
997                
998            } else {
999                // There was a validation error - show the default form error message
1000                mr.forms.showFormError(formSuccess, formError, 1000, 5000, 500);
1001            }
1002        } else {
1003            // If no MailChimp or Campaign Monitor form was detected then this is treated as an email form instead.
1004            if (typeof originalError !== typeof undefined && originalError !== false) {
1005                formError.text(originalError);
1006            }
1007
1008            error = mr.forms.validateFields(thisForm);
1009
1010            if (error === 1) {
1011                mr.forms.showFormError(formSuccess, formError, 1000, 5000, 500);
1012            } else {
1013
1014                thisForm.removeClass('attempted-submit');
1015
1016                // Hide the error if one was shown
1017                formError.fadeOut(200);
1018                
1019                // Create a new loading spinner in the submit button.
1020                submitButton.addClass('btn--loading');
1021
1022                jQuery.ajax({
1023                    type: "POST",
1024                    url: "mail/mail.php",
1025                    data: thisForm.serialize()+"&url="+window.location.href+"&captcha="+captchaUsed,
1026                    success: function(response) {
1027                        // Swiftmailer always sends back a number representing number of emails sent.
1028                        // If this is numeric (not Swift Mailer error text) AND greater than 0 then show success message.
1029
1030                        submitButton.removeClass('btn--loading');
1031
1032                        if ($.isNumeric(response)) {
1033                            if (parseInt(response,10) > 0) {
1034                                // For some browsers, if empty 'successRedirect' is undefined; for others,
1035                                // 'successRedirect' is false.  Check for both.
1036                                successRedirect = thisForm.attr('data-success-redirect');
1037                                if (typeof successRedirect !== typeof undefined && successRedirect !== false && successRedirect !== "") {
1038                                    window.location = successRedirect;
1039                                }
1040
1041                                mr.forms.resetForm(thisForm);
1042                                mr.forms.showFormSuccess(formSuccess, formError, 1000, 5000, 500);
1043                                mr.forms.captcha.resetWidgets();
1044                            }
1045                        }
1046                        // If error text was returned, put the text in the .form-error div and show it.
1047                        else {
1048                            // Keep the current error text in a data attribute on the form
1049                            formError.attr('original-error', formError.text());
1050                            // Show the error with the returned error text.
1051                            formError.text(response).stop(true).fadeIn(1000);
1052                            formSuccess.stop(true).fadeOut(1000);
1053                        }
1054                    },
1055                    error: function(errorObject, errorText, errorHTTP) {
1056                        // Keep the current error text in a data attribute on the form
1057                        formError.attr('original-error', formError.text());
1058                        // Show the error with the returned error text.
1059                        formError.text(errorHTTP).stop(true).fadeIn(1000);
1060                        formSuccess.stop(true).fadeOut(1000);
1061                        submitButton.removeClass('btn--loading');
1062                    }
1063                });
1064            }
1065        }
1066        return false;
1067    };
1068    
1069    mr.forms.validateFields = function(form) {
1070        var body = $(body),
1071            error = false,
1072            originalErrorMessage,
1073            name,
1074            thisElement;
1075
1076            form = $(form);
1077
1078
1079
1080
1081        form.find('.validate-required[type="checkbox"]').each(function() {
1082            var checkbox = $(this);
1083            if (!$('[name="' + $(this).attr('name') + '"]:checked').length) {
1084                error = 1;
1085                name = $(this).attr('data-name') ||  'check';
1086                checkbox.parent().addClass('field-error');
1087                //body.find('.form-error').text('Please tick at least one ' + name + ' box.');
1088            }
1089        });
1090
1091        form.find('.validate-required, .required, [required]').not('input[type="checkbox"]').each(function() {
1092            if ($(this).val() === '') {
1093                $(this).addClass('field-error');
1094                error = 1;
1095            } else {
1096                $(this).removeClass('field-error');
1097            }
1098        });
1099
1100        form.find('.validate-email, .email, [name*="cm-"][type="email"]').each(function() {
1101            if (!(/(.+)@(.+){2,}\.(.+){2,}/.test($(this).val()))) {
1102                $(this).addClass('field-error');
1103                error = 1;
1104            } else {
1105                $(this).removeClass('field-error');
1106            }
1107        });
1108
1109        form.find('.validate-number-dash').each(function() {
1110            if (!(/^[0-9][0-9-]+[0-9]$/.test($(this).val()))) {
1111                $(this).addClass('field-error');
1112                error = 1;
1113            } else {
1114                $(this).removeClass('field-error');
1115            }
1116        });
1117
1118        // Validate recaptcha
1119        if(form.find('div.recaptcha').length && typeof form.attr('data-recaptcha-sitekey') !== typeof undefined){
1120            thisElement = $(form.find('div.recaptcha'));
1121    
1122            if(grecaptcha.getResponse(form.data('recaptchaWidgetID')) !== ""){
1123                thisElement.removeClass('field-error');
1124            }else{
1125                thisElement.addClass('field-error');
1126                error = 1;
1127            }
1128        }
1129
1130        if (!form.find('.field-error').length) {
1131            body.find('.form-error').fadeOut(1000);
1132        }else{
1133            
1134            var firstError = $(form).find('.field-error:first');
1135            
1136            if(firstError.length){
1137                $('html, body').stop(true).animate({
1138                    scrollTop: (firstError.offset().top - 100)
1139                }, 1200, function(){firstError.focus();});
1140            }
1141        }
1142
1143
1144
1145        return error;
1146    };
1147
1148    mr.forms.showFormSuccess = function(formSuccess, formError, fadeOutError, wait, fadeOutSuccess){
1149        
1150        formSuccess.stop(true).fadeIn(fadeOutError);
1151
1152        formError.stop(true).fadeOut(fadeOutError);
1153        setTimeout(function() {
1154            formSuccess.stop(true).fadeOut(fadeOutSuccess);
1155        }, wait);
1156    };
1157
1158    mr.forms.showFormError = function(formSuccess, formError, fadeOutSuccess, wait, fadeOutError){
1159        
1160        formError.stop(true).fadeIn(fadeOutSuccess);
1161
1162        formSuccess.stop(true).fadeOut(fadeOutSuccess);
1163        setTimeout(function() {
1164            formError.stop(true).fadeOut(fadeOutError);
1165        }, wait);
1166    };
1167
1168    // Reset form to empty/default state.
1169    mr.forms.resetForm = function(form){
1170        form = $(form);
1171        form.get(0).reset();
1172        form.find('.input-radio, .input-checkbox').removeClass('checked');
1173
1174    };
1175
1176    // Defined on the window scope as the recaptcha js api seems not to be able to call function in mr scope
1177    window.mrFormsCaptchaInit = function(){
1178        mr.forms.captcha.renderWidgets();
1179    };
1180
1181    mr.forms.captcha.renderWidgets = function(){
1182        mr.forms.captcha.widgets.forEach(function(widget){
1183            if(widget.element.innerHTML === ''){
1184                widget.id = grecaptcha.render(widget.element, {
1185                    'sitekey' : mr.forms.captcha.sitekey,
1186                    'theme' : widget.theme,
1187                    'size' : widget.size,
1188                    'callback' : mr.forms.captcha.setHuman
1189                });
1190                widget.parentForm.data('recaptchaWidgetID', widget.id);
1191            }
1192        });
1193    };
1194
1195    mr.forms.captcha.resetWidgets = function(){
1196        mr.forms.captcha.widgets.forEach(function(widget){
1197            grecaptcha.reset(widget.id);
1198        });
1199    };
1200
1201    mr.forms.captcha.setHuman = function(){
1202        jQuery('div.recaptcha.field-error').removeClass('field-error');
1203    };
1204
1205    mr.components.documentReadyDeferred.push(documentReady);
1206    return mr;
1207
1208}(mr, jQuery, window, document));
1209
1210//////////////// Granim
1211mr = (function (mr, $, window, document){
1212    "use strict";
1213    
1214    var documentReady = function($){
1215    	$('[data-gradient-bg]').each(function(index,element){
1216    		var granimParent = $(this),
1217    			granimID 	 = 'granim-'+index+'',
1218				colours 	 = granimParent.attr('data-gradient-bg'),
1219				pairs        = [],
1220				tempPair     = [],
1221				count,
1222				passes,
1223				i;
1224
1225			// Canvas element forms the gradient background
1226			granimParent.prepend('<canvas id="'+granimID+'"></canvas>');
1227
1228            // Regular expression to match comma separated list of hex colour values
1229            passes = /^(#[0-9|a-f|A-F]{6}){1}([ ]*,[ ]*#[0-9|a-f|A-F]{6})*$/.test(colours);
1230
1231            if(passes === true){
1232            	colours = colours.replace(' ','');
1233            	colours = colours.split(',');
1234            	count = colours.length;
1235            	// If number of colours is odd - duplicate last colour to make even array
1236            	if(count%2 !== 0){
1237            		colours.push(colours[count-1]);
1238            	}
1239            	for(i = 0; i < (count/2); i++){
1240                    tempPair = [];
1241                    tempPair.push(colours.shift());
1242                    tempPair.push(colours.shift());
1243                    pairs.push(tempPair);
1244            	}
1245            }
1246
1247    		var granimElement = $(this);
1248    		var granimInstance = new Granim({
1249			    element: '#'+granimID,
1250			    name: 'basic-gradient',
1251			    direction: 'left-right',
1252			    opacity: [1, 1],
1253			    isPausedWhenNotInView: true,
1254			    states : {
1255			        "default-state": {
1256			            gradients: pairs
1257			        }
1258			    }
1259			});
1260    	});        
1261    };
1262
1263    mr.granim = {
1264      documentReady : documentReady        
1265    };
1266
1267    mr.components.documentReadyDeferred.push(documentReady);
1268    return mr;
1269
1270}(mr, jQuery, window, document));
1271
1272//////////////// Instagram
1273mr = (function (mr, $, window, document){
1274    "use strict";
1275    
1276    var documentReady = function($){
1277        
1278        if($('.instafeed').length){
1279
1280            // Replace with your own Access Token and Client ID
1281            var token  = '4079540202.b9b1d8a.1d13c245c68d4a17bfbff87919aaeb14',
1282                client = 'b9b1d8ae049d4153b24a6332f0088686',
1283                elementToken, elementClient;
1284
1285            if($('.instafeed[data-access-token][data-client-id]').length){
1286                elementToken = $('.instafeed[data-access-token][data-client-id]').first().attr('data-access-token');
1287                elementClient = $('.instafeed[data-access-token][data-client-id]').first().attr('data-client-id');
1288
1289                if(elementToken !== ""){token = elementToken;}
1290                if(elementClient !== ""){client = elementClient;}
1291            }
1292
1293            jQuery.fn.spectragram.accessData = {
1294                accessToken: token,
1295                clientID: client
1296            };  
1297        }
1298
1299        $('.instafeed').each(function(){
1300            var feed   = $(this),
1301                feedID = feed.attr('data-user-name'),
1302                fetchNumber = 12;
1303            if(typeof feed.attr('data-amount') !== typeof undefined){
1304                fetchNumber = parseInt(feed.attr('data-amount'), 10);
1305            }
1306            feed.append('<ul></ul>');
1307            feed.children('ul').spectragram('getUserFeed', {
1308                query: feedID,
1309                max: fetchNumber
1310            });
1311        });
1312    };
1313
1314    mr.instagram = {
1315        documentReady : documentReady        
1316    };
1317
1318    mr.components.documentReadyDeferred.push(documentReady);
1319    return mr;
1320
1321}(mr, jQuery, window, document));
1322
1323//////////////// Maps
1324mr = (function (mr, $, window, document){
1325    "use strict";
1326    
1327    mr.maps = {};
1328
1329    var documentReady = function($){
1330        // Interact with Map once the user has clicked (to prevent scrolling the page = zooming the map
1331
1332        $('.map-holder').on('click', function() {
1333            $(this).addClass('interact');
1334        }).removeClass('interact');
1335        
1336        var mapsOnPage = $('.map-container[data-maps-api-key]');
1337        if(mapsOnPage.length){
1338            mapsOnPage.addClass('gmaps-active');
1339            mr.maps.initAPI($);
1340            mr.maps.init();
1341        }
1342        
1343    };
1344    mr.maps.documentReady = documentReady;
1345
1346    mr.maps.initAPI = function($){
1347        // Load Google MAP API JS with callback to initialise when fully loaded
1348        if(document.querySelector('[data-maps-api-key]') && !document.querySelector('.gMapsAPI')){
1349            if($('[data-maps-api-key]').length){
1350                var script = document.createElement('script');
1351                var apiKey = $('[data-maps-api-key]:first').attr('data-maps-api-key');
1352                apiKey = typeof apiKey !== typeof undefined ? apiKey : ''; 
1353                if(apiKey !== ''){
1354                    script.type = 'text/javascript';
1355                    script.src = 'https://maps.googleapis.com/ma
1355ps/api/js?key='+apiKey+'&callback=mr.maps.init';
1356                    script.className = 'gMapsAPI';
1357                    document.body.appendChild(script);  
1358                }
1359            } 
1360        }
1361    };
1362
1363    mr.maps.init = function(){
1364        if(typeof window.google !== "undefined"){
1365            if(typeof window.google.maps !== "undefined"){
1366                
1367                jQuery('.gmaps-active').each(function(){
1368                    var mapElement    = this,
1369                        mapInstance   = jQuery(this),
1370                        mapJSON       = typeof mapInstance.attr('data-map-style') !== typeof undefined ? mapInstance.attr('data-map-style'): false,
1371                        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}]}],
1372                        zoomLevel     = (typeof mapInstance.attr('data-map-zoom') !== typeof undefined && mapInstance.attr('data-map-zoom') !== "") ? mapInstance.attr('data-map-zoom') * 1: 17,
1373                        latlong       = typeof mapInstance.attr('data-latlong') !== typeof undefined ? mapInstance.attr('data-latlong') : false,
1374                        latitude      = latlong ? 1 *latlong.substr(0, latlong.indexOf(',')) : false,
1375                        longitude     = latlong ? 1 * latlong.substr(latlong.indexOf(",") + 1) : false,
1376                        geocoder      = new google.maps.Geocoder(),
1377                        address       = typeof mapInstance.attr('data-address') !== typeof undefined ? mapInstance.attr('data-address').split(';'): [""],
1378                        markerImage   = typeof mapInstance.attr('data-marker-image') !== typeof undefined ? mapInstance.attr('data-marker-image'): 'img/mapmarker.png',
1379                        markerTitle   = "We Are Here",
1380                        isDraggable   = jQuery(document).width() > 766 ? true : false,
1381                        map, marker,
1382                        mapOptions = {
1383                            draggable: isDraggable,
1384                            scrollwheel: false,
1385                            zoom: zoomLevel,
1386                            disableDefaultUI: true,
1387                            styles: mapStyle
1388                        };
1389
1390                    if(typeof mapInstance.attr('data-marker-title') !== typeof undefined && mapInstance.attr('data-marker-title') !== "" )
1391                    {
1392                        markerTitle = mapInstance.attr('data-marker-title');
1393                    }
1394
1395                    if(address !== undefined && address[0] !== ""){
1396                            geocoder.geocode( { 'address': address[0].replace('[nomarker]','')}, function(results, status) {
1397                                if (status === google.maps.GeocoderStatus.OK) {
1398                                var map = new google.maps.Map(mapElement, mapOptions); 
1399                                map.setCenter(results[0].geometry.location);
1400                                
1401                                address.forEach(function(address){
1402                                    var markerGeoCoder;
1403                                    
1404                                    markerImage = {url: typeof window.mr_variant === typeof undefined ? typeof markerImage !== "object" ? markerImage: markerImage.url : '../img/mapmarker.png', scaledSize: new google.maps.Size(50,50)};
1405
1406                                    if(/(\-?\d+(\.\d+)?),\s*(\-?\d+(\.\d+)?)/.test(address) ){
1407                                        var latlong = address.split(','),
1408                                        marker = new google.maps.Marker({
1409                                                        position: { lat: 1*latlong[0], lng: 1*latlong[1] },
1410                                                        map: map,
1411                                                        icon: markerImage,
1412                                                        title: markerTitle,
1413                                                        optimised: fal
1413se
1414                                                    });
1415                                    }
1416                                    else if(address.indexOf('[nomarker]') < 0){
1417                                        markerGeoCoder = new google.maps.Geocoder();
1418                                        markerGeoCoder.geocode( { 'address': address.replace('[nomarker]','')}, function(results, status) {
1419                                            if (status === google.maps.GeocoderStatus.OK) {
1420                                                marker = new google.maps.Marker({
1421                                                    map: map,
1422                                                    icon: markerImage,
1423                                                    title: markerTitle,
1424                                                    position: results[0].geometry.location,
1425                                                    optimised: false
1426                                                });
1427                                            }
1428                                            else{
1429                                                console.log('Map marker error: '+status);
1430                                            }
1431                                        });
1432                                    }
1433
1434                                });
1435                            } else {
1436                                console.log('There was a problem geocoding the address.');
1437                            }
1438                        });
1439                    }
1440                    else if(typeof latitude !== typeof undefined && latitude !== "" && latitude !== false && typeof longitude !== typeof undefined && longitude !== "" && longitude !== false ){
1441                        mapOptions.center   = { lat: latitude, lng: longitude};
1442                        map                 = new google.maps.Map(mapInstance, mapOptions); 
1443                        marker              = new google.maps.Marker({
1444                                                    position: { lat: latitude, lng: longitude },
1445                                                    map: map,
1446                                                    icon: markerImage,
1447                                                    title: markerTitle
1448                                                });
1449
1450                    }
1451
1452                }); 
1453            }
1454        }
1455    };
1456
1457    mr.components.documentReady.push(documentReady);
1458    return mr;
1459
1460}(mr, jQuery, window, document));
1461
1462
1463//////////////// Masonry
1464mr = (function (mr, $, window, document){
1465    "use strict";
1466    
1467    var documentReady = function($){
1468
1469        mr.masonry.updateFilters();
1470
1471        $(document).on('click touchstart', '.masonry__filters li', function(){
1472            var masonryFilter = $(this);
1473            var masonryContainer = masonryFilter.closest('.masonry').find('.masonry__container');
1474            var filterValue = '*';
1475            if(masonryFilter.attr('data-masonry-filter') !== '*'){
1476                filterValue = '.filter-'+masonryFilter.attr('data-masonry-filter');
1477            }
1478            masonryFilter.siblings('li').removeClass('active');
1479            masonryFilter.addClass('active');
1480            masonryContainer.removeClass('masonry--animate');
1481            masonryContainer.on('layoutComplete',function(){
1482                $(this).addClass('masonry--active');
1483                if(typeof mr_parallax !== typeof undefined){
1484                    setTimeout(function(){ mr_parallax.profileParallaxElements(); },100);
1485                }
1486            });
1487            masonryContainer.isotope({ filter: filterValue });
1488            
1489        });
1490        
1491    };
1492
1493    var windowLoad = function(){
1494
1495        $('.masonry').each(function(){
1496            var masonry       = $(this).find('.masonry__container'),
1497                masonryParent = $(this),
1498                defaultFilter = '*';
1499
1500            // Check for a default filter attribute
1501            if(masonryParent.is('[data-default-filter]')){
1502                defaultFilter = masonryParent.attr('data-default-filter').toLowerCase();
1503                defaultFilter = '.filter-'+defaultFilter;
1504                masonryParent.find('li[data-masonry-filter]').removeClass('active');
1505                masonryParent.find('li[data-masonry-filter="'+masonryParent.attr("data-default-filter").toLowerCase()+'"]').addClass('active');
1506            }
1507
1508            masonry.on('layoutComplete',function(){
1509                masonry.addClass('masonry--active');
1510                if(typeof mr_parallax !== typeof undefined){
1511                    setTimeout(function(){ mr_parallax.profileParallaxElements(); },100);
1512                }
1513            });
1514
1515            masonry.isotope({
1516              itemSelector: '.masonry__item',
1517              filter: defaultFilter,
1518              masonry: {
1519                columnWidth: '.masonry__item'
1520              }
1521            });
1522
1523        });
1524    };
1525
1526    
1527    mr.masonry = {
1528        documentReady : documentReady,
1529        windowLoad : windowLoad        
1530    };
1531
1532    mr.masonry.updateFilters = function(masonry){
1533
1534        // If no argument is supplied, just apply the update to all masonry sets on the page.
1535        masonry = typeof masonry !== typeof undefined ? masonry : '.masonry';
1536        
1537        var $masonry = $(masonry);
1538        
1539        $masonry.each(function(){
1540            var $masonry         = $(this),
1541                masonryContainer = $masonry.find('.masonry__container'),
1542                filters          = $masonry.find('.masonry__filters'),
1543                // data-filter-all-text can be used to set the word for "all"
1544                filterAllText    = typeof filters.attr('data-filter-all-text') !== typeof undefined ? filters.attr('data-filter-all-text') : "All",
1545                filtersList;
1546            
1547            // Ensure we are working with a .masonry element
1548            if($masonry.is('.masonry')){
1549                // If a filterable masonry item exists
1550                if(masonryContainer.find('.masonry__item[data-masonry-filter]').length){
1551                    
1552                    // Create empty ul for filters
1553                    filtersList = filters.find('> ul');
1554
1555                    if(!filtersList.length){
1556                        filtersList = filters.append('<ul></ul>').find('> ul');
1557                    }
1558
1559                    // To avoid cases where user leave filter attribute blank
1560                    // only take items that have filter attribute
1561                    masonryContainer.find('.masonry__item[data-masonry-filter]').each(function(){
1562                        var masonryItem  = $(this),
1563                            filterString = masonryItem.attr('data-masonry-filter'),
1564                            filtersArray = [];
1565
1566                        // If not undefined or empty
1567                        if(typeof filterString !== typeof undefined && filterString !== ""){
1568                            // Split tags from string into array 
1569                            filtersArray = filterString.split(',');
1570                        }
1571                        jQuery(filtersArray).each(function(index, tag){
1572
1573                            // Slugify the tag
1574
1575                            var slug = mr.util.slugify(tag);
1576
1577                            // Add the filter class to the masonry item
1578
1579                            masonryItem.addClass('filter-'+slug);
1580
1581                            // If this tag does not appear in the list already, add it
1582                            if(!filtersList.find('[data-masonry-filter="'+slug+'"]').length){
1583                                filtersList.append('<li data-masonry-filter="'+slug+'">'+tag+'</li>');
1584                                
1585                            }
1586                        }); 
1587                    });
1588
1589                    mr.util.sortChildrenByText($(this).find('.masonry__filters ul'));
1590                    // Add a filter "all" option
1591                    if(!filtersList.find('[data-masonry-filter="*"]').length){
1592                        filtersList.prepend('<li class="active" data-masonry-filter="*">'+filterAllText+'</li>');
1593                    }
1594
1595                }
1596                //End of "if filterable masonry item exists"
1597            }
1598            //End of "if $masonry is .masonry"
1599        });
1600
1601    };
1602
1603    mr.masonry.updateLayout = function(masonry){
1604        
1605        // If no argument is supplied, just apply the update to all masonry sets on the page.
1606        masonry = typeof masonry !== typeof undefined ? masonry : '.masonry';
1607
1608        var $masonry = $(masonry);
1609        
1610
1611        $masonry.each(function(){
1612            var collection       = $(this),
1613                newItems         = collection.find('.masonry__item:not([style])'),
1614                masonryContainer = collection.find('.masonry__container');
1615
1616            if(collection.is('.masonry')){
1617                if(newItems.length){
1618                    masonryContainer.isotope('appended', newItems).isotope( 'layout');
1619                }
1620                
1621                masonryContainer.isotope('layout');
1622            }
1623        });
1624    };
1625
1626    mr.components.documentReady.push(documentReady);
1627    mr.components.windowLoad.push(windowLoad);
1628    return mr;
1629
1630}(mr, jQuery, window, document));
1631
1632
1633//////////////// Modals
1634mr = (function (mr, $, window, document){
1635    "use strict";
1636    
1637    mr.modals = {};
1638
1639    var documentReady = function($){
1640        var allPageModals = "<div class=\"all-page-modals\"></div>",
1641            mainContainer = $('div.main-container');
1642
1643        if(mainContainer.length){
1644            jQuery(allPageModals).insertAfter(mainContainer);
1645            mr.modals.allModalsContainer = $('div.all-page-modals');
1646        }
1647        else{
1648            jQuery('body').append(allPageModals);
1649            mr.modals.allModalsContainer = jQuery('body div.all-page-modals');
1650        }
1651
1652        $('.modal-container').each(function(){
1653
1654            // Add modal close if none exists
1655
1656            var modal        = $(this),
1657                $window      = $(window),
1658                modalContent = modal.find('.modal-content');
1659                
1660            
1661            if(!modal.find('.modal-close').length){
1662                modal.find('.modal-content').append('<div class="modal-close modal-close-cross"></div>');
1663            }
1664
1665            // Set modal height
1666            
1667            if(modalContent.attr('data-width') !== undefined){
1668                var modalWidth = modalContent.attr('data-width').substr(0,modalContent.attr('data-width').indexOf('%')) * 1;
1669                modalContent.css('width',modalWidth + '%');
1670            }
1671            if(modalContent.attr('data-height') !== undefined){
1672                var modalHeight = modalContent.attr('data-height').substr(0,modalContent.attr('data-height').indexOf('%')) * 1;
1673                modalContent.css('height',modalHeight + '%');
1674            }
1675
1676            // Set iframe's src to data-src to stop autoplaying iframes
1677            mr.util.idleSrc(modal, 'iframe');
1678
1679        });
1680
1681
1682        $('.modal-instance').each(function(index){
1683            var modalInstance = $(this);
1684            var modal = modalInstance.find('.modal-container');
1685            var modalContent = modalInstance.find('.modal-content');
1686            var trigger = modalInstance.find('.modal-trigger');
1687            
1688            // Link modal with modal-id attribute
1689            
1690            trigger.attr('data-modal-index',index);
1691            modal.attr('data-modal-index',index);
1692            
1693            // Set unique id for multiple triggers
1694            
1695            if(typeof modal.attr('data-modal-id') !== typeof undefined){
1696                trigger.attr('data-modal-id', modal.attr('data-modal-id'));
1697            }
1698            
1699
1700            // Attach the modal to the body            
1701            modal = modal.detach();
1702            mr.modals.allModalsContainer.append(modal);
1703        });
1704        
1705
1706        $('.modal-trigger').on('click', function(){
1707
1708            var modalTrigger = $(this);
1709            var uniqueID, targetModal;
1710            // Determine if the modal id is set by user or is set programatically
1711   
1712            if(typeof modalTrigger.attr('data-modal-id') !== typeof undefined){
1713                uniqueID = modalTrigger.attr('data-modal-id');
1714                targetModal = mr.modals.allModalsContainer.find('.modal-container[data-modal-id="'+uniqueID+'"]');    
1715            }else{
1716                uniqueID = $(this).attr('data-modal-index');
1717                targetModal = mr.modals.allModalsContainer.find('.modal-container[data-modal-index="'+uniqueID+'"]');
1718            }
1719            
1720            mr.util.activateIdleSrc(targetModal, 'iframe');
1721            mr.modals.autoplayVideo(targetModal);
1722
1723            mr.modals.showModal(targetModal);
1724
1725            return false;
1726        });
1727
1728        jQuery(document).on('click', '.modal-close', mr.modals.closeActiveModal);
1729
1730        jQuery(document).keyup(function(e) {
1731            if (e.keyCode === 27) { // escape key maps to keycode `27`
1732                mr.modals.closeActiveModal();
1733            }
1734        });
1735
1736        $('.modal-container').on('click', function(e) { 
1737            if( e.target !== this ) return;
1738            mr.modals.closeActiveModal();
1739        });
1740
1741        // Trigger autoshow modals
1742        $('.modal-container[data-autoshow]').each(function(){
1743            var modal = $(this);
1744            var millisecondsDelay = modal.attr('data-autoshow')*1;
1745
1746            mr.util.activateIdleSrc(modal);
1747            mr.modals.autoplayVideo(modal);
1748
1749            // If this modal has a cookie attribute, check to see if a cookie is set, and if so, don't show it.
1750            if(typeof modal.attr('data-cookie') !== typeof undefined){
1751                if(!mr.cookies.hasItem(modal.attr('data-cookie'))){
1752                    mr.modals.showModal(modal, millisecondsDelay);
1753                }
1754            }else{
1755                mr.modals.showModal(modal, millisecondsDelay);
1756            }
1757        });
1758
1759        // Exit modals
1760        $('.modal-container[data-show-on-exit]').each(function(){
1761            var modal        = jQuery(this),
1762                exitSelector = modal.attr('data-show-on-exit'),
1763                delay = 0;
1764
1765            if(modal.attr('data-delay')){
1766                delay = parseInt(modal.attr('data-delay'), 10) || 0;  
1767            } 
1768
1769            // If a valid selector is found, attach leave event to show modal.
1770            if($(exitSelector).length){
1771                modal.prepend($('<i class="ti-close close-modal">'));
1772                jQuery(document).on('mouseleave', exitSelector, function(){
1773                    if(!$('.modal-active').length){
1774                        if(typeof modal.attr('data-cookie') !== typeof undefined){
1775                            if(!mr.cookies.hasItem(modal.attr('data-cookie'))){
1776                                mr.modals.showModal(modal, delay);
1777                            }
1778                        }else{
1779                            mr.modals.showModal(modal, delay);
1780                        }
1781                    }
1782                });
1783            }
1784        });
1785
1786
1787        // Autoshow modal by ID from location href
1788        if(window.location.href.split('#').length === 2){
1789            var modalID = window.location.href.split('#').pop();
1790            if($('[data-modal-id="'+modalID+'"]').length){
1791                mr.modals.closeActiveModal();
1792                mr.modals.showModal($('[data-modal-id="'+modalID+'"]'));
1793            }  
1794        }
1795
1796        // Make modal scrollable
1797        $(document).on('wheel mousewheel scroll','.modal-content, .modal-content .scrollable', function(evt){
1798            if(evt.preventDefault){evt.preventDefault();}
1799            if(evt.stopPropagation){evt.stopPropagation();}
1800            this.scrollTop += (evt.originalEvent.deltaY); 
1801        });
1802    };
1803    ////////////////
1804    //////////////// End documentReady
1805    ////////////////
1806
1807    mr.modals.documentReady = documentReady;
1808
1809    mr.modals.showModal = function(modal, millisecondsDelay){
1810        
1811        var delay = (typeof millisecondsDelay !== typeof undefined) ? (1*millisecondsDelay) : 0;
1812        
1813        setTimeout(function(){
1814            $(modal).addClass('modal-active');
1815        },delay);
1816    };
1817
1818    mr.modals.closeActiveModal = function(){
1819        var modal = jQuery('body div.modal-active');
1820        mr.util.idleSrc(modal, 'iframe');
1821        mr.util.pauseVideo(modal);
1822
1823        // If this modal requires to be closed permanently using a cookie, set the cookie now.
1824        if(typeof modal.attr('data-cookie') !== typeof undefined){
1825            mr.cookies.setItem(modal.attr('data-cookie'), "true", Infinity, '/');
1826        }
1827
1828        modal.removeClass('modal-active');
1829    };
1830
1831    mr.modals.autoplayVideo = function(modal){
1832        // If modal contains HTML5 video with autoplay, play the video
1833        if(modal.find('video[autoplay]').length){
1834            var video = modal.find('video').get(0);
1835            video.play();
1836        }
1837    };
1838
1839    mr.components.documentReady.push(documentReady);
1840    return mr;
1841
1842}(mr, jQuery, window, document));
1843
1844//////////////// Newsletter Providers
1845mr = (function (mr, $, window, document){
1846    "use strict";
1847    
1848    mr.newsletters = {};
1849
1850    var documentReady = function($){
1851  
1852  	var form,checkbox,label,id,parent,radio;
1853    
1854    // Treat Campaign Monitor forms
1855    $('form[action*="createsend.com"]').each(function(){
1856    	form = $(this);
1857
1858        // Override browser validation and allow us to use our own
1859        form.attr('novalidate', 'novalidate');
1860
1861    	// Give each text input a placeholder value
1862
1863    	if(!form.is('.form--no-placeholders')){
1864            form.find('input:not([checkbox]):not([radio])').each(function(){
1865                var $input = $(this);
1866                if(typeof $input.attr('placeholder') !== typeof undefined){
1867                    if($input.attr('placeholder') === ""){
1868                        if($input.siblings('label').length){
1869                            $input.attr('placeholder', $input.siblings('label').first().text());
1870                            if(form.is('.form--no-labels')){   
1871                                $input.siblings('label').first().remove();
1872                            }
1873                        }
1874                    }
1875                }else if($input.siblings('label').length){
1876                    $input.attr('placeholder', $input.siblings('label').first().text()); 
1877                    if(form.is('.form--no-labels')){
1878                        $input.siblings('label').first().remove();
1879                    }
1880                }
1881                if($input.parent().is('p')){
1882                    $input.unwrap();
1883                }
1884            });
1885        }else{
1886            form.find('input[placeholder]').removeAttr('placeholder');
1887        }
1888
1889
1890    	// Wrap select elements in template code
1891
1892    	form.find('select').wrap('<div class="input-select"></div>');
1893
1894    	// Wrap radios elements in template code
1895
1896    	form.find('input[type="radio"]').wrap('<div class="input-radio"></div>');
1897
1898    	// Wrap checkbox elements in template code
1899
1900    	form.find('input[type="checkbox"]').each(function(){
1901    		checkbox = $(this);
1902    		id = checkbox.attr('id');
1903    		label = form.find('label[for='+id+']');
1904            if(!label.length){
1905                label = $('<label for="'+id+'"></label>');
1906            }
1907    		
1908    		checkbox.before('<div class="input-checkbox" data-id="'+id+'"></div>');
1909    		$('.input-checkbox[data-id="'+id+'"]').prepend(checkbox);
1910    		$('.input-checkbox[data-id="'+id+'"]').prepend(label);
1911    	});
1912
1913    	form.find('button[type="submit"]').each(function(){
1914            var button = $(this);
1915            button.addClass('btn');
1916            if(button.parent().is('p')){
1917                button.unwrap();
1918            }
1919        });
1920        
1921        form.find('[required]').attr('required', 'required').addClass('validate-required');
1922
1923        form.addClass('form--active');
1924
1925        mr.newsletters.prepareAjaxAction(form);
1926
1927
1928    });
1929
1930    // Treat MailChimp forms
1931    $('form[action*="list-manage.com"]').each(function(){
1932    	form = $(this);
1933
1934        // Override browser validation and allow us to use our own
1935        form.attr('novalidate', 'novalidate');
1936
1937    	// Give each text input a placeholder value
1938        if(!form.is('.form--no-placeholders')){
1939        	form.find('input:not([checkbox]):not([radio])').each(function(){
1940        		var $input = $(this);
1941                if(typeof $input.attr('placeholder') !== typeof undefined){
1942                    if($input.attr('placeholder') === ""){
1943                        if($input.siblings('label').length){
1944                            $input.attr('placeholder', $input.siblings('label').first().text());
1945                            if(form.is('.form--no-labels')){   
1946                                $input.siblings('label').first().remove();
1947                            }
1948                        }
1949                    }
1950                }else if($input.siblings('label').length){
1951                    $input.attr('placeholder', $input.siblings('label').first().text()); 
1952                    if(form.is('.form--no-labels')){
1953                        $input.siblings('label').first().remove();
1954                    }
1955                }
1956        	});
1957        }else{
1958            form.find('input[placeholder]').removeAttr('placeholder');
1959        }
1960
1961        if(form.is('.form--no-labels')){
1962            form.find('input:not([checkbox]):not([radio])').each(function(){
1963                var $input = $(this);
1964                if($input.siblings('label').length){
1965                    $input.siblings('label').first().remove();
1966                }
1967            });
1968        }
1969
1970    	// Wrap select elements in template code
1971
1972    	form.find('select').wrap('<div class="input-select"></div>');
1973
1974    	// Wrap checboxes elements in template code
1975
1976    	form.find('input[type="checkbox"]').each(function(){
1977    		checkbox = $(this);
1978    		parent = checkbox.parent();
1979    		label = parent.find('label');
1980            if(!label.length){
1981                label = $('<label></label>');
1982            }
1983    		checkbox.before('<div class="input-checkbox"></div>');
1984    		parent.find('.input-checkbox').append(checkbox);
1985    		parent.find('.input-checkbox').append(label);
1986    	});
1987
1988    	// Wrap radio elements in template code
1989
1990    	form.find('input[type="radio"]').each(function(){
1991    		radio = $(this);
1992    		parent = radio.closest('li');
1993    		label = parent.find('label');
1994            if(!label.length){
1995                label = $('<label></label>');
1996            }
1997    		radio.before('<div class="input-radio"></div>');
1998    		parent.find('.input-radio').prepend(radio);
1999    		parent.find('.input-radio').prepend(label);
2000    	});
2001
2002        // Convert MailChimp input[type="submit"] to div.button
2003
2004        form.find('input[type="submit"]').each(function(){
2005            var submit = $(this);
2006            
2007            var newButton = jQuery('<button/>').attr('type','submit').attr('class', submit.attr('class')).addClass('btn').text(submit.attr('value'));
2008            
2009            if(submit.parent().is('div.clear')){
2010                submit.unwrap();
2011            }
2012
2013            newButton.insertBefore(submit);
2014            submit.remove();
2015        });
2016
2017        form.find('input').each(function(){
2018            var input = $(this);
2019            if(input.hasClass('required')){
2020                input.removeClass('required').addClass('validate-required');
2021            }
2022        });
2023
2024        form.find('input[type="email"]').removeClass('email').addClass('validate-email');
2025
2026        form.find('#mce-responses').remove();
2027
2028        form.find('.mc-field-group').each(function(){
2029            $(this).children().first().unwrap();
2030        });
2031
2032        form.find('[required]').attr('required', 'required').addClass('validate-required');
2033
2034        form.addClass('form--active');
2035
2036        mr.newsletters.prepareAjaxAction(form);
2037
2038     
2039    
2040
2041    }); 
2042
2043	// Reinitialize the forms so interactions work as they should
2044
2045	mr.forms.documentReady(mr.setContext('form.form--active'));
2046		
2047  };
2048
2049  mr.newsletters.documentReady = documentReady;
2050
2051  mr.newsletters.prepareAjaxAction = function(form){
2052        var action = $(form).attr('action');
2053
2054        // Alter action for a Mail Chimp-compatible ajax request url.
2055        if(/list-manage\.com/.test(action)){
2056           action = action.replace('/post?', '/post-json?') + "&c=?";
2057           if(action.substr(0,2) === "//"){
2058               action = 'http:' + action;
2059           }
2060        }
2061
2062        // Alter action for a Campaign Monitor-compatible ajax request url.
2063        if(/createsend\.com/.test(action)){
2064           action = action + '?callback=?';
2065        }
2066
2067        // Set action on the form
2068        $(form).attr('action', action);
2069
2070    };
2071
2072
2073
2074  mr.components.documentReady.push(documentReady);
2075  return mr;
2076
2077}(mr, jQuery, window, document));
2078
2079//////////////// Notifications
2080mr = (function (mr, $, window, document){
2081    "use strict";
2082    
2083    mr.notifications = {};
2084
2085    var documentReady = function($){
2086        
2087        $('.notification').each(function(){
2088            var notification = $(this);
2089            if(!notification.find('.notification-close').length){
2090                notification.append('<div class="notification-close-cross notification-close"></div>');
2091            }
2092        });
2093    
2094
2095        $('.notification[data-autoshow]').each(function(){
2096            var notification = $(this);
2097            var millisecondsDelay = parseInt(notification.attr('data-autoshow'),10);
2098
2099            // If this notification has a cookie attribute, check to see if a cookie is set, and if so, don't show it.
2100            if(typeof notification.attr('data-cookie') !== typeof undefined){
2101                if(!mr.cookies.hasItem(notification.attr('data-cookie'))){
2102                    mr.notifications.showNotification(notification, millisecondsDelay);
2103                }
2104            }else{
2105                mr.notifications.showNotification(notification, millisecondsDelay);
2106            }
2107        });
2108
2109        $('[data-notification-link]:not(.notification)').on('click', function(){
2110            var notificationID = jQuery(this).attr('data-notification-link');
2111            var notification = $('.notification[data-notification-link="'+notificationID+'"]');
2112            jQuery('.notification--reveal').addClass('notification--dismissed');
2113            notification.removeClass('notification--dismissed');
2114            mr.notifications.showNotification(notification, 0);
2115            return false;
2116        });
2117
2118        $('.notification-close').on('click', function(){
2119            var closeButton = jQuery(this);
2120            // Pass the closeNotification function a reference to the close button
2121            mr.notifications.closeNotification(closeButton);
2122
2123            if(closeButton.attr('href') === '#'){
2124                return false;
2125            }
2126        });
2127
2128        $('.notification .inner-link').on('click', function(){
2129            var notificationLink = jQuery(this).closest('.notification').attr('data-notification-link');
2130            mr.notifications.closeNotification(notificationLink);
2131        });
2132    
2133    };
2134    
2135    mr.notifications.documentReady = documentReady;
2136
2137    mr.notifications.showNotification = function(notification, millisecondsDelay){
2138        var delay = (typeof millisecondsDelay !== typeof undefined) ? (1*millisecondsDelay) : 0;
2139        setTimeout(function(){
2140            notification.addClass('notification--reveal');
2141            notification.closest('nav').addClass('notification--reveal');
2142            if(notification.find('input').length){
2143                notification.find('input').first().focus();
2144            }
2145        },delay);
2146        // If notification has autohide attribute, set a timeout 
2147        // for the autohide time plus the original delay time in case notification was called
2148        // on page load
2149        if(notification.is('[data-autohide]')){
2150            var hideDelay = parseInt(notification.attr('data-autohide'),10);
2151            setTimeout(function(){
2152                mr.notifications.closeNotification(notification);
2153            },hideDelay+delay);
2154        }
2155    };
2156
2157    mr.notifications.closeNotification = function(notification){
2158        var $notification = jQuery(notification);
2159
2160        notification = $notification.is('.notification') ? 
2161                       $notification :
2162                       $notification.is('.notification-close') ? 
2163                       $notification.closest('.notification') : 
2164                       $('.notification[data-notification-link="'+notification+'"]');
2165        
2166        notification.addClass('notification--dismissed');
2167        notification.closest('nav').removeClass('notification--reveal');
2168
2169        // If this notification requires to be closed permanently using a cookie, set the cookie now.
2170        if(typeof notification.attr('data-cookie') !== typeof undefined){
2171            mr.cookies.setItem(notification.attr('data-cookie'), "true", Infinity, '/');
2172        }
2173    };
2174
2175    mr.components.documentReady.push(documentReady);
2176    return mr;
2177
2178}(mr, jQuery, window, document));
2179
2180//////////////// Parallax
2181mr = (function (mr, $, window, document){
2182    "use strict";
2183    
2184    var documentReady = function($){
2185        
2186        var $window      = $(window); 
2187        var windowWidth  = $window.width();
2188        var windowHeight = $window.height();
2189        var navHeight    = $('nav').outerHeight(true);
2190
2191        // Disable parallax on mobile
2192
2193        if ((/Android|iPhone|iPad|iPod|BlackBerry|Windows Phone/i).test(navigator.userAgent || navigator.vendor || window.opera)) {
2194            $('section').removeClass('parallax');
2195        }
2196
2197        if (windowWidth > 768) {
2198            var parallaxHero = $('.parallax:nth-of-type(1)'),
2199                parallaxHeroImage = $('.parallax:nth-of-type(1) .background-image-holder');
2200
2201            parallaxHeroImage.css('top', -(navHeight));
2202            if(parallaxHero.outerHeight(true) === windowHeight){
2203                parallaxHeroImage.css('height', windowHeight + navHeight);
2204            }
2205        }
2206    };
2207
2208    mr.parallax = {
2209        documentReady : documentReady        
2210    };
2211
2212    mr.components.documentReady.push(documentReady);
2213    return mr;
2214
2215}(mr, jQuery, window, document));
2216
2217//////////////// EasyPiecharts
2218mr = (function (mr, $, window, document){
2219	  "use strict";
2220
2221		mr.easypiecharts = {};
2222		mr.easypiecharts.pies = [];
2223
2224		var documentReady = function($){
2225
2226			mr.easypiecharts.init = function(){
2227
2228				mr.easypiecharts.pies = [];
2229            
2230				$('.radial').each(function(){
2231				  var pieObject  = {},
2232					  currentPie = jQuery(this);
2233
2234					  pieObject.element = currentPie;
2235					  pieObject.value = parseInt(currentPie.attr('data-value'),10);
2236					  pieObject.top = currentPie.offset().top;
2237					  pieObject.height = currentPie.height()/2;
2238					  pieObject.active = false;
2239					  mr.easypiecharts.pies.push(pieObject);
2240				});
2241			};
2242
2243			mr.easypiecharts.activate = function(){
2244				mr.easypiecharts.pies.forEach(function(pie){
2245					if(Math.round((mr.scroll.y + mr.window.height)) >= Math.round(pie.top+pie.height)){
2246						if(pie.active === false){
2247							
2248		                	pie.element.data('easyPieChart').enableAnimation();
2249		                	pie.element.data('easyPieChart').update(pie.value);
2250		                	pie.element.addClass('radial--active');
2251		                	pie.active = true;
2252						}
2253		            }
2254	        	});
2255			};
2256
2257		  	$('.radial').each(function(){
2258		  		var chart    = jQuery(this),
2259		  			value    = 0,
2260		  			color    = '#000000',
2261		  			time     = 2000,
2262		  			pieSize  = 110,
2263		  			barWidth = 3;
2264
2265		  		if(typeof chart.attr('data-timing') !== typeof undefined){
2266		  			time = chart.attr('data-timing')*1;
2267		  		}
2268		  		if(typeof chart.attr('data-color') !== typeof undefined){
2269		  			color = chart.attr('data-color');
2270		  		}
2271		  		if(typeof chart.attr('data-size') !== typeof undefined){
2272		  			pieSize = chart.attr('data-size');
2273		  		}
2274		  		if(typeof chart.attr('data-bar-width') !== typeof undefined){
2275		  			barWidth = chart.attr('data-bar-width');
2276		  		}
2277		  		chart.css('height',pieSize).css('width',pieSize);
2278
2279		  		chart.easyPieChart({
2280		  			animate: ({duration: time, enabled: true}),
2281		  			barColor: color,
2282		  			scaleColor: false,
2283		  			size: pieSize,
2284		  			lineWidth: barWidth
2285		  		});
2286		  		chart.data('easyPieChart').update(0);
2287		  	});
2288
2289		  	if($('.radial').length){
2290		  		mr.easypiecharts.init();
2291		  		mr.easypiecharts.activate();
2292		  		mr.scroll.listeners.push(mr.easypiecharts.activate);
2293		  	}
2294
2295	  };
2296
2297	  mr.easypiecharts.documentReady = documentReady;
2298
2299	  mr.components.documentReadyDeferred.push(documentReady);
2300	  return mr;
2301
2302}(mr, jQuery, window, document));
2303
2304//////////////// Flickity
2305mr = (function (mr, $, window, document){
2306    "use strict";
2307    
2308    mr.sliders = {};
2309    mr.sliders.draggable = true;
2310
2311    var documentReady = function($){
2312
2313        $('.slider').each(function(index){
2314            
2315            var slider = $(this);
2316            var sliderInitializer = slider.find('ul.slides');
2317            sliderInitializer.find('>li').addClass('slide');
2318            var childnum = sliderInitializer.find('li').length;
2319            var arrows = false;
2320            var paging = false;
2321            var timing = 7000;
2322            var autoplay = true;
2323            var draggable = mr.sliders.draggable;
2324            if(slider.attr('data-arrows') === 'true'){
2325                arrows = true;
2326            }else{
2327                arrows = false;
2328            }
2329            if(slider.attr('data-autoplay') === 'false'){
2330                autoplay = false;
2331            }else{
2332                autoplay = true;
2333            }
2334            if(slider.attr('data-paging') === 'true' && sliderInitializer.find('li').length > 1){
2335                paging = true;
2336            }else{
2337                paging = false;
2338            }
2339            if(slider.attr('data-timing')){
2340                timing = slider.attr('data-timing')*1;
2341            }
2342            // Set data attribute to inidicate the number of children in the slider
2343            slider.attr('data-children',childnum);
2344
2345            if(childnum < 2){
2346                draggable = false;
2347            }
2348
2349            $(sliderInitializer).flickity({
2350                cellSelector: '.slide',
2351                cellAlign: 'left',
2352                wrapAround: true,
2353                pageDots: paging,
2354                prevNextButtons: arrows,
2355                autoPlay: timing,
2356                draggable: draggable,
2357                imagesLoaded: true
2358            });
2359
2360            $(sliderInitializer).on( 'scroll.flickity', function( event, progress ) {
2361              if(slider.find('.is-selected').hasClass('controls--dark')){
2362                slider.addClass('controls--dark');
2363              }else{
2364                slider.removeClass('controls--dark'); 
2365              }
2366            });
2367        });
2368        
2369    };
2370
2371    mr.sliders.documentReady = documentReady;
2372
2373    mr.components.documentReadyDeferred.push(documentReady);
2374    return mr;
2375
2376}(mr, jQuery, window, document));
2377
2378//////////////// Smoothscroll
2379mr = (function (mr, $, window, document){
2380    "use strict";
2381    
2382    mr.smoothscroll = {};
2383    mr.smoothscroll.sections = [];
2384    
2385    mr.smoothscroll.init = function(){
2386        mr.smoothscroll.sections = [];
2387
2388       
2389
2390        $('a.inner-link').each(function(){
2391            var sectionObject = {},
2392                link          = $(this),
2393                href          = link.attr('href'),
2394                validLink     = new RegExp('^#[^\r\n\t\f\v\#\.]+$','gm');
2395                            
2396            if(validLink.test(href)){
2397                
2398                if($('section'+href).length){
2399
2400                    sectionObject.id     = href;
2401                    sectionObject.top = Math.round($(href).offset().top);
2402                    sectionObject.height = Math.round($(href).outerHeight());
2403                    sectionObject.link   = link.get(0);
2404                    sectionObject.active = false;
2405
2406                    mr.smoothscroll.sections.push(sectionObject);
2407                }
2408            }
2409        });
2410
2411        mr.smoothscroll.highlight();
2412    };
2413
2414    mr.smoothscroll.highlight = function(){
2415        mr.smoothscroll.sections.forEach(function(section){
2416            if(mr.scroll.y >= section.top && mr.scroll.y < (section.top + section.height)){
2417                if(section.active === false){
2418                    section.link.classList.add("inner-link--active");
2419                    section.active = true;
2420                }
2421            }else{
2422                section.link.classList.remove("inner-link--active");
2423                section.active = false;
2424            }
2425        });
2426    };
2427
2428    mr.scroll.listeners.push(mr.smoothscroll.highlight);
2429
2430    var documentReady = function($){
2431        // Smooth scroll to inner links
2432        var innerLinks = $('a.inner-link');
2433
2434        if(innerLinks.length){
2435            innerLinks.each(function(index){
2436                var link          = $(this),
2437                    href          = link.attr('href');
2438                if(href.charAt(0) !== "#"){
2439                    link.removeClass('inner-link');
2440                }
2441            });
2442
2443            mr.smoothscroll.init();
2444            $(window).on('resize', mr.smoothscroll.init);
2445
2446            var offset = 0;
2447            if($('body[data-smooth-scroll-offset]').length){
2448                offset = $('body').attr('data-smooth-scroll-offset');
2449                offset = offset*1;
2450            }
2451            
2452            smoothScroll.init({
2453                selector: '.inner-link',
2454                selectorHeader: null,
2455                speed: 750,
2456                easing: 'easeInOutCubic',
2457                offset: offset
2458            });
2459        }
2460    };
2461
2462    mr.smoothscroll.documentReady = documentReady;
2463
2464    mr.components.documentReady.push(documentReady);
2465    mr.components.windowLoad.push(mr.smoothscroll.init);
2466    return mr;
2467
2468}(mr, jQuery, window, document));
2469
2470//////////////// Tabs
2471mr = (function (mr, $, window, document){
2472    "use strict";
2473
2474    mr.tabs = {};
2475    
2476    var documentReady = function($){
2477        $('.tabs').each(function(){
2478            var tabs = $(this);
2479            tabs.after('<ul class="tabs-content">');
2480            tabs.find('li').each(function(){
2481                var currentTab      = $(this),
2482                    tabContent      = currentTab.find('.tab__content').wrap('<li></li>').parent(),
2483                    tabContentClone = tabContent.clone(true,true);
2484                tabContent.remove();
2485                currentTab.closest('.tabs-container').find('.tabs-content').append(tabContentClone);
2486            });
2487        });
2488        
2489        $('.tabs > li').on('click', function(){
2490            var clickedTab = $(this), hash;
2491            mr.tabs.activateTab(clickedTab);
2492
2493            // Update the URL bar if the currently clicked tab has an ID
2494            if(clickedTab.is('[id]')){
2495                // Create the hash from the tab's ID
2496                hash = '#'+ clickedTab.attr('id');
2497                // Check we are in a newish browser with the history API
2498                if(history.pushState) {
2499                    history.pushState(null, null, hash);
2500                }
2501                else {
2502                    location.hash = hash;
2503                }
2504            }
2505        });
2506
2507        $('.tabs li.active').each(function(){
2508            mr.tabs.activateTab(this);
2509        });
2510
2511        if(window.location.hash !== ''){
2512            mr.tabs.activateTabById(window.location.hash);
2513        }
2514
2515        $('a[href^="#"]').on('click', function(){
2516            mr.tabs.activateTabById($(this).attr('href'));
2517        });
2518
2519    };
2520
2521    mr.tabs.activateTab = function(tab){
2522        var clickedTab    = $(tab),
2523            tabContainer  = clickedTab.closest('.tabs-container'),
2524            activeIndex   = (clickedTab.index()*1)+(1),
2525            activeContent = tabContainer.find('> .tabs-content > li:nth-of-type('+activeIndex+')'),
2526            openEvent     = document.createEvent('Event'),
2527            iframe, radial;
2528
2529            openEvent.initEvent('tabOpened.tabs.mr', true, true);
2530
2531
2532        tabContainer.find('> .tabs > li').removeClass('active');
2533        tabContainer.find('> .tabs-content > li').removeClass('active');
2534        
2535        clickedTab.addClass('active').trigger('tabOpened.tabs.mr').get(0).dispatchEvent(openEvent);
2536        activeContent.addClass('active');
2537
2538        
2539
2540        // If there is an <iframe> element in the tab, reload its content when the tab is made active.
2541        iframe = activeContent.find('iframe');
2542        if(iframe.length){
2543            iframe.attr('src', iframe.attr('src'));
2544        }
2545    };
2546
2547
2548
2549    mr.tabs.activateTabById = function(id){
2550        if(id !== '' && id !== '#'){
2551            $('.tabs > li#'+id.replace('#', '')).click();
2552        }
2553    };
2554
2555    mr.tabs.documentReady = documentReady;
2556    mr.components.documentReady.push(documentReady);
2557    return mr;
2558
2559}(mr, jQuery, window, document));
2560
2561//////////////// Toggle Class
2562mr = (function (mr, $, window, document){
2563    "use strict";
2564    
2565    var documentReady = function($){
2566        $('[data-toggle-class]').each(function(){
2567        	var element = $(this),
2568                data    = element.attr('data-toggle-class').split("|");
2569        		
2570
2571            $(data).each(function(){
2572                var candidate     = element,
2573                    dataArray     = [],
2574            	    toggleClass   = '',
2575            	    toggleElement = '',
2576                    dataArray = this.split(";");
2577
2578            	if(dataArray.length === 2){
2579            		toggleElement = dataArray[0];
2580            		toggleClass   = dataArray[1];
2581            		$(candidate).on('click',function(){
2582                        if(!candidate.hasClass('toggled-class')){
2583                            candidate.toggleClass('toggled-class');
2584                        }else{
2585                            candidate.removeClass('toggled-class');
2586                        }
2587            			$(toggleElement).toggleClass(toggleClass);
2588            			return false;
2589            		});
2590            	}else{
2591            		console.log('Error in [data-toggle-class] attribute. This attribute accepts an element, or comma separated elements terminated witha ";" followed by a class name to toggle');
2592            	}
2593            });
2594        });
2595    };
2596
2597    mr.toggleClass = {
2598        documentReady : documentReady        
2599    };
2600
2601    mr.components.documentReady.push(documentReady);
2602    return mr;
2603
2604}(mr, jQuery, window, document));
2605
2606//////////////// Typed Headline Effect
2607mr = (function (mr, $, window, document){
2608    "use strict";
2609    
2610    var documentReady = function($){
2611        $('.typed-text').each(function(){
2612            var text = $(this);
2613            var strings = text.attr("data-typed-strings") ? text.attr("data-typed-strings").split(",") : [];
2614            $(text).typed({
2615                strings: strings,
2616                typeSpeed: 100,
2617                loop: true,
2618                showCursor: false
2619            });
2620        });
2621    };
2622
2623    mr.typed = {
2624        documentReady : documentReady        
2625    };
2626
2627    mr.components.documentReady.push(documentReady);
2628    return mr;
2629
2630}(mr, jQuery, window, document));
2631
2632//////////////// Twitter Feeds
2633mr = (function (mr, $, window, document){
2634    "use strict";
2635    
2636    var documentReady = function($){
2637        $('.tweets-feed').each(function(index) {
2638            $(this).attr('id', 'tweets-' + index);
2639        }).each(function(index) {
2640            var element = $('#tweets-' + index);
2641            var TweetConfig = {
2642               "domId": '',
2643               "maxTweets": element.attr('data-amount'),
2644               "enableLinks": true,
2645               "showUser": true,
2646               "showTime": true,
2647               "dateFunction": '',
2648               "showRetweet": false,
2649               "customCallback": handleTweets
2650            };
2651
2652            if(typeof element.attr('data-widget-id') !== typeof undefined){
2653                TweetConfig.id = element.attr('data-widget-id');
2654            }else if(typeof element.attr('data-feed-name') !== typeof undefined && element.attr('data-feed-name') !== ""){
2655                TweetConfig.profile = {"screenName": element.attr('data-feed-name').replace('@', '')};
2656            }else{
2657                TweetConfig.profile = {"screenName": 'twitter'};
2658            }
2659
2660            if(element.closest('.twitter-feed--slider').length){
2661                element.addClass('slider');
2662            }
2663
2664            function handleTweets(tweets) {
2665                var x = tweets.length;
2666                var n = 0;
2667                var html = '<ul class="slides">';
2668                while (n < x) {
2669                    html += '<li>' + tweets[n] + '</li>';
2670                    n++;
2671                }
2672                html += '</ul>';
2673                element.html(html);
2674                
2675                // Initialize twitter feed slider
2676                if(element.closest('.slider').length){
2677                    mr.sliders.documentReady(mr.setContext());
2678                     
2679                    return html;
2680                }
2681            }
2682            twitterFetcher.fetch(TweetConfig);
2683        });
2684    };
2685
2686    mr.twitter = {
2687        documentReady : documentReady
2688    };
2689
2690    mr.components.documentReady.push(documentReady);
2691
2692    return mr;
2693
2694}(mr, jQuery, window, document));
2695
2696//////////////// Video
2697mr = (function (mr, $, window, document){
2698    "use strict";
2699    
2700	  var documentReady = function($){
2701	      
2702			//////////////// Youtube Background
2703
2704			if($('.youtube-background').length){
2705				$('.youtube-background').each(function(){
2706					var player = $(this);
2707					var vidURL = $(this).attr('data-video-url');
2708					var startAt = $(this).attr('data-start-at');
2709					player.attr('data-property','{videoURL:"'+vidURL+'",containment:"self",autoPlay:true, mute:true, startAt:'+startAt+', opacity:1}');
2710					player.closest('.videobg').append('<div class="loading-indicator"></div>');
2711					player.YTPlayer();
2712					player.on("YTPStart",function(){
2713				  		player.closest('.videobg').addClass('video-active');
2714					});	
2715				});
2716			}
2717
2718			if($('.videobg').find('video').length){
2719				$('.videobg').find('video').closest('.videobg').addClass('video-active');
2720			} 
2721
2722			//////////////// Video Cover Play Icons
2723
2724			$('.video-cover').each(function(){
2725			    var videoCover = $(this);
2726			    if(videoCover.find('iframe').length){
2727			        videoCover.find('iframe').attr('data-src', videoCover.find('iframe').attr('src'));
2728			        videoCover.find('iframe').attr('src','');
2729			    }
2730			});
2731
2732			$('.video-cover .video-play-icon').on("click", function(){
2733			    var playIcon = $(this);
2734			    var videoCover = playIcon.closest('.video-cover');
2735			    if(videoCover.find('video').length){
2736			        var video = videoCover.find('video').get(0);
2737			        videoCover.addClass('reveal-video');
2738			        video.play();
2739			        return false;
2740			    }else if(videoCover.find('iframe').length){
2741			        var iframe = videoCover.find('iframe');
2742			        iframe.attr('src',iframe.attr('data-src'));
2743			        videoCover.addClass('reveal-video');
2744			        return false;
2745			    }
2746			});
2747	  };
2748
2749	  mr.video = {
2750	      documentReady : documentReady        
2751	  };
2752
2753	  mr.components.documentReady.push(documentReady);
2754	  return mr;
2755
2756}(mr, jQuery, window, document));
2757
2758//////////////// Wizard
2759mr = (function (mr, $, window, document){
2760    "use strict";
2761    
2762	  var documentReady = function($){
2763
2764		$('.wizard').each(function(){
2765			var wizard = jQuery(this);
2766			wizard.steps({
2767				headerTag: "h5",
2768				bodyTag: "section",
2769				transitionEffect: "slideLeft",
2770				autoFocus: true
2771			});
2772			wizard.addClass('active');
2773		});
2774			
2775	  };
2776
2777	  mr.wizard = {
2778	      documentReady : documentReady        
2779	  };
2780
2781	  mr.components.documentReady.push(documentReady);
2782	  return mr;
2783
2784}(mr, jQuery, window, document));
2785
2786
2787$(function() {
2788    $('#meals-menu .row .feature__body').matchHeight();
2789});

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.