1'use strict'; 2 3// Global components list 4let components = {}; 5 6components.pageReveal = { 7 selector: 'html', 8 init: function( nodes ) { 9 window.addEventListener( 'components:ready', function () { 10 window.dispatchEvent( new CustomEvent( 'resize' ) ); 11 document.documentElement.classList.add( 'components-ready' ); 12 13 setTimeout( function() { 14 document.documentElement.classList.add( 'page-loaded' ); 15 }, 300 ); 16 }, { once: true } ); 17 } 18}; 19 20components.currentDevice = { 21 selector: 'html', 22 script: '/assets/components/current-device/current-device.min.js' 23}; 24 25components.fontFivoSansModern = { 26 selector: 'html', 27 styles: '/assets/components/fivosansmodern/fivosansmodern.css' 28}; 29 30components.fontLato = { 31 selector: 'html', 32 styles: 'https://fonts.googleapis.com/css2?family=Lato:ital,wght@0,400;0,700;1,400;1,700&display=swap' 33}; 34 35components.spartan = { 36 selector: 'html', 37 styles: 'https://fonts.googleapis.com/css2?family=Spartan:wght@400;500;600;700;900&display=swap' 38}; 39 40components.fontAwesome = { 41 selector: '[class*="fa-"]', 42 styles: '/assets/components/font-awesome/font-awesome.css' 43}; 44 45components.mdi = { 46 selector: '[class*="mdi-"]', 47 styles: '/assets/components/mdi/mdi.css' 48}; 49 50components.linearicons = { 51 selector: '[class*="linearicons-"]', 52 styles: '/assets/components/linearicons/linearicons.css' 53}; 54 55components.alert = { 56 selector: '.alert', 57 styles: '/assets/components/alert/alert.css' 58}; 59 60components.blogPost = { 61 selector: '.blog-post', 62 styles: '/assets/components/blog-post/blog-post.css' 63}; 64 65components.blogSearch = { 66 selector: '.blog-search', 67 styles: '/assets/components/blog-search/blog-search.css' 68}; 69 70components.blurb = { 71 selector: '.blurb', 72 styles: '/assets/components/blurb/blurb.css' 73}; 74 75components.box = { 76 selector: '.box', 77 styles: '/assets/components/box/box.css' 78}; 79 80components.breadcrumb = { 81 selector: '.breadcrumb', 82 styles: '/assets/components/breadcrumb/breadcrumb.css' 83}; 84 85components.button = { 86 selector: '.btn', 87 styles: '/assets/components/button/button.css' 88}; 89 90components.checkboxColor = { 91 selector: '.checkbox-color', 92 styles: '/assets/components/checkbox-color/checkbox-color.css' 93}; 94 95components.checkboxTag = { 96 selector: '.checkbox-tag', 97 styles: '/assets/components/checkbox-tag/checkbox-tag.css' 98}; 99 100components.close = { 101 selector: '.close', 102 styles: '/assets/components/close/close.css' 103}; 104 105components.comment = { 106 selector: '.comment', 107 styles: '/assets/components/comment/comment.css' 108}; 109 110components.divider = { 111 selector: '.divider', 112 styles: '/assets/components/divider/divider.css' 113}; 114 115components.footer = { 116 selector: 'footer', 117 styles: '/assets/components/footer/footer.css' 118}; 119 120components.gallery = { 121 selector: '.gallery', 122 styles: [ 123 '/assets/components/gallery/gallery.css', 124 '/assets/components/linearicons/linearicons.css' 125 ] 126}; 127 128components.grid = { 129 selector: '.container, .container-fluid, .row, [class*="col-"]', 130 styles: '/assets/components/grid/grid.css' 131}; 132 133components.icon = { 134 selector: '.icon', 135 styles: '/assets/components/icon/icon.css' 136}; 137 138components.image = { 139 selector: '.image', 140 styles: '/assets/components/image/image.css' 141}; 142 143components.input = { 144 selector: '.form-group, .input-group, .form-check, .custom-control, .form-control', 145 styles: '/assets/components/input/input.css' 146}; 147 148components.intro = { 149 selector: '.intro', 150 styles: '/assets/components/intro/intro.css' 151}; 152 153components.link = { 154 selector: '.link', 155 styles: '/assets/components/link/link.css' 156}; 157 158components.list = { 159 selector: '.list', 160 styles: '/assets/components/list/list.css' 161}; 162 163components.logo = { 164 selector: '.logo', 165 styles: '/assets/components/logo/logo.css' 166}; 167 168components.nav = { 169 selector: '.nav', 170 styles: '/assets/components/nav/nav.css' 171}; 172 173components.pagination = { 174 selector: '.pag', 175 styles: '/assets/components/pag/pag.css' 176}; 177 178components.person = { 179 selector: '.person', 180 styles: '/assets/components/person/person.css' 181}; 182 183components.post = { 184 selector: '.post',
185 styles: '/assets/components/post/post.css' 186}; 187 188components.preloader = { 189 selector: '.preloader', 190 styles: '/assets/components/preloader/preloader.css' 191}; 192 193components.product = { 194 selector: '.product', 195 styles: '/assets/components/product/product.css' 196}; 197 198components.quote = { 199 selector: '.quote', 200 styles: '/assets/components/quote/quote.css' 201}; 202 203components.rdForm = { 204 selector: '.rd-form', 205 styles: '/assets/components/rd-form/rd-form.css' 206}; 207 208components.section = { 209 selector: 'section', 210 styles: '/assets/components/section/section.css' 211}; 212 213components.snackbar = { 214 selector: '.snackbar', 215 styles: '/assets/components/snackbar/snackbar.css' 216}; 217 218components.social = { 219 selector: '.social', 220 styles: '/assets/components/social/social.css' 221}; 222 223components.tab = { 224 selector: '.tab', 225 styles: '/assets/components/tab/tab.css' 226}; 227 228components.tag = { 229 selector: '.tag', 230 styles: '/assets/components/tag/tag.css' 231}; 232 233components.templateInfo = { 234 selector: '.template-info', 235 styles: '/assets/components/template-info/template-info.css' 236}; 237 238components.textBlock = { 239 selector: '.text-block', 240 styles: '/assets/components/text-block/text-block.css' 241}; 242 243components.textDivider = { 244 selector: '.text-divider', 245 styles: '/assets/components/text-divider/text-divider.css' 246}; 247 248components.thumbnail = { 249 selector: '.thumbnail', 250 styles: '/assets/components/thumbnail/thumbnail.css' 251}; 252 253components.widget = { 254 selector: '.widget', 255 styles: '/assets/components/widget/widget.css' 256}; 257 258// Script components 259components.accordion = { 260 selector: '.accordion', 261 styles: [ 262 '/assets/components/accordion/accordion.css', 263 '/assets/components/mdi/mdi.css' 264 ], 265 script: [ 266 '/assets/components/jquery/jquery.min.js', 267 '/assets/components/current-device/current-device.min.js', 268 '/assets/components/multiswitch/multiswitch.min.js' 269 ], 270 init: function ( nodes ) { 271 nodes.forEach( function ( node ) { 272 let 273 items = node.querySelectorAll( '.accordion-item' ), 274 click = device.ios() ? 'touchstart' : 'click'; 275 276 items.forEach( function ( item ) { 277 let 278 head = item.querySelector( '.accordion-head' ), 279 body = item.querySelector( '.accordion-body' ); 280 281 // MultiSwitch({ 282 // node: head, 283 // targets: [ item, body ], 284 // isolate: node.querySelectorAll( '.accordion-head' ), 285 // state: item.classList.contains( 'active' ), 286 // event: click, 287 // }); 288 289 // if ( !body.multiSwitchTarget.groups.active.state ) body.style.display = 'none'; 290 291 // body.addEventListener( 'switch:active', function () { 292 // let $this = $( this ); 293 294 // if ( this.multiSwitchTarget.groups.active.state ) { 295 // $this.stop().slideDown( 300 ); 296 // } else { 297 // $this.stop().slideUp( 300 ); 298 // } 299 // }); 300 301 item.addEventListener( click, function () { 302 let $this = $( this ); 303 304 if (false === $this.hasClass('active')) { 305 $this.addClass('active') 306 $this.find('.accordion-body').stop().slideDown( 300 ) 307 $this.find('.accordion-head').addClass('active') 308 $this.find('.accordion-body').addClass('active') 309 } else { 310 $this.removeClass('active') 311 $this.find('.accordion-body').stop().slideUp( 300 ) 312 $this.find('.accordion-head').removeClass('active') 313 $this.find('.accordion-body').removeClass('active') 314 } 315 }); 316 }); 317 }); 318 } 319}; 320 321components.animate = { 322 selector: '[data-animate]', 323 styles: '/assets/components/animate/animate.css', 324 script: '/assets/components/current-device/current-device.min.js', 325 init: function ( nodes ) { 326 if ( window.xMode || device.macos()|| device.ios() ) { 327 nodes.forEach( function ( node ) { 328 let params = parseJSON( node.getAttribute( 'data-animate' ) ); 329 node.classList.add( 'animated', params.class ); 330 }); 331 } else { 332 let observer = new IntersectionObserver( function ( entries ) { 333 let observer = this; 334 335 entries.forEach( function ( entry ) { 336 let 337 node = entry.target, 338 params = parseJSON( node.getAttribute( 'data-animate' ) ); 339 340 if ( params.delay ) node.style.animationDelay = params.delay; 341 if ( params.duration ) node.style.animationDuration = params.duration; 342 343 if ( entry.isIntersecting ) { 344 node.classList.add( 'animated', params.class ); 345 observer.unobserve( node ); 346 } 347 }); 348 }, { 349 threshold: .5 350 }); 351
352 nodes.forEach( function ( node ) { 353 observer.observe( node ); 354 }); 355 } 356 } 357}; 358 359components.twitterTimeline = { 360 selector: '.twitter-timeline', 361 init: function ( nodes ) { 362 var scriptSource = document.createElement("script"); 363 scriptSource.src = "https://platform.twitter.com/widgets.js"; 364 365 let observer = new IntersectionObserver( function ( entries ) { 366 let observer = this; 367 368 entries.forEach( function ( entry ) { 369 if ( entry.isIntersecting ) { 370 document.querySelector("head").appendChild( scriptSource ); 371 observer.unobserve( entry.target ); 372 } 373 }); 374 }, { 375 threshold: .5 376 }); 377 378 nodes.forEach( function ( node ) { 379 observer.observe( node ); 380 }); 381 382 } 383}; 384 385components.campaignMonitor = { 386 selector: '.campaign-mailform', 387 styles: '/assets/components/rd-mailform/rd-mailform.css', 388 script: '/assets/components/jquery/jquery.min.js', 389 init: function ( nodes ) { 390 /** 391 * @desc Check if all elements pass validation 392 * @param {object} elements - object of items for validation 393 * @param {object} captcha - captcha object for validation 394 * @return {boolean} 395 */ 396 function isValidated(elements, captcha) { 397 let results, errors = 0; 398 399 if (elements.length) { 400 for (let j = 0; j < elements.length; j++) { 401 402 let $input = $(elements[j]); 403 if ((results = $input.regula('validate')).length) { 404 for (let k = 0; k < results.length; k++) { 405 errors++; 406 $input.siblings(".form-validation").text(results[k].message).parent().addClass("has-error"); 407 } 408 } else { 409 $input.siblings(".form-validation").text("").parent().removeClass("has-error") 410 } 411 } 412 413 if (captcha) { 414 if (captcha.length) { 415 return validateReCaptcha(captcha) && errors === 0 416 } 417 } 418 419 return errors === 0; 420 } 421 return true; 422 } 423 424 let $nodes = $(nodes); 425 426 for ( let i = 0; i < $nodes.length; i++ ) { 427 let $campaignItem = $($nodes[i]); 428 429 $campaignItem.on('submit', $.proxy(function (e) { 430 e.preventDefault(); 431 432 let data = {}, 433 url = this.attr('action'), 434 dataArray = this.serializeArray(), 435 $output = $("#" + $nodes.attr("data-form-output")), 436 $this = $(this); 437 438 for ( let i = 0; i < dataArray.length; i++) { 439 data[dataArray[i].name] = dataArray[i].value; 440 } 441 442 $.ajax({
443 data: data, 444 url: url, 445 dataType: 'jsonp', 446 error: function (resp, text) { 447 $output.html('Server error: ' + text); 448 449 setTimeout(function () { 450 $output.removeClass("active"); 451 }, 4000); 452 }, 453 success: function (resp) { 454 $output.html(resp.Message).addClass('active'); 455 456 setTimeout(function () { 457 $output.removeClass("active"); 458 }, 6000); 459 }, 460 beforeSend: function (data) { 461 // Stop request if inputs are invalid 462 if ( window.xMode || !isValidated( $this.find( '[data-constraints]' ) ) ) 463 return false; 464 465 $output.html('Submitting...').addClass('active'); 466 } 467 }); 468 469 // Clear inputs after submit 470 let inputs = $this[0].getElementsByTagName('input'); 471 for (let i = 0; i < inputs.length; i++) { 472 inputs[i].value = ''; 473 let label = document.querySelector( '[for="'+ inputs[i].getAttribute( 'id' ) +'"]' ); 474 if( label ) label.classList.remove( 'focus', 'not-empty' ); 475 } 476 477 return false; 478 }, $campaignItem)); 479 } 480 } 481}; 482 483components.counter = { 484 selector: '[data-counter]', 485 styles: '/assets/components/counter/counter.css', 486 script: [ 487 '/assets/components/util/util.min.js', 488 '/assets/components/counter/counter.min.js', 489 ], 490 init: function ( nodes ) { 491 let observer = new IntersectionObserver( function ( entries ) { 492 let observer = this; 493 494 entries.forEach( function ( entry ) { 495 let node = entry.target; 496 497 if ( entry.isIntersecting ) { 498 node.counter.run(); 499 observer.unobserve( node ); 500 } 501 }); 502 }, { 503 rootMargin: '0px', 504 threshold: 1.0 505 }); 506 507 nodes.forEach( function ( node ) { 508 let counter = aCounter( Object.assign( { 509 node: node, 510 duration: 1000 511 }, parseJSON( node.getAttribute( 'data-counter' ) ) ) ); 512 513 if ( window.xMode ) { 514 counter.run(); 515 } else { 516 observer.observe( node ); 517 } 518 }) 519 } 520}; 521 522components.countdown = { 523 selector: '[ data-countdown ]', 524 styles: '/assets/components/countdown/countdown.css', 525 script: [ 526 '/assets/components/util/util.min.js', 527 '/assets/components/progress-circle/progress-circle.min.js', 528 '/assets/components/countdown/countdown.min.js' 529 ], 530 init: function ( nodes ) { 531 nodes.forEach( function ( node ) { 532 aCountdown( Object.assign( { 533 node: node, 534 tick: 100 535 }, parseJSON( node.getAttribute( 'data-countdown' ) ) ) ); 536 } ) 537 } 538}; 539 540components.lightgallery = { 541 selector: '[data-lightgallery]', 542 styles: '/assets/components/lightgallery/lightgallery.css', 543 script: [ 544 '/assets/components/jquery/jquery.min.js', 545 '/assets/components/lightgallery/lightgallery.min.js', 546 '/assets/components/util/util.min.js' 547 ], 548 init: function ( nodes ) { 549 if ( !window.xMode ) { 550 nodes.forEach( function ( node ) { 551 node = $( node ); 552 let 553 defaults = { 554 thumbnail: true, 555 selector: '.lightgallery-item', 556 youtubePlayerParams: { 557 modestbranding: 1, 558 showinfo: 0, 559 rel: 0, 560 controls: 0 561 }, 562 vimeoPlayerParams: { 563 byline : 0, 564 portrait : 0, 565 color : 'A90707' 566 } 567 }, 568 options = parseJSON( node.attr( 'data-lightgallery' ) ); 569 570 node.lightGallery( Util.merge( [ defaults, options ] ) ); 571 }); 572 } 573 } 574}; 575 576components.mailchimp = { 577 selector: '.mailchimp-mailform', 578 styles: '/assets/components/rd-mailform/rd-mailform.css', 579 script: '/assets/components/jquery/jquery.min.js', 580 init: function ( nodes ) { 581 let $nodes = $( nodes ); 582 583 for ( let i = 0; i < $nodes.length; i++ ) { 584 let 585 $mailchimpItem = $($nodes[i]), 586 $email = $mailchimpItem.find('input[type="email"]'); 587 588 // Required by MailChimp 589 $mailchimpItem.attr('novalidate', 'true'); 590 $email.attr('name', 'EMAIL'); 591 592 $mailchimpItem.on('submit', $.proxy( function ( $email, event ) { 593 event.preventDefault(); 594 595 let 596 $this = this, 597 data = {}, 598 url = $this.attr('action').replace('/post?', '/post-json?').concat('&c=?'), 599 dataArray = $this.serializeArray(), 600 $output = $("#" + $this.attr("data-form-output")); 601 602 for ( let i = 0; i < dataArray.length; i++ ) { 603 data[dataArray[i].name] = dataArray[i].value; 604 } 605 606 $.ajax({
607 data: data, 608 url: url, 609 dataType: 'jsonp', 610 error: function (resp, text) { 611 $output.html('Server error: ' + text); 612 613 setTimeout(function () { 614 $output.removeClass("active"); 615 }, 4000); 616 }, 617 success: function (resp) { 618 $output.html(resp.msg).addClass('active'); 619 $email[0].value = ''; 620 var $label = $('[for="'+ $email.attr( 'id' ) +'"]'); 621 if ( $label.length ) $label.removeClass( 'focus not-empty' ); 622 623 setTimeout(function () { 624 $output.removeClass("active"); 625 }, 6000); 626 }, 627 beforeSend: function (data) { 628 var isValidated = (function () { 629 var results, errors = 0; 630 var elements = $this.find('[data-constraints]'); 631 var captcha = null; 632 if (elements.length) { 633 for (var j = 0; j < elements.length; j++) { 634 635 var $input = $(elements[j]); 636 if ((results = $input.regula('validate')).length) { 637 for (var k = 0; k < results.length; k++) { 638 errors++; 639 $input.siblings(".form-validation").text(results[k].message).parent().addClass("has-error"); 640 } 641 } else { 642 $input.siblings(".form-validation").text("").parent().removeClass("has-error") 643 } 644 } 645 646 if (captcha) { 647 if (captcha.length) { 648 return validateReCaptcha(captcha) && errors === 0 649 } 650 } 651 652 return errors === 0; 653 } 654 return true; 655 })(); 656 657 // Stop request if builder or inputs are invalid 658 if ( window.xMode || !isValidated ) return false; 659 660 $output.html('Submitting...').addClass('active'); 661 } 662 }); 663 664 return false; 665 }, $mailchimpItem, $email )); 666 } 667 } 668}; 669 670components.modal = { 671 selector: '[data-modal]', 672 styles: '/assets/components/modal/modal.css', 673 script: [ 674 '/assets/components/jquery/jquery.min.js', 675 '/assets/components/bootstrap/js/popper.js', 676 '/assets/components/bootstrap/js/bootstrap.min.js' 677 ], 678 init: function ( nodes ) { 679 nodes.forEach( function ( node ) { 680 let params = parseJSON( node.getAttribute( 'data-modal' ) ); 681 node.addEventListener( 'click', function () { 682 $( params.target ).modal(); 683 } ); 684 }); 685 } 686}; 687 688components.multiswitch = { 689 selector: '[data-multi-switch]', 690 script: [ 691 '/assets/components/current-device/current-device.min.js', 692 '/assets/components/multiswitch/multiswitch.min.js' 693 ], 694 init: function ( nodes ) { 695 //let click = device.ios() ? 'touchstart' : 'click'; 696 let click = 'click'; 697 698 nodes.forEach( function ( node ) { 699 if ( node.tagName === 'A' ) { 700 node.addEventListener( click, function ( event ) { 701 event.preventDefault(); 702 }); 703 } 704 705 MultiSwitch( Object.assign( { 706 node: node, 707 event: click, 708 }, parseJSON( node.getAttribute( 'data-multi-switch' ) ) ) ); 709 }); 710 } 711}; 712 713components.nav = { 714 selector: '.nav', 715 styles: '/assets/components/nav/nav.css', 716 script: [ 717 '/assets/components/jquery/jquery.min.js', 718 '/assets/components/bootstrap/js/popper.js', 719 '/assets/components/bootstrap/js/bootstrap.min.js' 720 ], 721 init: function ( nodes ) { 722 nodes.forEach( function ( node ) { 723 $( node ).on( 'click', function ( event ) { 724 event.preventDefault(); 725 $( this ).tab( 'show' ); 726 }); 727 728 $( node ).find( 'a[data-toggle="tab"]' ).on( 'shown.bs.tab', function () { 729 window.dispatchEvent( new Event( 'resize' ) ); 730 }); 731 }); 732 } 733}; 734 735components.owlCarousel = { 736 selector: '.owl-carousel', 737 styles: [ 738 '/assets/components/owl-carousel/owl.carousel.css', 739 '/assets/components/mdi/mdi.css' 740 ], 741 script: [ 742 '/assets/components/jquery/jquery.min.js', 743 '/assets/components/owl-carousel/owl.carousel.min.js', 744 '/assets/components/util/util.min.js' 745 ], 746 init: function ( nodes ) { 747 nodes.forEach( function ( node ) { 748 let 749 params = parseJSON( node.getAttribute( 'data-owl' ) ), 750 defaults = { 751 items: 1, 752 margin: 30, 753 loop: false, 754 mouseDrag: true, 755 stagePadding: 0, 756 nav: false, 757 navText: [], 758 dots: false, 759 autoplay: false, 760 autoplayHoverPause: true 761 }, 762 xMode = { 763 autoplay: false, 764 loop: false, 765 mouseDrag: false 766 }, 767 generated = { 768 autoplay: node.getAttribute( 'data-autoplay' ) !== 'false', 769 loop: node.getAttribute( 'data-loop' ) !== 'false', 770 mouseDrag: node.getAttribute( 'data-mouse-drag' ) !== 'false', 771 responsive: {} 772 }, 773 aliaces = [ '-', '-sm-', '-md-', '-lg-', '-xl-', '-xxl-' ], 774 values = [ 0, 576, 768, 992, 1200, 1600 ], 775 responsive = generated.responsive; 776 777 for ( let j = 0; j < values.length; j++ ) { 778 responsive[ values[ j ] ] = {}; 779 780 for ( let k = j; k >= -1; k-- ) { 781 if ( !responsive[ values[ j ] ][ 'items' ] && node.getAttribute( 'data' + aliaces[ k ] + 'items' ) ) { 782 responsive[ values[ j ] ][ 'items' ] = k < 0 ? 1 : parseInt( node.getAttribute( 'data' + aliaces[ k ] + 'items' ), 10 ); 783 } 784 if ( !responsive[ values[ j ] ][ 'stagePadding' ] && responsive[ values[ j ] ][ 'stagePadding' ] !== 0 && node.getAttribute( 'data' + aliaces[ k ] + 'stage-padding' ) ) { 785 responsive[ values[ j ] ][ 'stagePadding' ] = k < 0 ? 0 : parseInt( node.getAttribute( 'data' + aliaces[ k ] + 'stage-padding' ), 10 ); 786 } 787 if ( !responsive[ values[ j ] ][ 'margin' ] && responsive[ values[ j ] ][ 'margin' ] !== 0 && node.getAttribute( 'data' + aliaces[ k ] + 'margin' ) ) { 788 responsive[ values[ j ] ][ 'margin' ] = k < 0 ? 30 : parseInt( node.getAttribute( 'data' + aliaces[ k ] + 'margin' ), 10 ); 789 } 790 } 791 } 792 793 node.owl = $( node ); 794 $( node ).owlCarousel( Util.merge( window.xMode ? [ defaults, params, generated, xMode ] : [ defaults, params, generated ] ) ); 795 }); 796 } 797}; 798 799components.progressLinear = { 800 selector: '.progress-linear', 801 styles: '/assets/components/progress-linear/progress-linear.css', 802 script: [ 803 '/assets/components/util/util.min.js', 804 '/assets/components/counter/counter.min.js' 805 ], 806 init: function ( nodes ) { 807 let observer = new IntersectionObserver( function ( entries ) { 808 let observer = this; 809
810 entries.forEach( function ( entry ) { 811 let node = entry.target; 812 813 if ( entry.isIntersecting ) { 814 node.counter.run(); 815 observer.unobserve( node ); 816 } 817 }); 818 }, { 819 rootMargin: '0px', 820 threshold: 1.0 821 }); 822 823 nodes.forEach( function ( node ) { 824 let 825 bar = node.querySelector( '.progress-linear-bar' ), 826 counter = node.counter = aCounter({ 827 node: node.querySelector( '.progress-linear-counter' ), 828 duration: 3000, 829 onStart: function ( value ) { 830 bar.style.width = this.params.to +'%'; 831 } 832 }); 833 834 if ( window.xMode ) { 835 counter.run(); 836 } else { 837 observer.observe( node ); 838 } 839 }); 840 } 841}; 842 843components.regula = { 844 selector: '[data-constraints]', 845 styles: '/assets/components/regula/regula.css', 846 script: [ 847 '/assets/components/jquery/jquery.min.js', 848 '/assets/components/regula/regula.min.js' 849 ], 850 init: function ( nodes ) { 851 let elements = $( nodes ); 852 853 // Custom validator - phone number 854 regula.custom({ 855 name: 'PhoneNumber', 856 defaultMessage: 'ÐевеÑнÑй ÑоÑмаÑ', 857 validator: function() { 858 return /^((\+?375|(8[\s\-]?0))[\s\-]?)(\d[\s\-]?){9}$/i.test( this.value ); 859 } 860 }); 861 862 regula.custom({ 863 name: 'FIO', 864 defaultMessage: 'ÐевеÑнÑй ÑоÑмаÑ', 865 validator: function() { 866 return this.value.split(" ").length - 1 >= 2; 867 } 868 }); 869 870 regula.custom({ 871 name: 'PhoneLength', 872 defaultMessage: 'Ðведенное знаÑение должно бÑÑÑ Ð±Ð¾Ð»ÐµÐµ 9 ÑиÑÑ', 873 validator: function() { 874 return this.value.length >= 9; 875 } 876 }); 877 878 regula.custom({ 879 name: 'CustomEmail', 880 defaultMessage: 'ÐевеÑнÑй ÑоÑмаÑ', 881 validator: function() { 882 if ( this.value === '' ) return true; 883 else return /^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$/i.test( this.value ); 884 } 885 }); 886 887 for (let i = 0; i < elements.length; i++) { 888 let o = $(elements[i]), v; 889 o.addClass("form-control-has-validation").after("<span class='form-validation'></span>"); 890 v = o.parent().find(".form-validation"); 891 if (v.is(":last-child")) o.addClass("form-control-last-child"); 892 } 893 894 elements.on('input change propertychange blur', function (e) { 895 let $this = $(this), results; 896 897 if (e.type !== "blur") if (!$this.parent().hasClass("has-error")) return; 898 if ($this.parents('.rd-mailform').hasClass('success')) return; 899 900 if (( results = $this.regula('validate') ).length) { 901 for (let i = 0; i < results.length; i++) { 902 $this.siblings(".form-validation").text(results[i].message).parent().addClass("has-error"); 903 } 904 } else { 905 $this.siblings(".form-validation").text("").parent().removeClass("has-error") 906 } 907 }).regula('bind'); 908 909 let regularConstraintsMessages = [ 910 { 911 type: regula.Constraint.Required, 912 newMessage: "Ðоле обÑзаÑелÑно Ð´Ð»Ñ Ð·Ð°Ð¿Ð¾Ð»Ð½ÐµÐ½Ð¸Ñ." 913 }, 914 { 915 type: regula.Constraint.Email, 916 newMessage: "ÐдÑÐµÑ ÑлекÑÑонной поÑÑÑ Ð½ÐµÐ´ÐµÐ¹ÑÑвиÑелен." 917 }, 918 { 919 type: regula.Constraint.Numeric, 920 newMessage: "Ðожно вводиÑÑ ÑолÑко ÑиÑÑÑ" 921 }, 922 { 923 type: regula.Constraint.Selected, 924 newMessage: "Please choose an option." 925 } 926 ]; 927 928 929 for (let i = 0; i < regularConstraintsMessages.length; i++) { 930 let regularConstraint = regularConstraintsMessages[i]; 931 932 regula.override({ 933 constraintType: regularConstraint.type, 934 defaultMessage: regularConstraint.newMessage 935 }); 936 } 937 } 938}; 939 940components.rdCalendar = { 941 selector: '.rd-calendar', 942 styles: [ 943 '/assets/components/rd-calendar/rd-calendar.css', 944 '/assets/components/prompt/prompt.css', 945 '/assets/components/mdi/mdi.css', 946 ], 947 script: [ 948 '/assets/components/jquery/jquery.min.js', 949 '/assets/components/rd-calendar/rd-calendar-fixed.min.js', 950 '/assets/components/prompt/prompt.js' 951 ], 952 init: function ( nodes ) { 953 function initEvents ( calendar ) { 954 let events = calendar.querySelectorAll( '.rdc-table_has-events' ); 955
956 events.forEach( function ( node ) { 957 node.addEventListener( 'click', function ( event ) { 958 event.preventDefault(); 959 event.stopPropagation(); 960 961 const calendarEventsContainer = document.querySelector('.calendar-events__container') 962 calendarEventsContainer.innerHTML = node.querySelector( '.rdc-table_events' ).innerHTML 963 calendarEventsContainer.classList.add('active') 964 965 const productImage = document.querySelector('.product-img') 966 if (productImage) { 967 productImage.classList.add('blur') 968 } 969 }); 970 }); 971 } 972 973 nodes.forEach( function ( node ) { 974 $( node ).rdCalendar({ 975 days: $( node ).attr("data-days") ? $( node ).attr("data-days").split(/\s?,\s?/i) : [ 'SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA' ], 976 months: $( node ).attr("data-months") ? $( node ).attr("data-months").split(/\s?,\s?/i) : [ 'SU', 'MO', 'TU', 'WE', 'TH', 'FR', 'SA' ] 977 }); 978 initEvents( node ); 979 $('.rdc-next, .rdc-prev').on( "click", initEvents.bind( null, node ) ); 980 }); 981 } 982}; 983 984components.rdMailform = { 985 selector: '.rd-mailform', 986 styles: [ 987 '/assets/components/rd-mailform/rd-mailform.css', 988 '/assets/components/font-awesome/font-awesome.css' 989 ], 990 script: [ 991 '/assets/components/jquery/jquery.min.js', 992 '/assets/components/rd-mailform/rd-mailform.min.js', 993 ], 994 init: function ( nodes ) { 995 let i, j, k, 996 $captchas = $( nodes ).find( '.recaptcha' ), 997 msg = { 998 'MF000': 'Successfully sent!', 999 'MF001': 'Recipients are not set!', 1000 'MF002': 'Form will not work locally!', 1001 'MF003': 'Please, define email field in your form!', 1002 'MF004': 'Please, define type of your form!', 1003 'MF254': 'Something went wrong with PHPMailer!', 1004 'MF255': 'Aw, snap! Something went wrong.' 1005 }; 1006 1007 if ( $captchas.length ) { 1008 $.getScript("//www.google.com/recaptcha/api.js?onload=onloadCaptchaCallback&render=explicit&hl=en"); 1009 } 1010 1011 /** 1012 * @desc Check if all elements pass validation 1013 * @param {object} elements - object of items for validation 1014 * @param {object} captcha - captcha object for validation 1015 * @return {boolean} 1016 */ 1017 function isValidated(elements, captcha) { 1018 let results, errors = 0; 1019 1020 if (elements.length) { 1021 for (let j = 0; j < elements.length; j++) { 1022 1023 let $input = $(elements[j]); 1024 if ((results = $input.regula('validate')).length) { 1025 for (k = 0; k < results.length; k++) { 1026 errors++; 1027 $input.siblings(".form-validation").text(results[k].message).parent().addClass("has-error"); 1028 } 1029 } else { 1030 $input.siblings(".form-validation").text("").parent().removeClass("has-error") 1031 } 1032 } 1033 1034 if (captcha) { 1035 if (captcha.length) { 1036 return validateReCaptcha(captcha) && errors === 0 1037 } 1038 } 1039 1040 return errors === 0; 1041 } 1042 return true; 1043 } 1044 1045 /** 1046 * @desc Validate google reCaptcha 1047 * @param {object} captcha - captcha object for validation 1048 * @return {boolean} 1049 */ 1050 function validateReCaptcha(captcha) { 1051 let captchaToken = captcha.find('.g-recaptcha-response').val(); 1052 1053 if (captchaToken.length === 0) { 1054 captcha 1055 .siblings('.form-validation') 1056 .html('Please, prove that you are not robot.') 1057 .addClass('active'); 1058 captcha 1059 .closest('.form-wrap') 1060 .addClass('has-error'); 1061 1062 captcha.on('propertychange', function () { 1063 let $this = $(this), 1064 captchaToken = $this.find('.g-recaptcha-response').val(); 1065 1066 if (captchaToken.length > 0) { 1067 $this 1068 .closest('.form-wrap') 1069 .removeClass('has-error'); 1070 $this 1071 .siblings('.form-validation') 1072 .removeClass('active') 1073 .html(''); 1074 $this.off('propertychange'); 1075 } 1076 }); 1077 1078 return false; 1079 } 1080 1081 return true; 1082 } 1083 1084 /** 1085 * @desc Initialize Google reCaptcha 1086 */ 1087 window.onloadCaptchaCallback = function () { 1088 for (let i = 0; i < $captchas.length; i++) { 1089 let 1090 $captcha = $($captchas[i]), 1091 resizeHandler = (function() { 1092 let 1093 frame = this.querySelector( 'iframe' ), 1094 inner = this.firstElementChild, 1095 inner2 = inner.firstElementChild, 1096 containerRect = null, 1097 frameRect = null, 1098 scale = null; 1099 1100 inner2.style.transform = ''; 1101 inner.style.height = 'auto'; 1102 inner.style.width = 'auto'; 1103 1104 containerRect = this.getBoundingClientRect(); 1105 frameRect = frame.getBoundingClientRect(); 1106 scale = containerRect.width/frameRect.width; 1107 1108 if ( scale < 1 ) { 1109 inner2.style.transform = 'scale('+ scale +')'; 1110 inner2.style.transformOrigin = 'top left'; 1111 inner.style.height = ( frameRect.height * scale ) + 'px'; 1112 inner.style.width = ( frameRect.width * scale ) + 'px'; 1113 } 1114 }).bind( $captchas[i] ); 1115 1116 grecaptcha.render( 1117 $captcha.attr('id'), 1118 { 1119 sitekey: $captcha.attr('data-sitekey'), 1120 size: $captcha.attr('data-size') ? $captcha.attr('data-size') : 'normal', 1121 theme: $captcha.attr('data-theme') ? $captcha.attr('data-theme') : 'light', 1122 callback: function () { 1123 $('.recaptcha').trigger('propertychange'); 1124 } 1125 } 1126 ); 1127 1128 $captcha.after("<span class='form-validation'></span>"); 1129 1130 if ( $captchas[i].hasAttribute( 'data-auto-size' ) ) { 1131 resizeHandler(); 1132 window.addEventListener( 'resize', resizeHandler ); 1133 } 1134 } 1135 }; 1136 1137 for ( i = 0; i < nodes.length; i++ ) { 1138 let 1139 $form = $(nodes[i]), 1140 formHasCaptcha = false; 1141 1142 $form.attr('novalidate', 'novalidate').ajaxForm({ 1143 data: { 1144 "form-type": $form.attr("data-form-type") || "contact", 1145 "counter": i 1146 }, 1147 beforeSubmit: function (arr, $form, options) { 1148 if ( window.xMode ) return; 1149 1150 let 1151 form = $(nodes[this.extraData.counter]), 1152 inputs = form.find("[data-constraints]"), 1153 output = $("#" + form.attr("data-form-output")), 1154 captcha = form.find('.recaptcha'), 1155 captchaFlag = true; 1156 1157 output.removeClass("active error success"); 1158 1159 if (isValidated(inputs, captcha)) { 1160 1161 // veify reCaptcha 1162 if (captcha.length) {
1163 let captchaToken = captcha.find('.g-recaptcha-response').val(), 1164 captchaMsg = { 1165 'CPT001': 'Please, setup you "site key" and "secret key" of reCaptcha', 1166 'CPT002': 'Something wrong with google reCaptcha' 1167 }; 1168 1169 formHasCaptcha = true; 1170 1171 $.ajax({ 1172 method: "POST", 1173 url: "components/rd-mailform/reCaptcha.php", 1174 data: {'g-recaptcha-response': captchaToken}, 1175 async: false 1176 }) 1177 .done(function (responceCode) { 1178 if (responceCode !== 'CPT000') { 1179 if (output.hasClass("snackbar")) { 1180 output.html('<div class="snackbar-inner"><div class="snackbar-title"><span class="icon snackbar-icon fa-check"></span>'+ captchaMsg[responceCode] +'</div></div>'); 1181 1182 setTimeout(function () { 1183 output.removeClass("active"); 1184 }, 3500); 1185 1186 captchaFlag = false; 1187 } else { 1188 output.html(captchaMsg[responceCode]); 1189 } 1190 1191 output.addClass("active"); 1192 } 1193 });
1194 } 1195 1196 if (!captchaFlag) { 1197 return false; 1198 } 1199 1200 form.addClass('form-in-process'); 1201 1202 if (output.hasClass("snackbar")) { 1203 output.html('<div class="snackbar-inner"><div class="snackbar-title"><span class="icon snackbar-icon fa-circle-o-notch fa-spin"></span>Sending</div></div>'); 1204 output.addClass("active"); 1205 } 1206 } else { 1207 return false; 1208 } 1209 }, 1210 error: function (result) { 1211 if ( window.xMode ) return; 1212 1213 let 1214 output = $("#" + $(nodes[this.extraData.counter]).attr("data-form-output")), 1215 form = $(nodes[this.extraData.counter]); 1216 1217 output.text(msg[result]); 1218 form.removeClass('form-in-process'); 1219 1220 if (formHasCaptcha) { 1221 grecaptcha.reset(); 1222 } 1223 }, 1224 success: function (result) { 1225 if ( window.xMode ) return; 1226 1227 let 1228 form = $(nodes[this.extraData.counter]), 1229 output = $("#" + form.attr("data-form-output")), 1230 select = form.find('select'); 1231 1232 form 1233 .addClass('success') 1234 .removeClass('form-in-process'); 1235 1236 if (formHasCaptcha) { 1237 grecaptcha.reset(); 1238 } 1239 1240 result = result.length === 5 ? result : 'MF255'; 1241 output.text(msg[result]); 1242 1243 if (result === "MF000") { 1244 if (output.hasClass("snackbar")) { 1245 output.html('<div class="snackbar-inner"><div class="snackbar-title"><span class="icon snackbar-icon fa-check"></span>'+ msg[result] +'</div></div>'); 1246 } else { 1247 output.addClass("active success"); 1248 } 1249 } else { 1250 if (output.hasClass("snackbar")) { 1251 output.html('<div class="snackbar-inner"><div class="snackbar-title"><span class="icon snackbar-icon fa-exclamation-triangle"></span>'+ msg[result] +'</div></div>'); 1252 } else { 1253 output.addClass("active error"); 1254 } 1255 } 1256 1257 form.clearForm(); 1258 1259 if (select.length) { 1260 select.select2("val", ""); 1261 } 1262 1263 form.find('input, textarea').trigger('blur'); 1264 1265 setTimeout(function () { 1266 output.removeClass("active error success"); 1267 form.removeClass('success'); 1268 }, 3500); 1269 } 1270 }); 1271 } 1272 } 1273}; 1274 1275components.rdNavbar = { 1276 selector: '.rd-navbar', 1277 styles: [ 1278 '/assets/components/rd-navbar/rd-navbar.css' 1279 ], 1280 script: [ 1281 '/assets/components/jquery/jquery.min.js', 1282 '/assets/components/util/util.min.js', 1283 '/assets/components/current-device/current-device.min.js', 1284 '/assets/components/rd-navbar/rd-navbar-fixed.min.js' 1285 ], 1286 dependencies: 'currentDevice', 1287 init: function ( nodes ) { 1288 nodes.forEach( function ( node ) { 1289 let 1290 backButtons = node.querySelectorAll( '.navbar-navigation-back-btn' ), 1291 params = parseJSON( node.getAttribute( 'data-rd-navbar' ) ), 1292 defaults = { 1293 stickUpClone: false, 1294 anchorNav: false, 1295 autoHeight: false, 1296 stickUpOffset: '1px', 1297 responsive: { 1298 0: { 1299 layout: 'rd-navbar-fixed', 1300 deviceLayout: 'rd-navbar-fixed', 1301 focusOnHover: 'ontouchstart' in window, 1302 stickUp: false 1303 }, 1304 992: { 1305 layout: 'rd-navbar-fixed', 1306 deviceLayout: 'rd-navbar-fixed', 1307 focusOnHover: 'ontouchstart' in window, 1308 stickUp: false 1309 }, 1310 1200: { 1311 layout: 'rd-navbar-fullwidth', 1312 deviceLayout: 'rd-navbar-fullwidth', 1313 stickUp: true, 1314 stickUpOffset: '1px', 1315 autoHeight: true 1316 } 1317 }, 1318 callbacks: { 1319 onStuck: function () { 1320 document.documentElement.classList.add( 'rd-navbar-stuck' ); 1321 }, 1322 onUnstuck: function () { 1323 document.documentElement.classList.remove( 'rd-navbar-stuck' ); 1324 }, 1325 onDropdownToggle: function () { 1326 if ( this.classList.contains( 'opened' ) ) { 1327 this.parentElement.classList.add( 'overlaid' ); 1328 } else { 1329 this.parentElement.classList.remove( 'overlaid' ); 1330 } 1331 }, 1332 onDropdownClose: function () { 1333 this.parentElement.classList.remove( 'overlaid' ); 1334 } 1335 } 1336 }, 1337 xMode = { 1338 stickUpClone: false, 1339 anchorNav: false, 1340 responsive: { 1341 0: { 1342 stickUp: false, 1343 stickUpClone: false 1344 }, 1345 992: { 1346 stickUp: false, 1347 stickUpClone: false 1348 }, 1349 1200: { 1350 stickUp: false, 1351 stickUpClone: false 1352 } 1353 }, 1354 callbacks: { 1355 onDropdownOver: function () { return false; } 1356 } 1357 }, 1358 navbar = node.RDNavbar = new RDNavbar( node, Util.merge( window.xMode ? [ defaults, params, xMode ] : [ defaults, params ] ) ); 1359 1360 if ( backButtons.length ) { 1361 backButtons.forEach( function ( btn ) { 1362 btn.addEventListener( 'click', function () { 1363 let 1364 submenu = this.closest( '.rd-navbar-submenu' ), 1365 parentmenu = submenu.parentElement; 1366 1367 navbar.dropdownToggle.call( submenu, navbar ); 1368 });
1369 }); 1370 } 1371 }) 1372 } 1373}; 1374 1375components.rdRange = { 1376 selector: '.rd-range', 1377 styles: '/assets/components/rd-range/rd-range.css', 1378 script: [ 1379 '/assets/components/jquery/jquery.min.js', 1380 '/assets/components/rd-range/rd-range.min.js' 1381 ], 1382 init: function ( nodes ) { 1383 nodes.forEach( function ( node ) { 1384 $( node ).RDRange({}); 1385 }); 1386 } 1387}; 1388 1389components.rdSearch = { 1390 selector: '[data-rd-search]', 1391 styles: '/assets/components/rd-search/rd-search.css', 1392 script: '/assets/components/rd-search/rd-search.js', 1393 init: function ( nodes ) { 1394 nodes.forEach( function ( node ) { 1395 new RDSearch( Object.assign( { 1396 form: node, 1397 handler: 'components/rd-search/rd-search.php', 1398 output: '.rd-search-results', 1399 }, parseJSON( node.getAttribute( 'data-rd-search' ) ) ) ); 1400 }); 1401 } 1402}; 1403 1404components.select2 = { 1405 selector: '.select2', 1406 styles: '/assets/components/select2/select2.css', 1407 script: [ 1408 '/assets/components/jquery/jquery.min.js', 1409 '/assets/components/select2/select2.min.js' 1410 ], 1411 init: function ( nodes ) { 1412 nodes.forEach( function ( node ) { 1413 let 1414 params = parseJSON( node.getAttribute( 'data-select2-options' ) ), 1415 defaults = { 1416 dropdownParent: $( node ).parent(), 1417 minimumResultsForSearch: Infinity 1418 }; 1419 1420 $( node ).select2( $.extend( defaults, params ) ); 1421 $( node ).on('select2:select', function (e) { 1422 var data = e.params.data; 1423 window.location.href = data.id 1424 }) 1425 }); 1426 } 1427}; 1428 1429components.spinner = { 1430 selector: '[data-spinner]', 1431 styles: '/assets/components/spinner/spinner.css', 1432 script: [ 1433 '/assets/components/jquery/jquery.min.js', 1434 '/assets/components/jquery/jquery-ui.min.js' 1435 ], 1436 init: function ( nodes ) { 1437 nodes.forEach( function ( node ) { 1438 let 1439 params = parseJSON( node.getAttribute( 'data-spinner' ) ), 1440 defaults = { 1441 min: 0, 1442 step: 1 1443 }; 1444 1445 $( node ).spinner( $.extend( defaults, params ) ); 1446 }); 1447 } 1448}; 1449 1450components.swiper = { 1451 selector: '[data-swiper]', 1452 styles: '/assets/components/swiper/swiper.css', 1453 script: [ 1454 '/assets/components/jquery/jquery.min.js', 1455 '/assets/components/swiper/swiper.min.js', 1456 '/assets/components/util/util.min.js' 1457 ], 1458 init: function ( nodes ) { 1459 nodes.forEach( function ( node ) { 1460 let 1461 slides = node.querySelectorAll( '.swiper-slide[data-slide-bg]' ), 1462 params = parseJSON( node.getAttribute( 'data-swiper' ) ), 1463 nextItem = node.querySelector( '.swiper-next-item' ), 1464 pagination = {}; 1465 1466 if ( params.paginationImage === true ) { 1467 pagination = { 1468 type: 'bullets', 1469 renderBullet: function ( index, className ) { 1470 let 1471 indexActive = this.params.loop === true ? index + 1 : index, 1472 backgroundImage = window.getComputedStyle( this.slides[ indexActive ] ).getPropertyValue("background-image"); 1473 return "<span style='background-image:" + backgroundImage + "' class='" + className + "'></span>"; 1474 } 1475 } 1476 } 1477 1478 let 1479 defaults = { 1480 speed: 1000, 1481 loop: true, 1482 simulateTouch: false, 1483 pagination: Object.assign( { 1484 type: 'bullets', 1485 el: '.swiper-pagination', 1486 clickable: true, 1487 formatFractionCurrent: function ( number ) { 1488 return number < 10 ? '0' + number : number; 1489 }, 1490 formatFractionTotal: function ( number ) { 1491 return number < 10 ? '0' + number : number; 1492 }, 1493 renderFraction: function (currentClass, totalClass) { 1494 return '<span class="' + currentClass + '"></span>' + 1495 '/' + 1496 '<span class="' + totalClass + '"></span>'; 1497 } 1498 }, pagination ), 1499 navigation: { 1500 nextEl: '.swiper-button-next', 1501 prevEl: '.swiper-button-prev' 1502 }, 1503 autoplay: { 1504 delay: 5000 1505 }, 1506 on: { 1507 init: function () { 1508 if ( nextItem ) { 1509 let 1510 activeElement = this.params.loop === true ? this.realIndex + 2 : this.realIndex, 1511 backgroundImage = window.getComputedStyle( this.slides[ activeElement ] ).getPropertyValue("background-image"); 1512 nextItem.style.backgroundImage = backgroundImage; 1513 nextItem.querySelector( '.swiper-next-item-tag' ).textContent = this.slides[ activeElement ].getAttribute( 'data-swiper-tag' ); 1514 } 1515 }, 1516 slideChange: function () { 1517 if ( nextItem ) { 1518 let 1519 activeElement = this.params.loop === true ? this.realIndex + 2 : this.realIndex, 1520 backgroundImage = window.getComputedStyle( this.slides[ activeElement ] ).getPropertyValue( "background-image" ); 1521 nextItem.style.backgroundImage = backgroundImage; 1522 nextItem.querySelector( '.swiper-next-item-tag' ).textContent = this.slides[ activeElement ].getAttribute( 'data-swiper-tag' ); 1523 } 1524 } 1525 } 1526 }, 1527 xMode = { 1528 autoplay: false, 1529 loop: false, 1530 simulateTouch: false 1531 }; 1532
1533 // Set background image for slides with `data-slide-bg` attribute for Novi Builder 1534 slides.forEach( function ( slide ) { 1535 slide.style.backgroundImage = 'url(' + slide.getAttribute( "data-slide-bg" ) + ')'; 1536 }); 1537 1538 new Swiper( node, Util.merge( window.xMode ? [ defaults, params, xMode ] : [ defaults, params ] ) ); 1539 }); 1540 } 1541}; 1542 1543components.slick = { 1544 selector: '.slick-slider', 1545 styles: '/assets/components/slick/slick.css', 1546 script: [ 1547 '/assets/components/jquery/jquery.min.js', 1548 '/assets/components/slick/slick.min.js' 1549 ], 1550 init: function ( nodes ) { 1551 nodes.forEach( function ( node ) { 1552 let 1553 breakpoint = { sm: 576, md: 768, lg: 992, xl: 1200, xxl: 1600 }, // slick slider uses desktop first principle 1554 responsive = []; 1555 1556 // Making responsive parameters 1557 for ( let key in breakpoint ) { 1558 if ( node.hasAttribute( 'data-slick-'+ key ) ) { 1559 responsive.push({ 1560 breakpoint: breakpoint[ key ], 1561 settings: parseJSON( node.getAttribute( 'data-slick-'+ key ) ) 1562 }); 1563 } 1564 } 1565 1566 $( node ).slick({ responsive: responsive }); 1567 }); 1568 } 1569}; 1570 1571components.table = { 1572 selector: '.table', 1573 styles: '/assets/components/table/table.css' 1574}; 1575 1576components.termList = { 1577 selector: '.term-list', 1578 styles: '/assets/components/term-list/term-list.css' 1579}; 1580 1581components.tooltip = { 1582 selector: '[data-tooltip]', 1583 styles: '/assets/components/tooltip/tooltip.css', 1584 script: [ 1585 '/assets/components/jquery/jquery.min.js', 1586 '/assets/components/bootstrap/js/popper.js', 1587 '/assets/components/bootstrap/js/bootstrap.min.js' 1588 ], 1589 init: function ( nodes ) { 1590 nodes.forEach( function ( node ) { 1591 let options = parseJSON( node.getAttribute( 'data-tooltip' ) ); 1592 $( node ).tooltip( options ) 1593 }) 1594 } 1595}; 1596 1597components.toTop = { 1598 selector: 'html', 1599 styles: '/assets/components/to-top/to-top.css', 1600 script: '/assets/components/jquery/jquery.min.js', 1601 init: function () { 1602 if ( !window.xMode ) { 1603 let node = document.createElement( 'div' ); 1604 node.className = 'to-top mdi-chevron-up'; 1605 document.body.appendChild( node ); 1606 1607 node.addEventListener( 'mousedown', function () { 1608 this.classList.add( 'active' ); 1609 1610 $( 'html, body' ).stop().animate( { scrollTop:0 }, 500, 'swing', (function () { 1611 this.classList.remove( 'active' ); 1612 }).bind( this )); 1613 }); 1614 1615 document.addEventListener( 'scroll', function () { 1616 if ( window.scrollY > window.innerHeight ) node.classList.add( 'show' ); 1617 else node.classList.remove( 'show' ); 1618 }); 1619 } 1620 } 1621}; 1622 1623 1624/** 1625 * Wrapper to eliminate json errors 1626 * @param {string} str - JSON string 1627 * @returns {object} - parsed or empty object 1628 */ 1629function parseJSON ( str ) { 1630 try { 1631 if ( str ) return JSON.parse( str ); 1632 else return {}; 1633 } catch ( error ) { 1634 console.warn( error ); 1635 return {}; 1636 } 1637} 1638 1639/** 1640 * Get tag of passed data 1641 * @param {*} data 1642 * @return {string} 1643 */ 1644function objectTag ( data ) { 1645 return Object.prototype.toString.call( data ).slice( 8, -1 ); 1646} 1647 1648/** 1649 * Merging of two objects 1650 * @param {Object} source 1651 * @param {Object} merged 1652 * @return {Object} 1653 */ 1654function merge( source, merged ) { 1655 for ( let key in merged ) { 1656 let tag = objectTag( merged[ key ] ); 1657 1658 if ( tag === 'Object' ) { 1659 if ( typeof( source[ key ] ) !== 'object' ) source[ key ] = {}; 1660 source[ key ] = merge( source[ key ], merged[ key ] ); 1661 } else if ( tag !== 'Null' ) { 1662 source[ key ] = merged[ key ]; 1663 } 1664 } 1665 1666 return source; 1667} 1668 1669/** 1670 * Strict merging of two objects. Merged only parameters from the original object and with the same data type. Merge only simple data types, arrays and objects. 1671 * @param source 1672 * @param merged 1673 * @return {object} 1674 */ 1675function strictMerge( source, merged ) { 1676 for ( let key in source ) { 1677 let 1678 sTag = objectTag( source[ key ] ), 1679 mTag = objectTag( merged[ key ] ); 1680 1681 if ( [ 'Object', 'Array', 'Number', 'String', 'Boolean', 'Null', 'Undefined' ].indexOf( sTag ) > -1 ) { 1682 if ( sTag === 'Object' && sTag === mTag ) { 1683 source[ key ] = strictMerge( source[ key ], merged[ key ] ); 1684 } else if ( mTag !== 'Undefined' && ( sTag === 'Undefined' || sTag === 'Null' || sTag === mTag ) ) { 1685 source[ key ] = merged[ key ]; 1686 } 1687 } 1688 } 1689 1690 return source; 1691} 1692 1693// Main 1694window.addEventListener( 'load', function () { 1695 new ZemezCore({ 1696 debug: true, 1697 components: components, 1698 observeDOM: window.xMode, 1699 IEHandler: function ( version ) { 1700 document.documentElement.classList.add( 'ie-'+ version ); 1701 } 1702 }); 1703});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.