PageSourceSearch

https://gethue.com//js/scripts.js

js gethue.com collected 2026-10-01 10:28:42 UTC 107,496 bytes, 2,899 lines download raw bytes

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

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.