script.js 54 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536153715381539154015411542154315441545154615471548154915501551155215531554155515561557155815591560156115621563156415651566156715681569157015711572157315741575157615771578157915801581158215831584158515861587158815891590159115921593159415951596159715981599160016011602160316041605160616071608160916101611161216131614161516161617161816191620162116221623162416251626162716281629163016311632163316341635163616371638163916401641164216431644164516461647164816491650165116521653165416551656165716581659166016611662166316641665166616671668166916701671167216731674167516761677167816791680168116821683168416851686168716881689169016911692169316941695169616971698169917001701
  1. "use strict";
  2. (function () {
  3. // Global variables
  4. var userAgent = navigator.userAgent.toLowerCase(),
  5. initialDate = new Date(),
  6. $document = $(document),
  7. $window = $(window),
  8. $html = $("html"),
  9. $body = $("body"),
  10. isDesktop = $html.hasClass("desktop"),
  11. isIE = userAgent.indexOf("msie") !== -1 ? parseInt(userAgent.split("msie")[1], 10) : userAgent.indexOf("trident") !== -1 ? 11 : userAgent.indexOf("edge") !== -1 ? 12 : false,
  12. isMobile = /Android|webOS|iPhone|iPad|iPod|BlackBerry|IEMobile|Opera Mini/i.test(navigator.userAgent),
  13. windowReady = false,
  14. isNoviBuilder = false,
  15. livedemo = false,
  16. plugins = {
  17. bootstrapTooltip: $( '[data-toggle="tooltip"]' ),
  18. bootstrapTabs: $( '.tabs-custom' ),
  19. customToggle: $( '[data-custom-toggle]' ),
  20. counter: $( '.counter' ),
  21. countDown: $( '[data-circle-countdown]' ),
  22. captcha: $( '.recaptcha' ),
  23. campaignMonitor: $( '.campaign-mailform' ),
  24. copyrightYear: $( '.copyright-year' ),
  25. checkbox: $( 'input[type="checkbox"]' ),
  26. isotope: $( '.isotope-wrap' ),
  27. lightGallery: $( '[data-lightgallery="group"]' ),
  28. lightGalleryItem: $( '[data-lightgallery="item"]' ),
  29. lightDynamicGalleryItem: $( '[data-lightgallery="dynamic"]' ),
  30. maps: $( '.google-map-container' ),
  31. materialParallax: $( '.parallax-container' ),
  32. mailchimp: $( '.mailchimp-mailform' ),
  33. multitoggle: document.querySelectorAll( '[data-multitoggle]' ),
  34. owl: $( '.owl-carousel' ),
  35. progressLinear: $( '.progress-linear' ),
  36. preloader: $( '.preloader' ),
  37. rdNavbar: $( '.rd-navbar' ),
  38. rdMailForm: $( '.rd-mailform' ),
  39. rdInputLabel: $( '.form-label' ),
  40. regula: $( '[data-constraints]' ),
  41. radio: $( 'input[type="radio"]' ),
  42. rdRange: $( '.rd-range' ),
  43. radioPanel: $( '.radio-panel .radio-inline' ),
  44. swiper: document.querySelectorAll( '.swiper-container' ),
  45. selectFilter: $( 'select' ),
  46. slick: $( '.slick-slider' ),
  47. stepper: $( 'input[type="number"]' ),
  48. search: $( '.rd-search' ),
  49. searchResults: $( '.rd-search-results' ),
  50. wow: $( '.wow' )
  51. };
  52. /**
  53. * @desc Check the element was been scrolled into the view
  54. * @param {object} elem - jQuery object
  55. * @return {boolean}
  56. */
  57. function isScrolledIntoView ( elem ) {
  58. if ( isNoviBuilder ) return true;
  59. return elem.offset().top + elem.outerHeight() >= $window.scrollTop() && elem.offset().top <= $window.scrollTop() + $window.height();
  60. }
  61. /**
  62. * @desc Calls a function when element has been scrolled into the view
  63. * @param {object} element - jQuery object
  64. * @param {function} func - init function
  65. */
  66. function lazyInit( element, func ) {
  67. var scrollHandler = function () {
  68. if ( ( !element.hasClass( 'lazy-loaded' ) && ( isScrolledIntoView( element ) ) ) ) {
  69. func.call( element );
  70. element.addClass( 'lazy-loaded' );
  71. }
  72. };
  73. scrollHandler();
  74. $window.on( 'scroll', scrollHandler );
  75. }
  76. // Initialize scripts that require a loaded page
  77. $window.on('load', function () {
  78. // Page loader & Page transition
  79. if (plugins.preloader.length && !isNoviBuilder) {
  80. pageTransition({
  81. target: document.querySelector( '.page' ),
  82. delay: 0,
  83. duration: 500,
  84. classIn: 'fadeIn',
  85. classOut: 'fadeOut',
  86. classActive: 'animated',
  87. conditions: function (event, link) {
  88. return !/(\#|callto:|tel:|mailto:|:\/\/)/.test(link) && !event.currentTarget.hasAttribute('data-lightgallery');
  89. },
  90. onTransitionStart: function ( options ) {
  91. setTimeout( function () {
  92. plugins.preloader.removeClass('loaded');
  93. }, options.duration * .75 );
  94. },
  95. onReady: function () {
  96. plugins.preloader.addClass('loaded');
  97. windowReady = true;
  98. }
  99. });
  100. }
  101. // jQuery Count To
  102. if ( plugins.counter.length ) {
  103. for ( var i = 0; i < plugins.counter.length; i++ ) {
  104. var
  105. counter = $(plugins.counter[i]),
  106. initCount = function () {
  107. var counter = $(this);
  108. if ( !counter.hasClass( "animated-first" ) && isScrolledIntoView( counter ) ) {
  109. counter.countTo({
  110. refreshInterval: 40,
  111. speed: counter.attr("data-speed") || 1000,
  112. from: 0,
  113. to: parseInt( counter.text(), 10 )
  114. });
  115. counter.addClass('animated-first');
  116. }
  117. };
  118. $.proxy( initCount, counter )();
  119. $window.on( "scroll", $.proxy( initCount, counter ) );
  120. }
  121. }
  122. // Progress bar
  123. if ( plugins.progressLinear.length ) {
  124. for ( var i = 0; i < plugins.progressLinear.length; i++) {
  125. var
  126. bar = $(plugins.progressLinear[i]),
  127. initProgress = function() {
  128. var
  129. bar = $(this),
  130. end = parseInt($(this).find('.progress-value').text(), 10);
  131. if ( !bar.hasClass( "animated-first" ) && isScrolledIntoView( bar ) ) {
  132. bar.find('.progress-bar-linear').css({width: end + '%'});
  133. bar.find('.progress-value').countTo({
  134. refreshInterval: 40,
  135. from: 0,
  136. to: end,
  137. speed: 1000
  138. });
  139. bar.addClass('animated-first');
  140. }
  141. };
  142. $.proxy( initProgress, bar )();
  143. $window.on( "scroll", $.proxy( initProgress, bar ) );
  144. }
  145. }
  146. // SVG Countdown
  147. if( plugins.countDown.length ) {
  148. svgCountDown({
  149. tickInterval: 100,
  150. counterSelector: '.countdown-counter'
  151. });
  152. }
  153. // Isotope
  154. if ( plugins.isotope.length ) {
  155. for ( var i = 0; i < plugins.isotope.length; i++ ) {
  156. var
  157. wrap = plugins.isotope[ i ],
  158. filterHandler = function ( event ) {
  159. event.preventDefault();
  160. for ( var n = 0; n < this.isoGroup.filters.length; n++ ) this.isoGroup.filters[ n ].classList.remove( 'active' );
  161. this.classList.add( 'active' );
  162. this.isoGroup.isotope.arrange( { filter: this.getAttribute( "data-isotope-filter" ) !== '*' ? '[data-filter*="' + this.getAttribute( "data-isotope-filter" ) + '"]' : '*' } );
  163. },
  164. resizeHandler = function () {
  165. this.isoGroup.isotope.layout();
  166. };
  167. wrap.isoGroup = {};
  168. wrap.isoGroup.filters = wrap.querySelectorAll( '[data-isotope-filter]' );
  169. wrap.isoGroup.node = wrap.querySelector( '.isotope' );
  170. wrap.isoGroup.layout = wrap.isoGroup.node.getAttribute( 'data-isotope-layout' ) ? wrap.isoGroup.node.getAttribute( 'data-isotope-layout' ) : 'masonry';
  171. wrap.isoGroup.isotope = new Isotope( wrap.isoGroup.node, {
  172. itemSelector: '.isotope-item',
  173. layoutMode: wrap.isoGroup.layout,
  174. filter: '*',
  175. masonry: {
  176. columnWidth: '.col-1'
  177. }
  178. } );
  179. $('.isotope-filters-toggle').on('click', function(){
  180. $('.isotope-filters-list').toggleClass('active');
  181. });
  182. for ( var n = 0; n < wrap.isoGroup.filters.length; n++ ) {
  183. var filter = wrap.isoGroup.filters[ n ];
  184. filter.isoGroup = wrap.isoGroup;
  185. filter.addEventListener( 'click', filterHandler );
  186. }
  187. window.addEventListener( 'resize', resizeHandler.bind( wrap ) );
  188. }
  189. }
  190. // Material Parallax
  191. if ( plugins.materialParallax.length ) {
  192. if ( !isNoviBuilder && !isIE && !isMobile) {
  193. plugins.materialParallax.parallax();
  194. } else {
  195. for ( var i = 0; i < plugins.materialParallax.length; i++ ) {
  196. var $parallax = $(plugins.materialParallax[i]);
  197. $parallax.addClass( 'parallax-disabled' );
  198. $parallax.css({ "background-image": 'url('+ $parallax.data("parallax-img") +')' });
  199. }
  200. }
  201. }
  202. });
  203. // Initialize scripts that require a finished document
  204. $(function () {
  205. isNoviBuilder = window.xMode;
  206. /**
  207. * @desc Initialize owl carousel plugin
  208. * @param {object} c - carousel jQuery object
  209. */
  210. function initOwlCarousel(c) {
  211. var aliaces = ["-", "-sm-", "-md-", "-lg-", "-xl-", "-xxl-"],
  212. values = [0, 576, 768, 992, 1200, 1600],
  213. responsive = {};
  214. for (var j = 0; j < values.length; j++) {
  215. responsive[values[j]] = {};
  216. for (var k = j; k >= -1; k--) {
  217. if (!responsive[values[j]]["items"] && c.attr("data" + aliaces[k] + "items")) {
  218. responsive[values[j]]["items"] = k < 0 ? 1 : parseInt(c.attr("data" + aliaces[k] + "items"), 10);
  219. }
  220. if (!responsive[values[j]]["stagePadding"] && responsive[values[j]]["stagePadding"] !== 0 && c.attr("data" + aliaces[k] + "stage-padding")) {
  221. responsive[values[j]]["stagePadding"] = k < 0 ? 0 : parseInt(c.attr("data" + aliaces[k] + "stage-padding"), 10);
  222. }
  223. if (!responsive[values[j]]["margin"] && responsive[values[j]]["margin"] !== 0 && c.attr("data" + aliaces[k] + "margin")) {
  224. responsive[values[j]]["margin"] = k < 0 ? 30 : parseInt(c.attr("data" + aliaces[k] + "margin"), 10);
  225. }
  226. }
  227. }
  228. // Enable custom pagination
  229. if (c.attr('data-dots-custom')) {
  230. c.on("initialized.owl.carousel", function (event) {
  231. var carousel = $(event.currentTarget),
  232. customPag = $(carousel.attr("data-dots-custom")),
  233. active = 0;
  234. if (carousel.attr('data-active')) {
  235. active = parseInt(carousel.attr('data-active'), 10);
  236. }
  237. carousel.trigger('to.owl.carousel', [active, 300, true]);
  238. customPag.find("[data-owl-item='" + active + "']").addClass("active");
  239. customPag.find("[data-owl-item]").on('click', function (e) {
  240. e.preventDefault();
  241. carousel.trigger('to.owl.carousel', [parseInt(this.getAttribute("data-owl-item"), 10), 300, true]);
  242. });
  243. carousel.on("translate.owl.carousel", function (event) {
  244. customPag.find(".active").removeClass("active");
  245. customPag.find("[data-owl-item='" + event.item.index + "']").addClass("active")
  246. });
  247. });
  248. }
  249. c.on("initialized.owl.carousel", function () {
  250. initLightGalleryItem(c.find('[data-lightgallery="item"]'), 'lightGallery-in-carousel');
  251. });
  252. c.owlCarousel({
  253. autoplay: isNoviBuilder ? false : c.attr("data-autoplay") === "true",
  254. loop: isNoviBuilder ? false : c.attr("data-loop") !== "false",
  255. items: 1,
  256. center: c.attr("data-center") === "true",
  257. dotsContainer: c.attr("data-pagination-class") || false,
  258. navContainer: c.attr("data-navigation-class") || false,
  259. mouseDrag: isNoviBuilder ? false : c.attr("data-mouse-drag") !== "false",
  260. nav: c.attr("data-nav") === "true",
  261. dots: c.attr("data-dots") === "true",
  262. dotsEach: c.attr("data-dots-each") ? parseInt(c.attr("data-dots-each"), 10) : false,
  263. animateIn: c.attr('data-animation-in') ? c.attr('data-animation-in') : false,
  264. animateOut: c.attr('data-animation-out') ? c.attr('data-animation-out') : false,
  265. responsive: responsive,
  266. smartSpeed: c.attr('data-smart-speed') ? c.attr('data-smart-speed') : 250,
  267. navText: c.attr("data-nav-text") ? $.parseJSON( c.attr("data-nav-text") ) : [],
  268. navClass: c.attr("data-nav-class") ? $.parseJSON( c.attr("data-nav-class") ) : ['owl-prev', 'owl-next']
  269. });
  270. }
  271. /**
  272. * @desc Create live search results
  273. * @param {object} options
  274. */
  275. function liveSearch(options) {
  276. $('#' + options.live).removeClass('cleared').html();
  277. options.current++;
  278. options.spin.addClass('loading');
  279. $.get(handler, {
  280. s: decodeURI(options.term),
  281. liveSearch: options.live,
  282. dataType: "html",
  283. liveCount: options.liveCount,
  284. filter: options.filter,
  285. template: options.template
  286. }, function (data) {
  287. options.processed++;
  288. var live = $('#' + options.live);
  289. if ((options.processed === options.current) && !live.hasClass('cleared')) {
  290. live.find('> #search-results').removeClass('active');
  291. live.html(data);
  292. setTimeout(function () {
  293. live.find('> #search-results').addClass('active');
  294. }, 50);
  295. }
  296. options.spin.parents('.rd-search').find('.input-group-addon').removeClass('loading');
  297. })
  298. }
  299. /**
  300. * @desc Attach form validation to elements
  301. * @param {object} elements - jQuery object
  302. */
  303. function attachFormValidator(elements) {
  304. // Custom validator - phone number
  305. regula.custom({
  306. name: 'PhoneNumber',
  307. defaultMessage: 'Invalid phone number format',
  308. validator: function() {
  309. if ( this.value === '' ) return true;
  310. else return /^(\+\d)?[0-9\-\(\) ]{5,}$/i.test( this.value );
  311. }
  312. });
  313. for (var i = 0; i < elements.length; i++) {
  314. var o = $(elements[i]), v;
  315. o.addClass("form-control-has-validation").after("<span class='form-validation'></span>");
  316. v = o.parent().find(".form-validation");
  317. if (v.is(":last-child")) o.addClass("form-control-last-child");
  318. }
  319. elements.on('input change propertychange blur', function (e) {
  320. var $this = $(this), results;
  321. if (e.type !== "blur") if (!$this.parent().hasClass("has-error")) return;
  322. if ($this.parents('.rd-mailform').hasClass('success')) return;
  323. if (( results = $this.regula('validate') ).length) {
  324. for (i = 0; i < results.length; i++) {
  325. $this.siblings(".form-validation").text(results[i].message).parent().addClass("has-error");
  326. }
  327. } else {
  328. $this.siblings(".form-validation").text("").parent().removeClass("has-error")
  329. }
  330. }).regula('bind');
  331. var regularConstraintsMessages = [
  332. {
  333. type: regula.Constraint.Required,
  334. newMessage: "The text field is required."
  335. },
  336. {
  337. type: regula.Constraint.Email,
  338. newMessage: "The email is not a valid email."
  339. },
  340. {
  341. type: regula.Constraint.Numeric,
  342. newMessage: "Only numbers are required"
  343. },
  344. {
  345. type: regula.Constraint.Selected,
  346. newMessage: "Please choose an option."
  347. }
  348. ];
  349. for (var i = 0; i < regularConstraintsMessages.length; i++) {
  350. var regularConstraint = regularConstraintsMessages[i];
  351. regula.override({
  352. constraintType: regularConstraint.type,
  353. defaultMessage: regularConstraint.newMessage
  354. });
  355. }
  356. }
  357. /**
  358. * @desc Check if all elements pass validation
  359. * @param {object} elements - object of items for validation
  360. * @param {object} captcha - captcha object for validation
  361. * @return {boolean}
  362. */
  363. function isValidated(elements, captcha) {
  364. var results, errors = 0;
  365. if (elements.length) {
  366. for (var j = 0; j < elements.length; j++) {
  367. var $input = $(elements[j]);
  368. if ((results = $input.regula('validate')).length) {
  369. for (k = 0; k < results.length; k++) {
  370. errors++;
  371. $input.siblings(".form-validation").text(results[k].message).parent().addClass("has-error");
  372. }
  373. } else {
  374. $input.siblings(".form-validation").text("").parent().removeClass("has-error")
  375. }
  376. }
  377. if (captcha) {
  378. if (captcha.length) {
  379. return validateReCaptcha(captcha) && errors === 0
  380. }
  381. }
  382. return errors === 0;
  383. }
  384. return true;
  385. }
  386. /**
  387. * @desc Validate google reCaptcha
  388. * @param {object} captcha - captcha object for validation
  389. * @return {boolean}
  390. */
  391. function validateReCaptcha(captcha) {
  392. var captchaToken = captcha.find('.g-recaptcha-response').val();
  393. if (captchaToken.length === 0) {
  394. captcha
  395. .siblings('.form-validation')
  396. .html('Please, prove that you are not robot.')
  397. .addClass('active');
  398. captcha
  399. .closest('.form-wrap')
  400. .addClass('has-error');
  401. captcha.on('propertychange', function () {
  402. var $this = $(this),
  403. captchaToken = $this.find('.g-recaptcha-response').val();
  404. if (captchaToken.length > 0) {
  405. $this
  406. .closest('.form-wrap')
  407. .removeClass('has-error');
  408. $this
  409. .siblings('.form-validation')
  410. .removeClass('active')
  411. .html('');
  412. $this.off('propertychange');
  413. }
  414. });
  415. return false;
  416. }
  417. return true;
  418. }
  419. /**
  420. * @desc Initialize Google reCaptcha
  421. */
  422. window.onloadCaptchaCallback = function () {
  423. for (var i = 0; i < plugins.captcha.length; i++) {
  424. var
  425. $captcha = $(plugins.captcha[i]),
  426. resizeHandler = (function() {
  427. var
  428. frame = this.querySelector( 'iframe' ),
  429. inner = this.firstElementChild,
  430. inner2 = inner.firstElementChild,
  431. containerRect = null,
  432. frameRect = null,
  433. scale = null;
  434. inner2.style.transform = '';
  435. inner.style.height = 'auto';
  436. inner.style.width = 'auto';
  437. containerRect = this.getBoundingClientRect();
  438. frameRect = frame.getBoundingClientRect();
  439. scale = containerRect.width/frameRect.width;
  440. if ( scale < 1 ) {
  441. inner2.style.transform = 'scale('+ scale +')';
  442. inner.style.height = ( frameRect.height * scale ) + 'px';
  443. inner.style.width = ( frameRect.width * scale ) + 'px';
  444. }
  445. }).bind( plugins.captcha[i] );
  446. grecaptcha.render(
  447. $captcha.attr('id'),
  448. {
  449. sitekey: $captcha.attr('data-sitekey'),
  450. size: $captcha.attr('data-size') ? $captcha.attr('data-size') : 'normal',
  451. theme: $captcha.attr('data-theme') ? $captcha.attr('data-theme') : 'light',
  452. callback: function () {
  453. $('.recaptcha').trigger('propertychange');
  454. }
  455. }
  456. );
  457. $captcha.after("<span class='form-validation'></span>");
  458. if ( plugins.captcha[i].hasAttribute( 'data-auto-size' ) ) {
  459. resizeHandler();
  460. window.addEventListener( 'resize', resizeHandler );
  461. }
  462. }
  463. };
  464. /**
  465. * @desc Initialize Bootstrap tooltip with required placement
  466. * @param {string} tooltipPlacement
  467. */
  468. function initBootstrapTooltip(tooltipPlacement) {
  469. plugins.bootstrapTooltip.tooltip('dispose');
  470. if (window.innerWidth < 576) {
  471. plugins.bootstrapTooltip.tooltip({placement: 'bottom'});
  472. } else {
  473. plugins.bootstrapTooltip.tooltip({placement: tooltipPlacement});
  474. }
  475. }
  476. /**
  477. * @desc Initialize the gallery with set of images
  478. * @param {object} itemsToInit - jQuery object
  479. * @param {string} addClass - additional gallery class
  480. */
  481. function initLightGallery(itemsToInit, addClass) {
  482. if (!isNoviBuilder) {
  483. $(itemsToInit).lightGallery({
  484. thumbnail: $(itemsToInit).attr("data-lg-thumbnail") !== "false",
  485. selector: "[data-lightgallery='item']",
  486. autoplay: $(itemsToInit).attr("data-lg-autoplay") === "true",
  487. pause: parseInt($(itemsToInit).attr("data-lg-autoplay-delay")) || 5000,
  488. addClass: addClass,
  489. mode: $(itemsToInit).attr("data-lg-animation") || "lg-slide",
  490. loop: $(itemsToInit).attr("data-lg-loop") !== "false"
  491. });
  492. }
  493. }
  494. /**
  495. * @desc Initialize the gallery with dynamic addition of images
  496. * @param {object} itemsToInit - jQuery object
  497. * @param {string} addClass - additional gallery class
  498. */
  499. function initDynamicLightGallery(itemsToInit, addClass) {
  500. if (!isNoviBuilder) {
  501. $(itemsToInit).on("click", function () {
  502. $(itemsToInit).lightGallery({
  503. thumbnail: $(itemsToInit).attr("data-lg-thumbnail") !== "false",
  504. selector: "[data-lightgallery='item']",
  505. autoplay: $(itemsToInit).attr("data-lg-autoplay") === "true",
  506. pause: parseInt($(itemsToInit).attr("data-lg-autoplay-delay")) || 5000,
  507. addClass: addClass,
  508. mode: $(itemsToInit).attr("data-lg-animation") || "lg-slide",
  509. loop: $(itemsToInit).attr("data-lg-loop") !== "false",
  510. dynamic: true,
  511. dynamicEl: JSON.parse($(itemsToInit).attr("data-lg-dynamic-elements")) || []
  512. });
  513. });
  514. }
  515. }
  516. /**
  517. * @desc Initialize the gallery with one image
  518. * @param {object} itemToInit - jQuery object
  519. * @param {string} addClass - additional gallery class
  520. */
  521. function initLightGalleryItem(itemToInit, addClass) {
  522. if (!isNoviBuilder) {
  523. $(itemToInit).lightGallery({
  524. selector: "this",
  525. addClass: addClass,
  526. counter: false,
  527. youtubePlayerParams: {
  528. modestbranding: 1,
  529. showinfo: 0,
  530. rel: 0,
  531. controls: 0
  532. },
  533. vimeoPlayerParams: {
  534. byline: 0,
  535. portrait: 0
  536. }
  537. });
  538. }
  539. }
  540. /**
  541. * @desc Google map function for getting latitude and longitude
  542. */
  543. function getLatLngObject(str, marker, map, callback) {
  544. var coordinates = {};
  545. try {
  546. coordinates = JSON.parse(str);
  547. callback(new google.maps.LatLng(
  548. coordinates.lat,
  549. coordinates.lng
  550. ), marker, map)
  551. } catch (e) {
  552. map.geocoder.geocode({'address': str}, function (results, status) {
  553. if (status === google.maps.GeocoderStatus.OK) {
  554. var latitude = results[0].geometry.location.lat();
  555. var longitude = results[0].geometry.location.lng();
  556. callback(new google.maps.LatLng(
  557. parseFloat(latitude),
  558. parseFloat(longitude)
  559. ), marker, map)
  560. }
  561. })
  562. }
  563. }
  564. /**
  565. * @desc Initialize Google maps
  566. */
  567. function initMaps() {
  568. var key;
  569. for ( var i = 0; i < plugins.maps.length; i++ ) {
  570. if ( plugins.maps[i].hasAttribute( "data-key" ) ) {
  571. key = plugins.maps[i].getAttribute( "data-key" );
  572. break;
  573. }
  574. }
  575. $.getScript('//maps.google.com/maps/api/js?'+ ( key ? 'key='+ key + '&' : '' ) +'sensor=false&libraries=geometry,places&v=quarterly', function () {
  576. var head = document.getElementsByTagName('head')[0],
  577. insertBefore = head.insertBefore;
  578. head.insertBefore = function (newElement, referenceElement) {
  579. if (newElement.href && newElement.href.indexOf('//fonts.googleapis.com/css?family=Roboto') !== -1 || newElement.innerHTML.indexOf('gm-style') !== -1) {
  580. return;
  581. }
  582. insertBefore.call(head, newElement, referenceElement);
  583. };
  584. var geocoder = new google.maps.Geocoder;
  585. for (var i = 0; i < plugins.maps.length; i++) {
  586. var zoom = parseInt(plugins.maps[i].getAttribute("data-zoom"), 10) || 11;
  587. var styles = plugins.maps[i].hasAttribute('data-styles') ? JSON.parse(plugins.maps[i].getAttribute("data-styles")) : [];
  588. var center = plugins.maps[i].getAttribute("data-center") || "New York";
  589. // Initialize map
  590. var map = new google.maps.Map(plugins.maps[i].querySelectorAll(".google-map")[0], {
  591. zoom: zoom,
  592. styles: styles,
  593. scrollwheel: false,
  594. center: {lat: 0, lng: 0}
  595. });
  596. // Add map object to map node
  597. plugins.maps[i].map = map;
  598. plugins.maps[i].geocoder = geocoder;
  599. plugins.maps[i].keySupported = true;
  600. plugins.maps[i].google = google;
  601. // Get Center coordinates from attribute
  602. getLatLngObject(center, null, plugins.maps[i], function (location, markerElement, mapElement) {
  603. mapElement.map.setCenter(location);
  604. });
  605. // Add markers from google-map-markers array
  606. var markerItems = plugins.maps[i].querySelectorAll(".google-map-markers li");
  607. if (markerItems.length){
  608. var markers = [];
  609. for (var j = 0; j < markerItems.length; j++){
  610. var markerElement = markerItems[j];
  611. getLatLngObject(markerElement.getAttribute("data-location"), markerElement, plugins.maps[i], function(location, markerElement, mapElement){
  612. var icon = markerElement.getAttribute("data-icon") || mapElement.getAttribute("data-icon");
  613. var activeIcon = markerElement.getAttribute("data-icon-active") || mapElement.getAttribute("data-icon-active");
  614. var info = markerElement.getAttribute("data-description") || "";
  615. var infoWindow = new google.maps.InfoWindow({
  616. content: info
  617. });
  618. markerElement.infoWindow = infoWindow;
  619. var markerData = {
  620. position: location,
  621. map: mapElement.map
  622. }
  623. if (icon){
  624. markerData.icon = icon;
  625. }
  626. var marker = new google.maps.Marker(markerData);
  627. markerElement.gmarker = marker;
  628. markers.push({markerElement: markerElement, infoWindow: infoWindow});
  629. marker.isActive = false;
  630. // Handle infoWindow close click
  631. google.maps.event.addListener(infoWindow,'closeclick',(function(markerElement, mapElement){
  632. var markerIcon = null;
  633. markerElement.gmarker.isActive = false;
  634. markerIcon = markerElement.getAttribute("data-icon") || mapElement.getAttribute("data-icon");
  635. markerElement.gmarker.setIcon(markerIcon);
  636. }).bind(this, markerElement, mapElement));
  637. // Set marker active on Click and open infoWindow
  638. google.maps.event.addListener(marker, 'click', (function(markerElement, mapElement) {
  639. if (markerElement.infoWindow.getContent().length === 0) return;
  640. var gMarker, currentMarker = markerElement.gmarker, currentInfoWindow;
  641. for (var k =0; k < markers.length; k++){
  642. var markerIcon;
  643. if (markers[k].markerElement === markerElement){
  644. currentInfoWindow = markers[k].infoWindow;
  645. }
  646. gMarker = markers[k].markerElement.gmarker;
  647. if (gMarker.isActive && markers[k].markerElement !== markerElement){
  648. gMarker.isActive = false;
  649. markerIcon = markers[k].markerElement.getAttribute("data-icon") || mapElement.getAttribute("data-icon")
  650. gMarker.setIcon(markerIcon);
  651. markers[k].infoWindow.close();
  652. }
  653. }
  654. currentMarker.isActive = !currentMarker.isActive;
  655. if (currentMarker.isActive) {
  656. if (markerIcon = markerElement.getAttribute("data-icon-active") || mapElement.getAttribute("data-icon-active")){
  657. currentMarker.setIcon(markerIcon);
  658. }
  659. currentInfoWindow.open(map, marker);
  660. }else{
  661. if (markerIcon = markerElement.getAttribute("data-icon") || mapElement.getAttribute("data-icon")){
  662. currentMarker.setIcon(markerIcon);
  663. }
  664. currentInfoWindow.close();
  665. }
  666. }).bind(this, markerElement, mapElement))
  667. })
  668. }
  669. }
  670. }
  671. });
  672. }
  673. /**
  674. * @desc Sets the actual previous index based on the position of the slide in the markup. Should be the most recent action.
  675. * @param {object} swiper - swiper instance
  676. */
  677. function setRealPrevious( swiper ) {
  678. var element = swiper.$wrapperEl[0].children[ swiper.activeIndex ];
  679. swiper.realPrevious = Array.prototype.indexOf.call( element.parentNode.children, element );
  680. }
  681. function initSwiper(sliderMarkup) {
  682. var
  683. autoplayAttr = sliderMarkup.getAttribute('data-autoplay') || 5000,
  684. slides = sliderMarkup.querySelectorAll('.swiper-slide'),
  685. swiper,
  686. options = {
  687. loop: sliderMarkup.getAttribute('data-loop') === 'true' || false,
  688. effect: sliderMarkup.getAttribute('data-effect') || 'slide',
  689. direction: sliderMarkup.getAttribute('data-direction') || 'horizontal',
  690. speed: sliderMarkup.getAttribute('data-speed') ? Number(sliderMarkup.getAttribute('data-speed')) : 600,
  691. simulateTouch: sliderMarkup.getAttribute('data-simulate-touch') === 'true' && !isNoviBuilder || false,
  692. slidesPerView: sliderMarkup.getAttribute('data-slides') || 1,
  693. spaceBetween: Number(sliderMarkup.getAttribute('data-margin')) || 0
  694. };
  695. if (Number(autoplayAttr)) {
  696. options.autoplay = {
  697. delay: Number(autoplayAttr),
  698. stopOnLastSlide: false,
  699. disableOnInteraction: true,
  700. reverseDirection: false,
  701. };
  702. }
  703. if (sliderMarkup.getAttribute('data-keyboard') === 'true') {
  704. options.keyboard = {
  705. enabled: sliderMarkup.getAttribute('data-keyboard') === 'true',
  706. onlyInViewport: true
  707. };
  708. }
  709. if (sliderMarkup.getAttribute('data-mousewheel') === 'true') {
  710. options.mousewheel = {
  711. sensitivity: 1
  712. };
  713. }
  714. if (sliderMarkup.querySelector('.swiper-button-next, .swiper-button-prev')) {
  715. options.navigation = {
  716. nextEl: '.swiper-button-next',
  717. prevEl: '.swiper-button-prev'
  718. };
  719. }
  720. if (sliderMarkup.querySelector('.swiper-pagination')) {
  721. options.pagination = {
  722. el: '.swiper-pagination',
  723. type: 'bullets',
  724. clickable: true
  725. };
  726. }
  727. if (sliderMarkup.querySelector('.swiper-scrollbar')) {
  728. options.scrollbar = {
  729. el: '.swiper-scrollbar',
  730. hide: false
  731. };
  732. }
  733. for (var s = 0; s < slides.length; s++) {
  734. var
  735. slide = slides[s],
  736. url = slide.getAttribute('data-slide-bg');
  737. if (url) slide.style.backgroundImage = 'url(' + url + ')';
  738. }
  739. options.on = {
  740. init: function () {
  741. setRealPrevious(this);
  742. initCaptionAnimate(this);
  743. // Real Previous Index must be set recent
  744. this.on('slideChangeTransitionEnd', function () {
  745. setRealPrevious(this);
  746. });
  747. }
  748. };
  749. swiper = new Swiper(sliderMarkup, options);
  750. return swiper;
  751. }
  752. /**
  753. * @desc Animate captions on active slides
  754. * @param {object} swiper - swiper instance
  755. */
  756. function initCaptionAnimate( swiper ) {
  757. var
  758. animate = function ( caption ) {
  759. return function() {
  760. var duration;
  761. if ( duration = caption.getAttribute( 'data-caption-duration' ) ) caption.style.animationDuration = duration +'ms';
  762. caption.classList.remove( 'not-animated' );
  763. caption.classList.add( caption.getAttribute( 'data-caption-animate' ) );
  764. caption.classList.add( 'animated' );
  765. };
  766. },
  767. initializeAnimation = function ( captions ) {
  768. for ( var i = 0; i < captions.length; i++ ) {
  769. var caption = captions[i];
  770. caption.classList.remove( 'animated' );
  771. caption.classList.remove( caption.getAttribute( 'data-caption-animate' ) );
  772. caption.classList.add( 'not-animated' );
  773. }
  774. },
  775. finalizeAnimation = function ( captions ) {
  776. for ( var i = 0; i < captions.length; i++ ) {
  777. var caption = captions[i];
  778. if ( caption.getAttribute( 'data-caption-delay' ) ) {
  779. setTimeout( animate( caption ), Number( caption.getAttribute( 'data-caption-delay' ) ) );
  780. } else {
  781. animate( caption )();
  782. }
  783. }
  784. };
  785. // Caption parameters
  786. swiper.params.caption = {
  787. animationEvent: 'slideChangeTransitionEnd'
  788. };
  789. initializeAnimation( swiper.$wrapperEl[0].querySelectorAll( '[data-caption-animate]' ) );
  790. finalizeAnimation( swiper.$wrapperEl[0].children[ swiper.activeIndex ].querySelectorAll( '[data-caption-animate]' ) );
  791. if ( swiper.params.caption.animationEvent === 'slideChangeTransitionEnd' ) {
  792. swiper.on( swiper.params.caption.animationEvent, function() {
  793. initializeAnimation( swiper.$wrapperEl[0].children[ swiper.previousIndex ].querySelectorAll( '[data-caption-animate]' ) );
  794. finalizeAnimation( swiper.$wrapperEl[0].children[ swiper.activeIndex ].querySelectorAll( '[data-caption-animate]' ) );
  795. });
  796. } else {
  797. swiper.on( 'slideChangeTransitionEnd', function() {
  798. initializeAnimation( swiper.$wrapperEl[0].children[ swiper.previousIndex ].querySelectorAll( '[data-caption-animate]' ) );
  799. });
  800. swiper.on( swiper.params.caption.animationEvent, function() {
  801. finalizeAnimation( swiper.$wrapperEl[0].children[ swiper.activeIndex ].querySelectorAll( '[data-caption-animate]' ) );
  802. });
  803. }
  804. }
  805. // Additional class on html if mac os.
  806. if (navigator.platform.match(/(Mac)/i)) {
  807. $html.addClass("mac-os");
  808. }
  809. // Adds some loosing functionality to IE browsers (IE Polyfills)
  810. if (isIE) {
  811. if (isIE === 12) $html.addClass("ie-edge");
  812. if (isIE === 11) $html.addClass("ie-11");
  813. if (isIE < 10) $html.addClass("lt-ie-10");
  814. if (isIE < 11) $html.addClass("ie-10");
  815. }
  816. // Google ReCaptcha
  817. if (plugins.captcha.length) {
  818. $.getScript("//www.google.com/recaptcha/api.js?onload=onloadCaptchaCallback&render=explicit&hl=en");
  819. }
  820. // Bootstrap Tooltips
  821. if (plugins.bootstrapTooltip.length) {
  822. var tooltipPlacement = plugins.bootstrapTooltip.attr('data-placement');
  823. initBootstrapTooltip(tooltipPlacement);
  824. $window.on('resize orientationchange', function () {
  825. initBootstrapTooltip(tooltipPlacement);
  826. })
  827. }
  828. // Bootstrap tabs
  829. if (plugins.bootstrapTabs.length) {
  830. for (var i = 0; i < plugins.bootstrapTabs.length; i++) {
  831. var bootstrapTabsItem = $(plugins.bootstrapTabs[i]);
  832. //If have slick carousel inside tab - resize slick carousel on click
  833. if (bootstrapTabsItem.find('.slick-slider').length) {
  834. bootstrapTabsItem.find('.tabs-custom-list > li > a').on('click', $.proxy(function () {
  835. var $this = $(this);
  836. var setTimeOutTime = isNoviBuilder ? 1500 : 300;
  837. setTimeout(function () {
  838. $this.find('.tab-content .tab-pane.active .slick-slider').slick('setPosition');
  839. }, setTimeOutTime);
  840. }, bootstrapTabsItem));
  841. }
  842. }
  843. }
  844. // Copyright Year (Evaluates correct copyright year)
  845. if (plugins.copyrightYear.length) {
  846. plugins.copyrightYear.text(initialDate.getFullYear());
  847. }
  848. // Google maps
  849. if( plugins.maps.length ) {
  850. lazyInit( plugins.maps, initMaps );
  851. }
  852. // Add custom styling options for input[type="radio"]
  853. if (plugins.radio.length) {
  854. for (var i = 0; i < plugins.radio.length; i++) {
  855. $(plugins.radio[i]).addClass("radio-custom").after("<span class='radio-custom-dummy'></span>")
  856. }
  857. }
  858. // Add custom styling options for input[type="checkbox"]
  859. if (plugins.checkbox.length) {
  860. for (var i = 0; i < plugins.checkbox.length; i++) {
  861. $(plugins.checkbox[i]).addClass("checkbox-custom").after("<span class='checkbox-custom-dummy'></span>")
  862. }
  863. }
  864. // UI To Top
  865. if (isDesktop && !isNoviBuilder) {
  866. $().UItoTop({
  867. easingType: 'easeOutQuad',
  868. containerClass: 'ui-to-top mdi mdi-arrow-up'
  869. });
  870. }
  871. // RD Navbar
  872. if (plugins.rdNavbar.length) {
  873. var aliaces, i, j, len, value, values, responsiveNavbar;
  874. aliaces = ["-", "-sm-", "-md-", "-lg-", "-xl-", "-xxl-"];
  875. values = [0, 576, 768, 992, 1200, 1600];
  876. responsiveNavbar = {};
  877. for (i = j = 0, len = values.length; j < len; i = ++j) {
  878. value = values[i];
  879. if (!responsiveNavbar[values[i]]) {
  880. responsiveNavbar[values[i]] = {};
  881. }
  882. if (plugins.rdNavbar.attr('data' + aliaces[i] + 'layout')) {
  883. responsiveNavbar[values[i]].layout = plugins.rdNavbar.attr('data' + aliaces[i] + 'layout');
  884. }
  885. if (plugins.rdNavbar.attr('data' + aliaces[i] + 'device-layout')) {
  886. responsiveNavbar[values[i]]['deviceLayout'] = plugins.rdNavbar.attr('data' + aliaces[i] + 'device-layout');
  887. }
  888. if (plugins.rdNavbar.attr('data' + aliaces[i] + 'hover-on')) {
  889. responsiveNavbar[values[i]]['focusOnHover'] = plugins.rdNavbar.attr('data' + aliaces[i] + 'hover-on') === 'true';
  890. }
  891. if (plugins.rdNavbar.attr('data' + aliaces[i] + 'auto-height')) {
  892. responsiveNavbar[values[i]]['autoHeight'] = plugins.rdNavbar.attr('data' + aliaces[i] + 'auto-height') === 'true';
  893. }
  894. if (isNoviBuilder) {
  895. responsiveNavbar[values[i]]['stickUp'] = false;
  896. } else if (plugins.rdNavbar.attr('data' + aliaces[i] + 'stick-up')) {
  897. responsiveNavbar[values[i]]['stickUp'] = plugins.rdNavbar.attr('data' + aliaces[i] + 'stick-up') === 'true';
  898. }
  899. if (plugins.rdNavbar.attr('data' + aliaces[i] + 'stick-up-offset')) {
  900. responsiveNavbar[values[i]]['stickUpOffset'] = plugins.rdNavbar.attr('data' + aliaces[i] + 'stick-up-offset');
  901. }
  902. }
  903. plugins.rdNavbar.RDNavbar({
  904. anchorNav: !isNoviBuilder,
  905. stickUpClone: (plugins.rdNavbar.attr("data-stick-up-clone") && !isNoviBuilder) ? plugins.rdNavbar.attr("data-stick-up-clone") === 'true' : false,
  906. responsive: responsiveNavbar,
  907. callbacks: {
  908. onStuck: function () {
  909. var navbarSearch = this.$element.find('.rd-search input');
  910. if (navbarSearch) {
  911. navbarSearch.val('').trigger('propertychange');
  912. }
  913. },
  914. onDropdownOver: function () {
  915. return !isNoviBuilder;
  916. },
  917. onUnstuck: function () {
  918. if (this.$clone === null)
  919. return;
  920. var navbarSearch = this.$clone.find('.rd-search input');
  921. if (navbarSearch) {
  922. navbarSearch.val('').trigger('propertychange');
  923. navbarSearch.trigger('blur');
  924. }
  925. }
  926. }
  927. });
  928. if (plugins.rdNavbar.attr("data-body-class")) {
  929. document.body.className += ' ' + plugins.rdNavbar.attr("data-body-class");
  930. }
  931. }
  932. // Owl carousel
  933. if (plugins.owl.length) {
  934. for (var i = 0; i < plugins.owl.length; i++) {
  935. var c = $(plugins.owl[i]);
  936. plugins.owl[i].owl = c;
  937. initOwlCarousel(c);
  938. }
  939. // Owl bug with webkit scrollbar
  940. if ( !isIE || isIE >= 12 ) {
  941. setTimeout( function() {
  942. window.dispatchEvent( new Event('resize') );
  943. }, 500)
  944. }
  945. }
  946. // RD Search
  947. if (plugins.search.length || plugins.searchResults) {
  948. var handler = "bat/rd-search.php";
  949. var defaultTemplate = '<h5 class="search-title"><a target="_top" href="#{href}" class="search-link">#{title}</a></h5>' +
  950. '<p>...#{token}...</p>' +
  951. '<p class="match"><em>Terms matched: #{count} - URL: #{href}</em></p>';
  952. var defaultFilter = '*.html';
  953. if (plugins.search.length) {
  954. for (var i = 0; i < plugins.search.length; i++) {
  955. var searchItem = $(plugins.search[i]),
  956. options = {
  957. element: searchItem,
  958. filter: (searchItem.attr('data-search-filter')) ? searchItem.attr('data-search-filter') : defaultFilter,
  959. template: (searchItem.attr('data-search-template')) ? searchItem.attr('data-search-template') : defaultTemplate,
  960. live: (searchItem.attr('data-search-live')) ? searchItem.attr('data-search-live') : false,
  961. liveCount: (searchItem.attr('data-search-live-count')) ? parseInt(searchItem.attr('data-search-live'), 10) : 4,
  962. current: 0, processed: 0, timer: {}
  963. };
  964. var $toggle = $('.rd-navbar-search-toggle');
  965. if ($toggle.length) {
  966. $toggle.on('click', (function (searchItem) {
  967. return function () {
  968. if (!($(this).hasClass('active'))) {
  969. searchItem.find('input').val('').trigger('propertychange');
  970. }
  971. }
  972. })(searchItem));
  973. }
  974. if (options.live) {
  975. var clearHandler = false;
  976. searchItem.find('input').on("input propertychange", $.proxy(function () {
  977. this.term = this.element.find('input').val().trim();
  978. this.spin = this.element.find('.input-group-addon');
  979. clearTimeout(this.timer);
  980. if (this.term.length > 2) {
  981. this.timer = setTimeout(liveSearch(this), 200);
  982. if (clearHandler === false) {
  983. clearHandler = true;
  984. $body.on("click", function (e) {
  985. if ($(e.toElement).parents('.rd-search').length === 0) {
  986. $('#rd-search-results-live').addClass('cleared').html('');
  987. }
  988. })
  989. }
  990. } else if (this.term.length === 0) {
  991. $('#' + this.live).addClass('cleared').html('');
  992. }
  993. }, options, this));
  994. }
  995. searchItem.submit($.proxy(function () {
  996. $('<input />').attr('type', 'hidden')
  997. .attr('name', "filter")
  998. .attr('value', this.filter)
  999. .appendTo(this.element);
  1000. return true;
  1001. }, options, this))
  1002. }
  1003. }
  1004. if (plugins.searchResults.length) {
  1005. var regExp = /\?.*s=([^&]+)\&filter=([^&]+)/g;
  1006. var match = regExp.exec(location.search);
  1007. if (match !== null) {
  1008. $.get(handler, {
  1009. s: decodeURI(match[1]),
  1010. dataType: "html",
  1011. filter: match[2],
  1012. template: defaultTemplate,
  1013. live: ''
  1014. }, function (data) {
  1015. plugins.searchResults.html(data);
  1016. })
  1017. }
  1018. }
  1019. }
  1020. // Swiper
  1021. if (plugins.swiper) {
  1022. for (var i = 0; i < plugins.swiper.length; i++) {
  1023. plugins.swiper[i].swiper = initSwiper(plugins.swiper[i]);
  1024. }
  1025. var dynamicSwipers = $('.swiper-slider-custom');
  1026. if(dynamicSwipers.length) {
  1027. $window.on('resize orientationchange', function () {
  1028. for (var i = 0; i < dynamicSwipers.length; i++) {
  1029. if(window.innerWidth < 576 && dynamicSwipers[i].swiper.params.direction === 'vertical') {
  1030. dynamicSwipers[i].setAttribute('data-direction', 'horizontal');
  1031. dynamicSwipers[i].swiper.destroy();
  1032. initSwiper(dynamicSwipers[i]);
  1033. } else if (window.innerWidth >= 576 && dynamicSwipers[i].swiper.params.direction === 'horizontal') {
  1034. dynamicSwipers[i].setAttribute('data-direction', 'vertical');
  1035. dynamicSwipers[i].swiper.destroy();
  1036. initSwiper(dynamicSwipers[i]);
  1037. }
  1038. }
  1039. });
  1040. }
  1041. }
  1042. // WOW
  1043. if ($html.hasClass("wow-animation") && plugins.wow.length && !isNoviBuilder && isDesktop) {
  1044. new WOW().init();
  1045. }
  1046. // RD Input Label
  1047. if (plugins.rdInputLabel.length) {
  1048. plugins.rdInputLabel.RDInputLabel();
  1049. }
  1050. // Regula
  1051. if (plugins.regula.length) {
  1052. attachFormValidator(plugins.regula);
  1053. }
  1054. // MailChimp Ajax subscription
  1055. if (plugins.mailchimp.length) {
  1056. for (i = 0; i < plugins.mailchimp.length; i++) {
  1057. var $mailchimpItem = $(plugins.mailchimp[i]),
  1058. $email = $mailchimpItem.find('input[type="email"]');
  1059. // Required by MailChimp
  1060. $mailchimpItem.attr('novalidate', 'true');
  1061. $email.attr('name', 'EMAIL');
  1062. $mailchimpItem.on('submit', $.proxy( function ( $email, event ) {
  1063. event.preventDefault();
  1064. var $this = this;
  1065. var data = {},
  1066. url = $this.attr('action').replace('/post?', '/post-json?').concat('&c=?'),
  1067. dataArray = $this.serializeArray(),
  1068. $output = $("#" + $this.attr("data-form-output"));
  1069. for (i = 0; i < dataArray.length; i++) {
  1070. data[dataArray[i].name] = dataArray[i].value;
  1071. }
  1072. $.ajax({
  1073. data: data,
  1074. url: url,
  1075. dataType: 'jsonp',
  1076. error: function (resp, text) {
  1077. $output.html('Server error: ' + text);
  1078. setTimeout(function () {
  1079. $output.removeClass("active");
  1080. }, 4000);
  1081. },
  1082. success: function (resp) {
  1083. $output.html(resp.msg).addClass('active');
  1084. $email[0].value = '';
  1085. var $label = $('[for="'+ $email.attr( 'id' ) +'"]');
  1086. if ( $label.length ) $label.removeClass( 'focus not-empty' );
  1087. setTimeout(function () {
  1088. $output.removeClass("active");
  1089. }, 6000);
  1090. },
  1091. beforeSend: function (data) {
  1092. var isNoviBuilder = window.xMode;
  1093. var isValidated = (function () {
  1094. var results, errors = 0;
  1095. var elements = $this.find('[data-constraints]');
  1096. var captcha = null;
  1097. if (elements.length) {
  1098. for (var j = 0; j < elements.length; j++) {
  1099. var $input = $(elements[j]);
  1100. if ((results = $input.regula('validate')).length) {
  1101. for (var k = 0; k < results.length; k++) {
  1102. errors++;
  1103. $input.siblings(".form-validation").text(results[k].message).parent().addClass("has-error");
  1104. }
  1105. } else {
  1106. $input.siblings(".form-validation").text("").parent().removeClass("has-error")
  1107. }
  1108. }
  1109. if (captcha) {
  1110. if (captcha.length) {
  1111. return validateReCaptcha(captcha) && errors === 0
  1112. }
  1113. }
  1114. return errors === 0;
  1115. }
  1116. return true;
  1117. })();
  1118. // Stop request if builder or inputs are invalide
  1119. if (isNoviBuilder || !isValidated)
  1120. return false;
  1121. $output.html('Submitting...').addClass('active');
  1122. }
  1123. });
  1124. return false;
  1125. }, $mailchimpItem, $email ));
  1126. }
  1127. }
  1128. // Campaign Monitor ajax subscription
  1129. if (plugins.campaignMonitor.length) {
  1130. for (i = 0; i < plugins.campaignMonitor.length; i++) {
  1131. var $campaignItem = $(plugins.campaignMonitor[i]);
  1132. $campaignItem.on('submit', $.proxy(function (e) {
  1133. var data = {},
  1134. url = this.attr('action'),
  1135. dataArray = this.serializeArray(),
  1136. $output = $("#" + plugins.campaignMonitor.attr("data-form-output")),
  1137. $this = $(this);
  1138. for (i = 0; i < dataArray.length; i++) {
  1139. data[dataArray[i].name] = dataArray[i].value;
  1140. }
  1141. $.ajax({
  1142. data: data,
  1143. url: url,
  1144. dataType: 'jsonp',
  1145. error: function (resp, text) {
  1146. $output.html('Server error: ' + text);
  1147. setTimeout(function () {
  1148. $output.removeClass("active");
  1149. }, 4000);
  1150. },
  1151. success: function (resp) {
  1152. $output.html(resp.Message).addClass('active');
  1153. setTimeout(function () {
  1154. $output.removeClass("active");
  1155. }, 6000);
  1156. },
  1157. beforeSend: function (data) {
  1158. // Stop request if builder or inputs are invalide
  1159. if (isNoviBuilder || !isValidated($this.find('[data-constraints]')))
  1160. return false;
  1161. $output.html('Submitting...').addClass('active');
  1162. }
  1163. });
  1164. // Clear inputs after submit
  1165. var inputs = $this[0].getElementsByTagName('input');
  1166. for (var i = 0; i < inputs.length; i++) {
  1167. inputs[i].value = '';
  1168. var label = document.querySelector( '[for="'+ inputs[i].getAttribute( 'id' ) +'"]' );
  1169. if( label ) label.classList.remove( 'focus', 'not-empty' );
  1170. }
  1171. return false;
  1172. }, $campaignItem));
  1173. }
  1174. }
  1175. // RD Mailform
  1176. if (plugins.rdMailForm.length) {
  1177. var i, j, k,
  1178. msg = {
  1179. 'MF000': 'Successfully sent!',
  1180. 'MF001': 'Recipients are not set!',
  1181. 'MF002': 'Form will not work locally!',
  1182. 'MF003': 'Please, define email field in your form!',
  1183. 'MF004': 'Please, define type of your form!',
  1184. 'MF254': 'Something went wrong with PHPMailer!',
  1185. 'MF255': 'Aw, snap! Something went wrong.'
  1186. };
  1187. for (i = 0; i < plugins.rdMailForm.length; i++) {
  1188. var $form = $(plugins.rdMailForm[i]),
  1189. formHasCaptcha = false;
  1190. $form.attr('novalidate', 'novalidate').ajaxForm({
  1191. data: {
  1192. "form-type": $form.attr("data-form-type") || "contact",
  1193. "counter": i
  1194. },
  1195. beforeSubmit: function (arr, $form, options) {
  1196. if (isNoviBuilder)
  1197. return;
  1198. var form = $(plugins.rdMailForm[this.extraData.counter]),
  1199. inputs = form.find("[data-constraints]"),
  1200. output = $("#" + form.attr("data-form-output")),
  1201. captcha = form.find('.recaptcha'),
  1202. captchaFlag = true;
  1203. output.removeClass("active error success");
  1204. if (isValidated(inputs, captcha)) {
  1205. // veify reCaptcha
  1206. if (captcha.length) {
  1207. var captchaToken = captcha.find('.g-recaptcha-response').val(),
  1208. captchaMsg = {
  1209. 'CPT001': 'Please, setup you "site key" and "secret key" of reCaptcha',
  1210. 'CPT002': 'Something wrong with google reCaptcha'
  1211. };
  1212. formHasCaptcha = true;
  1213. $.ajax({
  1214. method: "POST",
  1215. url: "bat/reCaptcha.php",
  1216. data: {'g-recaptcha-response': captchaToken},
  1217. async: false
  1218. })
  1219. .done(function (responceCode) {
  1220. if (responceCode !== 'CPT000') {
  1221. if (output.hasClass("snackbars")) {
  1222. output.html('<p><span class="icon text-middle mdi mdi-check icon-xxs"></span><span>' + captchaMsg[responceCode] + '</span></p>')
  1223. setTimeout(function () {
  1224. output.removeClass("active");
  1225. }, 3500);
  1226. captchaFlag = false;
  1227. } else {
  1228. output.html(captchaMsg[responceCode]);
  1229. }
  1230. output.addClass("active");
  1231. }
  1232. });
  1233. }
  1234. if (!captchaFlag) {
  1235. return false;
  1236. }
  1237. form.addClass('form-in-process');
  1238. if (output.hasClass("snackbars")) {
  1239. output.html('<p><span class="icon text-middle fa fa-circle-o-notch fa-spin icon-xxs"></span><span>Sending</span></p>');
  1240. output.addClass("active");
  1241. }
  1242. } else {
  1243. return false;
  1244. }
  1245. },
  1246. error: function (result) {
  1247. if (isNoviBuilder)
  1248. return;
  1249. var output = $("#" + $(plugins.rdMailForm[this.extraData.counter]).attr("data-form-output")),
  1250. form = $(plugins.rdMailForm[this.extraData.counter]);
  1251. output.text(msg[result]);
  1252. form.removeClass('form-in-process');
  1253. if (formHasCaptcha) {
  1254. grecaptcha.reset();
  1255. }
  1256. },
  1257. success: function (result) {
  1258. if (isNoviBuilder)
  1259. return;
  1260. var form = $(plugins.rdMailForm[this.extraData.counter]),
  1261. output = $("#" + form.attr("data-form-output")),
  1262. select = form.find('select');
  1263. form
  1264. .addClass('success')
  1265. .removeClass('form-in-process');
  1266. if (formHasCaptcha) {
  1267. grecaptcha.reset();
  1268. }
  1269. result = result.length === 5 ? result : 'MF255';
  1270. output.text(msg[result]);
  1271. if (result === "MF000") {
  1272. if (output.hasClass("snackbars")) {
  1273. output.html('<p><span class="icon text-middle mdi mdi-check icon-xxs"></span><span>' + msg[result] + '</span></p>');
  1274. } else {
  1275. output.addClass("active success");
  1276. }
  1277. } else {
  1278. if (output.hasClass("snackbars")) {
  1279. output.html(' <p class="snackbars-left"><span class="icon icon-xxs mdi mdi-alert-outline text-middle"></span><span>' + msg[result] + '</span></p>');
  1280. } else {
  1281. output.addClass("active error");
  1282. }
  1283. }
  1284. form.clearForm();
  1285. if (select.length) {
  1286. select.select2("val", "");
  1287. }
  1288. form.find('input, textarea').trigger('blur');
  1289. setTimeout(function () {
  1290. output.removeClass("active error success");
  1291. form.removeClass('success');
  1292. }, 3500);
  1293. }
  1294. });
  1295. }
  1296. }
  1297. // lightGallery
  1298. if (plugins.lightGallery.length) {
  1299. for (var i = 0; i < plugins.lightGallery.length; i++) {
  1300. initLightGallery(plugins.lightGallery[i]);
  1301. }
  1302. }
  1303. // lightGallery item
  1304. if (plugins.lightGalleryItem.length) {
  1305. // Filter carousel items
  1306. var notCarouselItems = [];
  1307. for (var z = 0; z < plugins.lightGalleryItem.length; z++) {
  1308. if (!$(plugins.lightGalleryItem[z]).parents('.owl-carousel').length &&
  1309. !$(plugins.lightGalleryItem[z]).parents('.swiper-slider').length &&
  1310. !$(plugins.lightGalleryItem[z]).parents('.slick-slider').length) {
  1311. notCarouselItems.push(plugins.lightGalleryItem[z]);
  1312. }
  1313. }
  1314. plugins.lightGalleryItem = notCarouselItems;
  1315. for (var i = 0; i < plugins.lightGalleryItem.length; i++) {
  1316. initLightGalleryItem(plugins.lightGalleryItem[i]);
  1317. }
  1318. }
  1319. // Dynamic lightGallery
  1320. if (plugins.lightDynamicGalleryItem.length) {
  1321. for (var i = 0; i < plugins.lightDynamicGalleryItem.length; i++) {
  1322. initDynamicLightGallery(plugins.lightDynamicGalleryItem[i]);
  1323. }
  1324. }
  1325. // Custom Toggles
  1326. if (plugins.customToggle.length) {
  1327. for (var i = 0; i < plugins.customToggle.length; i++) {
  1328. var $this = $(plugins.customToggle[i]);
  1329. $this.on('click', $.proxy(function (event) {
  1330. event.preventDefault();
  1331. var $ctx = $(this);
  1332. $($ctx.attr('data-custom-toggle')).add(this).toggleClass('active');
  1333. }, $this));
  1334. if ($this.attr("data-custom-toggle-hide-on-blur") === "true") {
  1335. $body.on("click", $this, function (e) {
  1336. if (e.target !== e.data[0]
  1337. && $(e.data.attr('data-custom-toggle')).find($(e.target)).length
  1338. && e.data.find($(e.target)).length === 0) {
  1339. $(e.data.attr('data-custom-toggle')).add(e.data[0]).removeClass('active');
  1340. }
  1341. })
  1342. }
  1343. if ($this.attr("data-custom-toggle-disable-on-blur") === "true") {
  1344. $body.on("click", $this, function (e) {
  1345. if (e.target !== e.data[0] && $(e.data.attr('data-custom-toggle')).find($(e.target)).length === 0 && e.data.find($(e.target)).length === 0) {
  1346. $(e.data.attr('data-custom-toggle')).add(e.data[0]).removeClass('active');
  1347. }
  1348. })
  1349. }
  1350. }
  1351. }
  1352. //RD Range
  1353. if (plugins.rdRange.length && !isNoviBuilder) {
  1354. plugins.rdRange.RDRange({
  1355. callbacks: {
  1356. onChange: function() {
  1357. var $inputs = $('.rd-range-input-value-1, .rd-range-input-value-2');
  1358. for(var z = 0; z < $inputs.length; z++) {
  1359. if(isDesktop) {
  1360. $inputs[z].style.width = ($inputs[z].value.length + 1) * 1.15 + 'ch';
  1361. }
  1362. }
  1363. },
  1364. }
  1365. });
  1366. }
  1367. // Select 2
  1368. if ( plugins.selectFilter.length ) {
  1369. for ( var i = 0; i < plugins.selectFilter.length; i++ ) {
  1370. var select = $( plugins.selectFilter[ i ] );
  1371. select.select2( {
  1372. dropdownParent: select.parent(),
  1373. placeholder: select.attr( 'data-placeholder' ) || null,
  1374. minimumResultsForSearch: select.attr( 'data-minimum-results-search' ) || Infinity,
  1375. containerCssClass: select.attr( 'data-container-class' ) || null,
  1376. dropdownCssClass: select.attr( 'data-dropdown-class' ) || null
  1377. } );
  1378. }
  1379. }
  1380. // Slick carousel
  1381. if (plugins.slick.length) {
  1382. for (var i = 0; i < plugins.slick.length; i++) {
  1383. var $slickItem = $(plugins.slick[i]);
  1384. $slickItem.on('init', function (slick) {
  1385. initLightGallery($('[data-lightgallery="group-slick"]'), 'lightGallery-in-carousel');
  1386. initLightGallery($('[data-lightgallery="item-slick"]'), 'lightGallery-in-carousel');
  1387. });
  1388. $slickItem.slick({
  1389. slidesToScroll: parseInt($slickItem.attr('data-slide-to-scroll'), 10) || 1,
  1390. asNavFor: $slickItem.attr('data-for') || false,
  1391. dots: $slickItem.attr("data-dots") === "true",
  1392. infinite: isNoviBuilder ? false : $slickItem.attr("data-loop") === "true",
  1393. focusOnSelect: $slickItem.attr('data-focus-select') || true,
  1394. arrows: $slickItem.attr("data-arrows") === "true",
  1395. swipe: $slickItem.attr("data-swipe") === "true",
  1396. autoplay: $slickItem.attr("data-autoplay") === "true",
  1397. centerMode: $slickItem.attr("data-center-mode") === "true",
  1398. fade: $slickItem.attr("data-slide-effect") === "true",
  1399. centerPadding: $slickItem.attr("data-center-padding") ? $slickItem.attr("data-center-padding") : '0.50',
  1400. mobileFirst: true,
  1401. appendArrows: $slickItem.attr("data-arrows-class") || $slickItem,
  1402. nextArrow: '<button type="button" class="slick-next"></button>',
  1403. prevArrow: '<button type="button" class="slick-prev"></button>',
  1404. responsive: [
  1405. {
  1406. breakpoint: 0,
  1407. settings: {
  1408. slidesToShow: parseInt($slickItem.attr('data-items'), 10) || 1,
  1409. vertical: $slickItem.attr('data-vertical') === 'true' || false
  1410. }
  1411. },
  1412. {
  1413. breakpoint: 575,
  1414. settings: {
  1415. slidesToShow: parseInt($slickItem.attr('data-sm-items'), 10) || 1,
  1416. vertical: $slickItem.attr('data-sm-vertical') === 'true' || false
  1417. }
  1418. },
  1419. {
  1420. breakpoint: 767,
  1421. settings: {
  1422. slidesToShow: parseInt($slickItem.attr('data-md-items'), 10) || 1,
  1423. vertical: $slickItem.attr('data-md-vertical') === 'true' || false
  1424. }
  1425. },
  1426. {
  1427. breakpoint: 991,
  1428. settings: {
  1429. slidesToShow: parseInt($slickItem.attr('data-lg-items'), 10) || 1,
  1430. vertical: $slickItem.attr('data-lg-vertical') === 'true' || false
  1431. }
  1432. },
  1433. {
  1434. breakpoint: 1199,
  1435. settings: {
  1436. slidesToShow: parseInt($slickItem.attr('data-xl-items'), 10) || 1,
  1437. vertical: $slickItem.attr('data-xl-vertical') === 'true' || false
  1438. }
  1439. },
  1440. {
  1441. breakpoint: 1599,
  1442. settings: {
  1443. slidesToShow: parseInt($slickItem.attr('data-xxl-items'), 10) || 1,
  1444. vertical: $slickItem.attr('data-xxl-vertical') === 'true' || false
  1445. }
  1446. }
  1447. ]
  1448. })
  1449. .on('afterChange', function (event, slick, currentSlide, nextSlide) {
  1450. var $this = $(this),
  1451. childCarousel = $this.attr('data-child');
  1452. if (childCarousel) {
  1453. $(childCarousel + ' .slick-slide').removeClass('slick-current');
  1454. $(childCarousel + ' .slick-slide').eq(currentSlide).addClass('slick-current');
  1455. }
  1456. });
  1457. }
  1458. }
  1459. // Stepper
  1460. if (plugins.stepper.length) {
  1461. plugins.stepper.stepper({
  1462. labels: {
  1463. up: "",
  1464. down: ""
  1465. }
  1466. });
  1467. }
  1468. // Radio Panel
  1469. if (plugins.radioPanel) {
  1470. for (var i = 0; i < plugins.radioPanel.length; i++) {
  1471. var $element = $(plugins.radioPanel[i]);
  1472. $element.on('click', function () {
  1473. plugins.radioPanel.removeClass('active');
  1474. $(this).addClass('active');
  1475. })
  1476. }
  1477. }
  1478. // Multitoggles
  1479. if(plugins.multitoggle.length) {
  1480. multitoggles();
  1481. }
  1482. });
  1483. }());