PageSourceSearch

https://www.rpr.cz/wp-content/themes/rpr/assets/js/theme.js?ver=1.0

js rpr.cz collected 2026-10-01 12:33:45 UTC 31,696 bytes, 913 lines download raw bytes

1'use strict';
2var theme = {
3  /**
4   * Theme's components/functions list
5   * Comment out or delete the unnecessary component.
6   * Some components have dependencies (plugins).
7   * Do not forget to remove dependency from src/js/vendor/ and recompile.
8   */
9  init: function () {
10    theme.stickyHeader();
11    theme.subMenu();
12    theme.offCanvas();
13    theme.isotope();
14    theme.onepageHeaderOffset();
15    theme.spyScroll();
16    theme.anchorSmoothScroll();
17    theme.svgInject();
18    theme.backgroundImage();
19    theme.backgroundImageMobile();
20    theme.imageHoverOverlay();
21    theme.rellax();
22    theme.scrollCue();
23    theme.swiperSlider();
24    theme.lightbox();
25    theme.plyr();
26    theme.progressBar();
27    theme.loader();
28    theme.pageProgress();
29    theme.counterUp();
30    theme.bsTooltips();
31    theme.bsPopovers();
32    theme.bsModal();
33    theme.iTooltip();
34    theme.forms();
35    theme.passVisibility();
36    theme.pricingSwitcher();
37    theme.textRotator();
38    theme.codeSnippet();
39  },
40  /**
41   * Sticky Header
42   * Enables sticky behavior on navbar on page scroll
43   * Requires assets/js/vendor/headhesive.min.js
44  */
45  stickyHeader: () => {
46    var navbar = document.querySelector(".navbar");
47    if (navbar == null) return;
48    var options = {
49      offset: 350,
50      offsetSide: 'top',
51      classes: {
52        clone: 'navbar-clone fixed',
53        stick: 'navbar-stick',
54        unstick: 'navbar-unstick',
55      },
56      onStick: function() {
57        var navbarClonedClass = this.clonedElem.classList;
58        if (navbarClonedClass.contains('transparent') && navbarClonedClass.contains('navbar-dark')) {
59          this.clonedElem.className = this.clonedElem.className.replace("navbar-dark","navbar-light");
60        }
61      }
62    };
63    var banner = new Headhesive('.navbar', options);
64  },
65  /**
66   * Sub Menus
67   * Enables multilevel dropdown
68   */
69  subMenu: () => {
70    (function($bs) {
71      const CLASS_NAME = 'has-child-dropdown-show';
72      $bs.Dropdown.prototype.toggle = function(_original) {
73          return function() {
74              document.querySelectorAll('.' + CLASS_NAME).forEach(function(e) {
75                  e.classList.remove(CLASS_NAME);
76              });
77              let dd = this._element.closest('.dropdown').parentNode.closest('.dropdown');
78              for (; dd && dd !== document; dd = dd.parentNode.closest('.dropdown')) {
79                  dd.classList.add(CLASS_NAME);
80              }
81              return _original.call(this);
82          }
83      }($bs.Dropdown.prototype.toggle);
84      document.querySelectorAll('.dropdown').forEach(function(dd) {
85          dd.addEventListener('hide.bs.dropdown', function(e) {
86              if (this.classList.contains(CLASS_NAME)) {
87                  this.classList.remove(CLASS_NAME);
88                  e.preventDefault();
89              }
90              e.stopPropagation();
91          });
92      });
93    })(bootstrap);
94  },
95  /**
96   * Offcanvas
97   * Enables offcanvas-nav, closes offcanvas on anchor clicks, focuses on input in search offcanvas
98   */
99  offCanvas: () => {
100    var navbar = document.querySelector(".navbar");
101    if (navbar == null) return;
102    const navOffCanvasBtn = document.querySelectorAll(".offcanvas-nav-btn");
103    const navOffCanvas = document.querySelector('.navbar:not(.navbar-clone) .offcanvas-nav');
104    const bsOffCanvas = new bootstrap.Offcanvas(navOffCanvas, {scroll: true});
105    const scrollLink = document.querySelectorAll('.onepage .navbar li a.scroll');
106    const searchOffcanvas = document.getElementById('offcanvas-search');
107    navOffCanvasBtn.forEach(e => {
108      e.addEventListener('click', event => {
109        bsOffCanvas.show();
110      })
111    });
112    scrollLink.forEach(e => {
113      e.addEventListener('click', event => {
114        bsOffCanvas.hide();
115      })
116    });
117    if(searchOffcanvas != null) {
118      searchOffcanvas.addEventListener('shown.bs.offcanvas', function () {
119        document.getElementById("search-form").focus();
120      });
121    }
122  },
123  /**
124   * Isotope
125   * Enables isotope grid layout and filtering
126   * Requires assets/js/vendor/isotope.pkgd.min.js
127   * Requires assets/js/vendor/imagesloaded.pkgd.min.js
128   */
129  isotope: () => {
130    var grids = document.querySelectorAll('.grid');
131    if(grids != null) {
132      grids.forEach(g => {
133        var grid = g.querySelector('.isotope');
134        var filtersElem = g.querySelector('.isotope-filter');
135        var buttonGroups = g.querySelectorAll('.isotope-filter');
136        var iso = new Isotope(grid, {
137          itemSelector: '.item',
138          layoutMode: 'masonry',
139          masonry: {
140            columnWidth: grid.offsetWidth / 12
141          },
142          percentPosition: true,
143          transitionDuration: '0.7s'
144        });
145        imagesLoaded(grid).on("progress", function() {
146          iso.layout({
147            masonry: {
148              columnWidth: grid.offsetWidth / 12
149            }
150          })
151        }),
152        window.addEventListener("resize", function() {
153          iso.arrange({
154            masonry: {
155              columnWidth: grid.offsetWidth / 12
156            }
157          });
158        }, true);
159        if(filtersElem != null) {
160          filtersElem.addEventListener('click', function(event) {
161            if(!matchesSelector(event.target, '.filter-item')) {
162              return;
163            }
164            var filterValue = event.target.getAttribute('data-filter');
165            iso.arrange({
166              filter: filterValue
167            });
168          });
169          for(var i = 0, len = buttonGroups.length; i < len; i++) {
170            var buttonGroup = buttonGroups[i];
171            buttonGroup.addEventListener('click', function(event) {
172              if(!matchesSelector(event.target, '.filter-item')) {
173                return;
174              }
175              buttonGroup.querySelector('.active').classList.remove('active');
176              event.target.classList.add('active');
177            });
178          }
179        }
180      });
181    }
182  },
183  /**
184   * Onepage Header Offset
185   * Adds an offset value to anchor point equal to sticky header height on a onepage
186   */
187  onepageHeaderOffset: () => {
188    var navbar = document.querySelector(".navbar");
189    if (navbar == null) return;
190    const header_height = document.querySelector(".navbar").offsetHeight;
191    const shrinked_header_height = 75;
192    const sections = document.querySelectorAll(".onepage section");
193    sections.forEach(section => {
194      section.style.paddingTop = shrinked_header_height + 'px';
195      section.style.marginTop = '-' + shrinked_header_height + 'px';
196    });
197    const first_section = document.querySelector(".onepage section:first-of-type");
198    if(first_section != null) {
199      first_section.style.paddingTop = header_height + 'px';
200      first_section.style.marginTop = '-' + header_height + 'px';
201    }
202  },
203  /**
204   * Spy Scroll
205   * Highlights the active nav link while scrolling through sections
206   */
207  spyScroll: () => {
208    let section = document.querySelectorAll('section[id]');
209    let navLinks = document.querySelectorAll('.nav-link.scroll');
210    window.onscroll = () => {
211      section.forEach(sec => {
212        let top = window.scrollY; //returns the number of pixels that the document is currently scrolled vertically.
213        let offset = sec.offsetTop - 0; //returns the distance of the outer border of the current element relative to the inner border of the top of the offsetParent, the closest positioned ancestor element
214        let height = sec.offsetHeight; //returns the height of an element, including vertical padding and borders, as an integer
215        let id = sec.getAttribute('id'); //gets the value of an attribute of an element
216        if (top >= offset && top < offset + height) {
217          navLinks.forEach(links => {
218            links.classList.remove('active');
219            document.querySelector(`.nav-link.scroll[href*=${id}]`).classList.add('active');
220            //[att*=val] Represents an element with the att attribute whose value contains at least one instance of the substring "val". If "val" is the empty string then the selector does not represent anything.
221          });
222        }
223      });
224    }
225  },
226  /**
227   * Anchor Smooth Scroll
228   * Adds smooth scroll animation to links with .scroll class
229   * Requires assets/js/vendor/smoothscroll.js
230   */
231  anchorSmoothScroll: () => {
232    const links = document.querySelectorAll(".scroll");
233    for(const link of links) {
234      link.addEventListener("click", clickHandler);
235    }
236    function clickHandler(e) {
237      e.preventDefault();
238      this.blur();
239      const href = this.getAttribute("href");
240      const offsetTop = document.querySelector(href).offsetTop;
241      scroll({
242        top: offsetTop,
243        behavior: "smooth"
244      });
245    }
246  },
247  /**
248   * SVGInject
249   * Replaces an img element with an inline SVG so you can apply colors to your SVGs
250   * Requires assets/js/vendor/svg-inject.min.js
251   */
252  svgInject: () => {
253    SVGInject.setOptions({
254      onFail: function(img, svg) {
255        img.classList.remove('svg-inject');
256      }
257    });
258    document.addEventListener('DOMContentLoaded', function() {
259      SVGInject(document.querySelectorAll('img.svg-inject'), {
260        useCache: true
261      });
262    });
263  },
264  /**
265   * Background Image
266   * Adds a background image link via data attribute "data-image-src"
267   */
268  backgroundImage: () => {
269    var bg = document.querySelectorAll(".bg-image");
270    for(var i = 0; i < bg.length; i++) {
271      var url = bg[i].getAttribute('data-image-src');
272      bg[i].style.backgroundImage = "url('" + url + "')";
273    }
274  },
275  /**
276   * Background Image Mobile
277   * Adds .mobile class to background images on mobile devices for styling purposes
278   */
279  backgroundImageMobile: () => {
280    var isMobile = (navigator.userAgent.match(/Android/i) || navigator.userAgent.match(/webOS/i) || navigator.userAgent.match(/iPhone/i) || navigator.userAgent.match(/iPad/i) || (navigator.platform === 'MacIntel' && navigator.maxTouchPoints > 1) || navigator.userAgent.match(/iPod/i) || navigator.userAgent.match(/BlackBerry/i)) ? true : false;
281    if(isMobile) {
282      document.querySelectorAll(".image-wrapper").forEach(e => {
283        e.classList.add("mobile")
284      })
285    }
286  },
287  /**
288   * Image Hover Overlay
289   * Adds span.bg inside .overlay for simpler markup and styling purposes
290   */
291  imageHoverOverlay: () => {
292    var overlay = document.querySelectorAll('.overlay > a, .overlay > span');
293    for(var i = 0; i < overlay.length; i++) {
294      var overlay_bg = document.createElement('span');
295      overlay_bg.className = "bg";
296      overlay[i].appendChild(overlay_bg);
297    }
298  },
299  /**
300   * Rellax.js
301   * Adds parallax animation to shapes and elements
302   * Requires assets/js/vendor/rellax.min.js
303   */
304  rellax: () => {
305    if(document.querySelector(".rellax") != null) {
306      window.onload = function() {
307        var rellax = new Rellax('.rellax', {
308          speed: 2,
309          center: true,
310          breakpoints: [576, 992, 1201]
311        });
312        var projects_overflow = document.querySelectorAll('.projects-overflow');
313        imagesLoaded(projects_overflow, function() {
314          rellax.refresh();
315        });
316      }
317    }
318  },
319  /**
320   * scrollCue.js
321   * Enables showing elements by scrolling
322   * Requires assets/js/vendor/scrollCue.min.js
323   */
324  scrollCue: () => {
325    scrollCue.init({
326      interval: -400,
327      duration: 700,
328      percentage: 0.8
329    });
330    scrollCue.update();
331  },
332  /**
333   * Swiper Slider
334   * Enables carousels and sliders
335   * Requires assets/js/vendor/swiper-bundle.min.js
336   */
337  swiperSlider: function() {
338    var carousel = document.querySelectorAll('.swiper-container');
339    for(var i = 0; i < carousel.length; i++) {
340      var slider1 = carousel[i];
341      slider1.classList.add('swiper-container-' + i);
342      var controls = document.createElement('div');
343      controls.className = "swiper-controls";
344      var pagi = document.createElement('div');
345      pagi.className = "swiper-pagination";
346      var navi = document.createElement('div');
347      navi.className = "swiper-navigation";
348      var prev = document.createElement('div');
349      prev.className = "swiper-button swiper-button-prev";
350      var next = document.createElement('div');
351      next.className = "swiper-button swiper-button-next";
352      slider1.appendChild(controls);
353      controls.appendChild(navi);
354      navi.appendChild(prev);
355      navi.appendChild(next);
356      controls.appendChild(pagi);
357      var sliderEffect = slider1.getAttribute('data-effect') ? slider1.getAttribute('data-effect') : 'slide';
358      if (slider1.getAttribute('data-items-auto') === 'true') {
359        var slidesPerViewInit = "auto";
360        var breakpointsInit = null;
361      } else {
362        var sliderItems = slider1.getAttribute('data-items') ? slider1.getAttribute('data-items') : 3; // items in all devices
363        var sliderItemsXs = slider1.getAttribute('data-items-xs') ? slider1.getAttribute('data-items-xs') : 1; // start - 575
364        var sliderItemsSm = slider1.getAttribute('data-items-sm') ? slider1.getAttribute('data-items-sm') : Number(sliderItemsXs); // 576 - 767
365        var sliderItemsMd = slider1.getAttribute('data-items-md') ? slider1.getAttribute('data-items-md') : Number(sliderItemsSm); // 768 - 991
366        var sliderItemsLg = slider1.getAttribute('data-items-lg') ? slider1.getAttribute('data-items-lg') : Number(sliderItemsMd); // 992 - 1199
367        var sliderItemsXl = slider1.getAttribute('data-items-xl') ? slider1.getAttribute('data-items-xl') 
367: Number(sliderItemsLg); // 1200 - end
368        var sliderItemsXxl = slider1.getAttribute('data-items-xxl') ? slider1.getAttribute('data-items-xxl') : Number(sliderItemsXl); // 1500 - end
369        var slidesPerViewInit = sliderItems;
370        var breakpointsInit = {
371          0: {
372            slidesPerView: Number(sliderItemsXs)
373          },
374          576: {
375            slidesPerView: Number(sliderItemsSm)
376          },
377          768: {
378            slidesPerView: Number(sliderItemsMd)
379          },
380          992: {
381            slidesPerView: Number(sliderItemsLg)
382          },
383          1200: {
384            slidesPerView: Number(sliderItemsXl)
385          },
386          1400: {
387            slidesPerView: Number(sliderItemsXxl)
388          }
389        }
390      }
391      var sliderSpeed = slider1.getAttribute('data-speed') ? slider1.getAttribute('data-speed') : 500;
392      var sliderAutoPlay = slider1.getAttribute('data-autoplay') !== 'false';
393      var sliderAutoPlayTime = slider1.getAttribute('data-autoplaytime') ? slider1.getAttribute('data-autoplaytime') : 5000;
394      var sliderAutoHeight = slider1.getAttribute('data-autoheight') === 'true';
395      var sliderResizeUpdate = slider1.getAttribute('data-resizeupdate') !== 'false';
396      var sliderAllowTouchMove = slider1.getAttribute('data-drag') !== 'false';
397      var sliderReverseDirection = slider1.getAttribute('data-reverse') === 'true';
398      var sliderMargin = slider1.getAttribute('data-margin') ? slider1.getAttribute('data-margin') : 30;
399      var sliderLoop = slider1.getAttribute('data-loop') === 'true';
400      var sliderCentered = slider1.getAttribute('data-centered') === 'true';
401      var swiper = slider1.querySelector('.swiper:not(.swiper-thumbs)');
402      var swiperTh = slider1.querySelector('.swiper-thumbs');
403      var sliderTh = new Swiper(swiperTh, {
404        slidesPerView: 5,
405        spaceBetween: 10,
406        loop: false,
407        threshold: 2,
408        slideToClickedSlide: true
409      });
410      if (slider1.getAttribute('data-thumbs') === 'true') {
411        var thumbsInit = sliderTh;
412        var swiperMain = document.createElement('div');
413        swiperMain.className = "swiper-main";
414        swiper.parentNode.insertBefore(swiperMain, swiper);
415        swiperMain.appendChild(swiper);
416        slider1.removeChild(controls);
417        swiperMain.appendChild(controls);
418      } else {
419        var thumbsInit = null;
420      }
421      var slider = new Swiper(swiper, {
422        on: {
423          beforeInit: function() {
424            if(slider1.getAttribute('data-nav') !== 'true' && slider1.getAttribute('data-dots') !== 'true') {
425              controls.remove();
426            }
427            if(slider1.getAttribute('data-dots') !== 'true') {
428              pagi.remove();
429            }
430            if(slider1.getAttribute('data-nav') !== 'true') {
431              navi.remove();
432            }
433          },
434          init: function() {
435            if(slider1.getAttribute('data-autoplay') !== 'true') {
436              this.autoplay.stop();
437            }
438            this.update();
439          }
440        },
441        autoplay: {
442          delay: sliderAutoPlayTime,
443          disableOnInteraction: false,
444          reverseDirection: sliderReverseDirection,
445          pauseOnMouseEnter: false
446        },
447        allowTouchMove: sliderAllowTouchMove,
448        speed: parseInt(sliderSpeed),
449        slidesPerView: slidesPerViewInit,
450        loop: sliderLoop,
451        centeredSlides: sliderCentered,
452        spaceBetween: Number(sliderMargin),
453        effect: sliderEffect,
454        autoHeight: sliderAutoHeight,
455        grabCursor: true,
456        resizeObserver: false,
457        updateOnWindowResize: sliderResizeUpdate,
458        breakpoints: breakpointsInit,
459        pagination: {
460          el: carousel[i].querySelector('.swiper-pagination'),
461          clickable: true
462        },
463        navigation: {
464          prevEl: slider1.querySelector('.swiper-button-prev'),
465          nextEl: slider1.querySelector('.swiper-button-next'),
466        },
467        thumbs: {
468          swiper: thumbsInit,
469        },
470      });
471    }
472  },
473  /**
474   * GLightbox
475   * Enables lightbox functionality
476   * Requires assets/js/vendor/glightbox.js
477   */
478  lightbox: () => {
479    const lightbox = GLightbox({
480      selector: '*[data-glightbox]',
481      touchNavigation: true,
482      loop: false,
483      zoomable: false,
484      autoplayVideos: true,
485      moreLength: 0,
486      slideExtraAttributes: {
487        poster: ''
488      },
489      plyr: {
490        css: '',
491        js: '',
492        config: {
493          ratio: '',
494          fullscreen: {
495            enabled: false,
496            iosNative: false
497          },
498          youtube: {
499            noCookie: true,
500            rel: 0,
501            showinfo: 0,
502            iv_load_policy: 3
503          },
504          vimeo: {
505            byline: false,
506            portrait: false,
507            title: false,
508            transparent: false
509          }
510        }
511      },
512    });
513  },
514  /**
515   * Plyr
516   * Enables media player
517   * Requires assets/js/vendor/plyr.js
518   */
519  plyr: () => {
520    var players = Plyr.setup('.player', {
521      loadSprite: true,
522    });
523  },
524  /**
525   * Progressbar
526   * Enables animated progressbars
527   * Requires assets/js/vendor/progressbar.min.js
528   * Requires assets/js/vendor/noframework.waypoints.min.js
529   */
530  progressBar: () => {
531    const pline = document.querySelectorAll(".progressbar.line");
532    const pcircle = document.querySelectorAll(".progressbar.semi-circle");
533    pline.forEach(e => {
534      var line = new ProgressBar.Line(e, {
535        strokeWidth: 6,
536        trailWidth: 6,
537        duration: 3000,
538        easing: 'easeInOut',
539        text: {
540          style: {
541            color: 'inherit',
542            position: 'absolute',
543            right: '0',
544            top: '-30px',
545            padding: 0,
546            margin: 0,
547            transform: null
548          },
549          autoStyleContainer: false
550        },
551        step: (state, line) => {
552          line.setText(Math.round(line.value() * 100) + ' %');
553        }
554      });
555      var value = e.getAttribute('data-value') / 100;
556      new Waypoint({
557        element: e,
558        handler: function() {
559          line.animate(value);
560        },
561        offset: 'bottom-in-view',
562      })
563    });
564    pcircle.forEach(e => {
565      var circle = new ProgressBar.SemiCircle(e, {
566        strokeWidth: 6,
567        trailWidth: 6,
568        duration: 2000,
569        easing: 'easeInOut',
570        step: (state, circle) => {
571          circle.setText(Math.round(circle.value() * 100));
572        }
573      });
574      var value = e.getAttribute('data-value') / 100;
575      new Waypoint({
576        element: e,
577        handler: function() {
578          circle.animate(value);
579        },
580        offset: 'bottom-in-view',
581      })
582    });
583  },
584  /**
585   * Loader
586   * 
587   */
588  loader: () => {
589    var preloader = document.querySelector('.page-loader');
590    if(preloader != null) {
591      document.body.onload = function(){
592        setTimeout(function() {
593          if( !preloader.classList.contains('done') )
594          {
595            preloader.classList.add('done');
596          }
597        }, 1000)
598      }
599    }
600  },
601  /**
602   * Page Progress
603   * Shows page progress on the bottom right corner of pages
604   */
605  pageProgress: () => {
606    var progressWrap = document.querySelector('.progress-wrap');
607    if(progressWrap != null) {
608      var progressPath = document.querySelector('.progress-wrap path');
609      var pathLength = progressPath.getTotalLength();
610      var offset = 50;
611      progressPath.style.transition = progressPath.style.WebkitTransition = 'none';
612      progressPath.style.strokeDasharray = pathLength + ' ' + pathLength;
613      progressPath.style.strokeDashoffset = pathLength;
614      progressPath.getBoundingClientRect();
615      progressPath.style.transition = progressPath.style.WebkitTransition = 'stroke-dashoffset 10ms linear';
616      window.addEventListener("scroll", function(event) {
617        var scroll = document.body.scrollTop || document.documentElement.scrollTop;
618        var height = document.documentElement.scrollHeight - document.documentElement.clientHeight;
619        var progress = pathLength - (scroll * pathLength / height);
620        progressPath.style.strokeDashoffset = progress;
621        var scrollElementPos = document.body.scrollTop || document.documentElement.scrollTop;
622        if(scrollElementPos >= offset) {
623          progressWrap.classList.add("active-progress")
624        } else {
625          progressWrap.classList.remove("active-progress")
626        }
627      });
628      progressWrap.addEventListener('click', function(e) {
629        e.preventDefault();
630        window.scroll({
631          top: 0, 
632          left: 0,
633          behavior: 'smooth'
634        });
635      });
636    }
637  },
638  /**
639   * Counter Up
640   * Counts up to a targeted number when the number becomes visible
641   * Requires assets/js/vendor/counterup.min.js
642   * Requires assets/js/vendor/noframework.waypoints.min.js
643   */
644  counterUp: () => {
645    var counterUp = window.counterUp["default"];
646    const counters = document.querySelectorAll(".counter");
647    counters.forEach(el => {
648      new Waypoint({
649        element: el,
650        handler: function() {
651          counterUp(el, {
652            duration: 1000,
653            delay: 50
654          })
655          this.destroy()
656        },
657        offset: 'bottom-in-view',
658      })
659    });
660  },
661  /**
662   * Bootstrap Tooltips
663   * Enables Bootstrap tooltips
664   * Requires Poppers library
665   */
666  bsTooltips: () => {
667    var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'))
668    var tooltipList = tooltipTriggerList.map(function(tooltipTriggerEl) {
669      return new bootstrap.Tooltip(tooltipTriggerEl, {
670        trigger: 'hover'
671      })
672    });
673    var tooltipTriggerWhite = [].slice.call(document.querySelectorAll('[data-bs-toggle="white-tooltip"]'))
674    var tooltipWhite = tooltipTriggerWhite.map(function(tooltipTriggerEl) {
675      return new bootstrap.Tooltip(tooltipTriggerEl, {
676        customClass: 'white-tooltip',
677        trigger: 'hover',
678        placement: 'left'
679      })
680    })
681  },
682  /**
683   * Bootstrap Popovers
684   * Enables Bootstrap popovers
685   * Requires Poppers library
686   */
687  bsPopovers: () => {
688    var popoverTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="popover"]'))
689    var popoverList = popoverTriggerList.map(function(popoverTriggerEl) {
690      return new bootstrap.Popover(popoverTriggerEl)
691    })
692  },
693  /**
694   * Bootstrap Modal
695   * Enables Bootstrap modal popup
696   */
697  bsModal: () => {
698    if(document.querySelector(".modal-popup") != null) {
699      var myModalPopup = new bootstrap.Modal(document.querySelector('.modal-popup'));
700      setTimeout(function() {
701        myModalPopup.show();
702      }, 200);
703    }
704    // Fixes jumping of page progress caused by modal
705    var innerWidth = window.innerWidth;
706    var clientWidth = document.body.clientWidth;
707    var scrollSize = innerWidth - clientWidth;
708    var myModalEl = document.querySelectorAll('.modal');
709    var navbarFixed = document.querySelector('.navbar.fixed');
710    var pageProgress = document.querySelector('.progress-wrap');
711    function setPadding() {
712      if(navbarFixed != null) {
713        navbarFixed.style.paddingRight = scrollSize + 'px';
714      }
715      if(pageProgress != null) {
716        pageProgress.style.marginRight = scrollSize + 'px';
717      }
718    }
719    function removePadding() {
720      if(navbarFixed != null) {
721        navbarFixed.style.paddingRight = '';
722      }
723      if(pageProgress != null) {
724       pageProgress.style.marginRight = '';
725      }
726    }
727    myModalEl.forEach(myModalEl => {
728      myModalEl.addEventListener('show.bs.modal', function(e) {
729        setPadding();
730      })
731      myModalEl.addEventListener('hidden.bs.modal', function(e) {
732        removePadding();
733      })
734    });
735  },
736  /**
737   * iTooltip
738   * Enables custom tooltip style for image hover docs/elements/hover.html
739   * Requires assets/js/vendor/itooltip.min.js
740   */
741  iTooltip: () => {
742    var tooltip = new iTooltip('.itooltip')
743    tooltip.init({
744      className: 'itooltip-inner',
745      indentX: 15,
746      indentY: 15,
747      positionX: 'right',
748      positionY: 'bottom'
749    })
750  },
751  /**
752   * Form Validation and Contact Form submit
753   * Bootstrap validation - Only sends messages if form has class ".contact-form" and is validated and shows success/fail messages
754   */
755  forms: () => {
756    (function() {
757      "use strict";
758      window.addEventListener("load", function() {
759        var forms = document.querySelectorAll(".needs-validation");
760        var inputRecaptcha = document.querySelector("input[data-recaptcha]"); 
761        window.verifyRecaptchaCallback = function (response) {
762          inputRecaptcha.value = response; 
763          inputRecaptcha.dispatchEvent(new Event("change"));
764        }
765        window.expiredRecaptchaCallback = function () {
766          var inputRecaptcha = document.querySelector("input[data-recaptcha]"); 
767          inputRecaptcha.value = ""; 
768          inputRecaptcha.dispatchEvent(new Event("change"));
769        }
770        var validation = Array.prototype.filter.call(forms, function(form) {
771          form.addEventListener("submit", function(event) {
772            if(form.checkValidity() === false) {
773              event.preventDefault();
774              event.stopPropagation();
775            }
776            form.classList.add("was-validated");
777            if(form.checkValidity() === true) {
778              event.preventDefault();
779              form.classList.remove("was-validated");
780              // Send message only if the form has class .contact-form
781              var isContactForm = form.classList.contains('contact-form');
782              if(isContactForm) {
783                var data = new FormData(form);
784                var alertClass = 'alert-danger';
785                fetch("assets/php/contact.php", {
786                  method: "post",
787                  body: data
788                }).then((data) => {
789                  if(data.ok) {
790                    alertClass = 'alert-success';
791                  }
792                  return data.text();
793                }).then((txt) => {
794                  var alertBox = '<div class="alert ' + alertClass + ' alert-dismissible fade show"><button type="button" class="btn-close" data-bs-dismiss="alert" aria-label="Close"></button>' + txt + '</div>';
795                  if(alertClass && txt) {
796                    form.querySelector(".messages").insertAdjacentHTML('beforeend', alertBox);
797                    form.reset();
798                    grecaptcha.reset();
799                  }
800                }).catch((err) => {
801                  console.log(err);
802                });
803              }
804            }
805          }, false);
806        });
807      }, false);
808    })();
809  },
810  /**
811   * Password Visibility Toggle
812   * Toggles password visibility in password input
813   */
814  passVisibility: () => {
815    let pass = document.querySelectorAll('.password-field');
816    for (let i = 0; i < pass.length; i++) {
817      let passInput = pass[i].querySelector('.form-control');
818      let passToggle = pass[i].querySelector('.password-toggle > i');
819      passToggle.addEventListener('click', (e) => {
820        if (passInput.type === "password") {
821          passInput.type = "text";
822          passToggle.classList.remove('uil-eye');
823          passToggle.classList.add('uil-eye-slash');
824        } else {
825          passInput.type = "password";
826          passToggle.classList.remove('uil-eye-slash'); 
827          passToggle.classList.add('uil-eye');
828        } 
829      }, false);
830    }
831  },
832  /**
833   * Pricing Switcher
834   * Enables monthly/yearly switcher seen on pricing tables
835   */
836  pricingSwitcher: () => {
837    if(document.querySelector(".pricing-switchers") != null) {
838      const wrapper = document.querySelectorAll(".pricing-wrapper");
839      wrapper.forEach(wrap => {
840        const switchers = wrap.querySelector(".pricing-switchers");
841        const switcher = wrap.querySelectorAll(".pricing-switcher");
842        const price = wrap.querySelectorAll(".price");
843        switchers.addEventListener("click", (e) => {
844          switcher.forEach(s => {
845            s.classList.toggle("pricing-switcher-active");
846          });
847          price.forEach(p => {
848            p.classList.remove("price-hidden");
849            p.classList.toggle("price-show");
850            p.classList.toggle("price-hide");
851          });
852        });
853      });
854    }
855  },
856  /**
857   * ReplaceMe.js
858   * Enables text rotator
859   * Requires assets/js/vendor/replaceme.min.js
860   */
861  textRotator: () => {
862    if(document.querySelector(".rotator-zoom") != null) {
863      var replace = new ReplaceMe(document.querySelector('.rotator-zoom'), {
864        animation: 'animate__animated animate__zoomIn',
865        speed: 2500,
866        separator: ',',
867        clickChange: false,
868        loopCount: 'infinite'
869      });
870    }
871    if(document.querySelector(".rotator-fade") != null) {
872      var replace = new ReplaceMe(document.querySelector('.rotator-fade'), {
873        animation: 'animate__animated animate__fadeInDown',
874        speed: 2500,
875        separator: ',',
876        clickChange: false,
877        loopCount: 'infinite'
878      });
879    }
880  },
881  /**
882   * Clipboard.js
883   * Enables clipboard on docs
884   * Requires assets/js/vendor/clipboard.min.js
885   */
886  codeSnippet: () => {
887    var btnHtml = '<button type="button" class="btn btn-sm btn-white rounded-pill btn-clipboard">Copy</button>'
888    document.querySelectorAll('.code-wrapper-inner').forEach(function(element) {
889      element.insertAdjacentHTML('beforebegin', btnHtml)
890    })
891    var clipboard = new ClipboardJS('.btn-clipboard', {
892      target: function(trigger) {
893        return trigger.nextElementSibling
894      }
895    })
896    clipboard.on('success', event => {
897      event.trigger.textContent = 'Copied!';
898      event.clearSelection();
899      setTimeout(function () {
900        event.trigger.textContent = 'Copy';
901      }, 2000);
902    });
903    var copyIconCode = new ClipboardJS('.btn-copy-icon');
904    copyIconCode.on('success', function(event) {
905      event.clearSelection();
906      event.trigger.textContent = 'Copied!';
907      window.setTimeout(function() {
908        event.trigger.textContent = 'Copy';
909      }, 2300);
910    });
911  },
912}
913theme.init();

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.