scripts.js 110 KB

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