HEX
Server: Apache/2
System: Linux cp07.iserverteam.com 3.10.0-1160.119.1.el7.x86_64 #1 SMP Tue Jun 4 14:43:51 UTC 2024 x86_64
User: fliyingp (1085)
PHP: 7.4.33
Disabled: exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname
Upload Files
File: /home/fliyingp/domains/fliyingpigeon.hk/public_html/wp-content/themes/ocean-theme/js/main.js
(function () {

  if (window.__cf7HandlersAttached) {
    console.warn('CF7 handlers already attached');
    return;
  }
  window.__cf7HandlersAttached = true;

  // ВЕСЬ твой код НИЖЕ
  console.log('CF7 handlers init');



function adjustBodyMarginForFooter() {
  const footerWrapper = document.querySelector('.footer-wrapper');
  if (!footerWrapper) return;
  if (document.querySelector('.error404')) return;

  const width = window.innerWidth;
  if (width <= 1024) {
    document.body.style.marginBottom = ''; // reset on mobile
    return;
  }

  const footerHeight = footerWrapper.offsetHeight;
  document.body.style.marginBottom = `${footerHeight}px`;
}
adjustBodyMarginForFooter()
// Run on load
window.addEventListener('DOMContentLoaded', adjustBodyMarginForFooter);

// Run on resize
window.addEventListener('resize', adjustBodyMarginForFooter);



document.addEventListener('DOMContentLoaded', () => {
    const sticky = document.querySelector('.sticky-social');
    const revealContent = document.querySelector('main.reveal-content');
    const offsetFromTop = window.innerHeight * 0.35;
    const offsetFromBottom = 20;

    const allowedSections = ['hero', 'about', 'big-header', 'top-title'];

    if (!sticky || !revealContent) {
        console.warn('sticky або revealContent не знайдені!');
        return;
    }

    // Скидання стилів
    sticky.style.top = 'unset';
    sticky.style.transform = 'unset';
    sticky.style.position = 'unset';

    // Знайти останній блок із дозволених перед чужим
    const sections = Array.from(document.querySelectorAll('main.reveal-content > *'));
    let lastAllowedBlockBottom = null;

    for (let i = 0; i < sections.length - 1; i++) {
        const current = sections[i];
        const next = sections[i + 1];
        const isAllowed = allowedSections.some(cls => current.classList.contains(cls));
        const nextIsAllowed = allowedSections.some(cls => next.classList.contains(cls));

        if (isAllowed && !nextIsAllowed) {
            const rect = current.getBoundingClientRect();
            const scrollY = window.scrollY || window.pageYOffset;
            lastAllowedBlockBottom = scrollY + rect.bottom;
            break;
        }
    }

    function onScroll() {
    const stickyHeight = sticky.offsetHeight;
		console.log(stickyHeight)
    const revealRect = revealContent.getBoundingClientRect();

    // Значення за замовчуванням
    let stopAt = window.scrollY + revealRect.bottom;
		console.log(stopAt)
    if (lastAllowedBlockBottom !== null) {
        stopAt = lastAllowedBlockBottom;
    }

    const stickyBottomInViewport = offsetFromTop + stickyHeight;
    const stickyBottomInDocument = window.scrollY + stickyBottomInViewport;

const shouldStop = stickyBottomInDocument >= stopAt - stickyHeight;
		console.log(shouldStop)

    if (shouldStop) {
    const absoluteTop = stopAt - stickyHeight * 2; // 🛠️ віднімаємо offsetFromBottom
    sticky.style.position = 'absolute';
    sticky.style.top = absoluteTop + 'px';
} else {
    sticky.style.position = 'fixed';
    sticky.style.top = offsetFromTop + 'px';
}

}


    window.addEventListener('scroll', onScroll);
    window.addEventListener('resize', () => {
        // Перерахувати при ресайзі
        lastAllowedBlockBottom = null;

        for (let i = 0; i < sections.length - 1; i++) {
            const current = sections[i];
            const next = sections[i + 1];
            const isAllowed = allowedSections.some(cls => current.classList.contains(cls));
            const nextIsAllowed = allowedSections.some(cls => next.classList.contains(cls));

            if (isAllowed && !nextIsAllowed) {
                const rect = current.getBoundingClientRect();
                const scrollY = window.scrollY || window.pageYOffset;
                lastAllowedBlockBottom = scrollY + rect.bottom;
                break;
            }
        }

        onScroll();
    });

    onScroll(); // initial
	sticky.style.opacity = '1';
});


document.addEventListener("DOMContentLoaded", () => {
  const accordions = document.querySelectorAll(".accordion");

  let openFill;
  let closedFill;
  let isTechnologies = false;

  if (document.querySelector(".technologies__body-accordion")) {
    openFill = "#001C36";
    closedFill = "#001C36";
    isTechnologies = true;
  } else {
    openFill = "#F0F2F5";
    closedFill = "#F0F2F5";
  }

  const iconOpen = `
      <svg width="16" height="16" viewBox="0 0 16 16" fill="none"
           xmlns="http://www.w3.org/2000/svg">
        <path d="M3.04688 8.63996V7.35156H12.9574V8.63996H3.04688Z" fill="${openFill}"/>
      </svg>`;

  const iconClosed = `
      <svg width="16" height="16" viewBox="0 0 16 16" fill="none"
           xmlns="http://www.w3.org/2000/svg">
        <path d="M7.36428 8.64013H3.04688V7.35173H7.36428V3.02637H8.65267V7.35173H12.9574V8.64013H8.65267V12.9409H7.36428V8.64013Z"
              fill="${closedFill}"/>
      </svg>`;

  accordions.forEach((accordion) => {
    accordion.addEventListener("click", () => {
      accordion.classList.toggle("active");

      const panel = accordion.nextElementSibling;
      const iconContainer = accordion.querySelector(".faq__button");

      if (accordion.classList.contains("active")) {
        panel.style.maxHeight = `${panel.scrollHeight + 84}px`;
        if (isTechnologies) {
          panel.style.marginBottom = `84px`;
        } else {
          panel.style.paddingBottom = `84px`;
        }
        iconContainer.innerHTML = iconOpen;
      } else {
        panel.style.maxHeight = "0px";
        if (isTechnologies) {
          panel.style.marginBottom = `0`;
        } else {
          panel.style.paddingBottom = `0`;
        }
        iconContainer.innerHTML = iconClosed;
      }
    });
  });
});

document.addEventListener("DOMContentLoaded", function () {
  if (document.querySelector(".project-gallery-slider")) {
    const gallerySlider = new Swiper(".project-gallery-slider", {
      loop: false,
      slidesPerView: 1.5,
      spaceBetween: 8,
      pagination: {
        el: ".project-gallery__pagination",
        clickable: true,
      },
      navigation: {
        nextEl: ".project-gallery__next",
        prevEl: ".project-gallery__prev",
      },
      breakpoints: {
        768: {
          slidesPerView: 2.2,
        },
        1024: {
          slidesPerView: 3,
        },
      },
    });
  }
});

// document.addEventListener("DOMContentLoaded", function () {
//   const menuBtn = document.querySelector("#menuBtn");
//   const fullMenu = document.querySelector(".header__upper");
//   const exitBtn = document.querySelector("#exitBtn");

//   menuBtn.addEventListener("click", function () {
//     fullMenu.classList.toggle("opened");
//   });

//   exitBtn.addEventListener("click", function () {
//     fullMenu.classList.toggle("opened");
//   });
// });

// document.addEventListener("DOMContentLoaded", function () {
//   const langBtn = document.querySelector("#langBtn");
//   const langList = document.querySelector("#langList");
//   const langContainer = document.querySelector("#langContainer");
//   const currentLang = document.querySelector("#currentLang");
//   const fullMenuLangs = document.querySelector("#fullMenuLang");

//   langBtn?.addEventListener("click", function () {
//     const listStatus = langList.classList.contains("opened");
//     listStatus ? closeList() : openList();
//   });

//   document.addEventListener("click", function (e) {
//     if (!langContainer.contains(e.target)) {
//       closeList();
//     }
//   });

//   function openList() {
//     langList.classList.add("opened");
//   }

//   function closeList() {
//     langList.classList.remove("opened");
//   }

//   function updateLangContainer(currentLangContainer, langListContainer) {
//     const translatePressFloater = document.querySelector("#trp-floater-ls");
//     if (!translatePressFloater) return;

//     const currentObj = getCurrentLang();
//     currentLangContainer.textContent = currentObj.title;
//     langListContainer.innerHTML = getListLang();

//     function getCurrentLang() {
//       const markup = translatePressFloater.querySelector(
//         "#trp-floater-ls-current-language"
//       );
//       return {
//         title: markup?.querySelector("a")?.textContent.trim() ?? "—",
//         flag: markup?.querySelector("img")?.src ?? "",
//       };
//     }

//     function getListLang() {
//       const links = translatePressFloater.querySelectorAll(
//         "#trp-floater-ls-language-list .trp-language-wrap a"
//       );
//       const result = [];

//       links.forEach((item) => {
//         const isDisabled = item.classList.contains(
//           "trp-floater-ls-disabled-language"
//         );
//         const flag = item.querySelector("img")?.src ?? "";
//         const title = item.textContent.trim();
//         const url = item.href;

//         result.push(
//           `<a class="header-lang-list-item${
//             isDisabled ? " active" : ""
//           }" href="${url}">
//             <p class="header-lang-list-item-title">${title}</p>
//           </a>`
//         );
//       });

//       return result.join("");
//     }
//   }

//   updateLangContainer(currentLang, langList);
//   updateLangContainer(currentLang, fullMenuLangs);
// });

// document.addEventListener("DOMContentLoaded", function () {
//   const langList = document.querySelector("#langList");
//   const langContainer = document.querySelector("#langContainer");

//   function toggleOpenLangList() {
//     langList.classList.toggle("opened");
//   }

//   function closeLangListOnClickOutside(e) {
//     if (!langContainer.contains(e.target)) {
//       langList.classList.remove("opened");
//     }
//   }

//   langContainer.addEventListener("click", toggleOpenLangList);
//   document.addEventListener("click", closeLangListOnClickOutside);
// });


	document.addEventListener("DOMContentLoaded", () => {
  const popup = document.querySelector(".consult-popup");
  const closeBtn = document.querySelector("#closeConsult");
  const consultationBtn = document.querySelector("#consultationBtn");
  const consultationFullBtn = document.querySelector(".header__upper-consult-btn");

  if (!popup) return;

  const open = () => popup.classList.add("opened");
  const close = () => popup.classList.remove("opened");

  consultationBtn?.addEventListener("click", open);
  consultationFullBtn?.addEventListener("click", open);
  closeBtn?.addEventListener("click", (e) => {
    e.preventDefault();
    e.stopPropagation();
    close();
  });

  document.addEventListener("click", (e) => {
    if (!popup.classList.contains("opened")) return;

    const insideContent = e.target.closest(".consult-popup__content");
    const onOpenBtn =
      e.target.closest("#consultationBtn") ||
      e.target.closest(".header__upper-consult-btn");

    if (!insideContent && !onOpenBtn) close();
  });
});

	
document.addEventListener("DOMContentLoaded", function () {
  const customSubmit = document.querySelector(".footer__custom-submit");
  const hiddenSubmit = document.querySelector(".footer__submit");

  if (customSubmit && hiddenSubmit) {
    customSubmit.addEventListener("click", function () {
      hiddenSubmit.click();
    });
  }
});

document.addEventListener("DOMContentLoaded", function () {
  const upBtn = document.querySelector(".footer__up-btn");

  if (upBtn) {
    upBtn.addEventListener("click", function () {
      window.scrollTo({
        top: 0,
        behavior: "smooth",
      });
    });
  }
});

document.addEventListener("DOMContentLoaded", function () {
  const header = document.querySelector(".header");
  setTimeout(() => {
    header.classList.add("visible");
  }, 100);
});

document.addEventListener("DOMContentLoaded", function () {
  const title = document.querySelector(".hero__title");

  const observer = new IntersectionObserver(
    (entries, observer) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          title.classList.add("visible");
          observer.unobserve(entry.target);
        }
      });
    },
    {
      threshold: 0.5,
    }
  );

  if (title) observer.observe(title);
});

document.addEventListener("DOMContentLoaded", () => {
  const subTextsWrapper = document.querySelector(".about__sub-text-wrapper");

  if (!subTextsWrapper) return;

  const observer = new IntersectionObserver(
    (entries, observer) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          subTextsWrapper.classList.add("visible");
          observer.disconnect();
        }
      });
    },
    { threshold: 0.2 }
  );

  observer.observe(subTextsWrapper);
});

document.addEventListener("DOMContentLoaded", () => {
  const items = document.querySelectorAll(".advatages__item");

  if (!items.length) return;

  const observer = new IntersectionObserver(
    (entries, observer) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          const el = entry.target;
          const index = Array.from(items).indexOf(el);

          const direction = index % 2 === 0 ? "-100%" : "100%";
          el.style.setProperty("--translate-x", direction);

          el.classList.add("visible");
          observer.unobserve(el);
        }
      });
    },
    {
      threshold: 0.2,
    }
  );

  items.forEach((item) => observer.observe(item));
});

document.addEventListener("DOMContentLoaded", () => {
  const items = document.querySelectorAll(".services__item");

  if (items.length) {
    const itemObserver = new IntersectionObserver(
      (entries, observer) => {
        entries.forEach((entry) => {
          if (entry.isIntersecting) {
            const el = entry.target;
            const index = Array.from(items).indexOf(el);

            setTimeout(() => {
              el.classList.add("visible");
            }, index * 200);

            observer.unobserve(el);
          }
        });
      },
      {
        threshold: 0.2,
      }
    );

    items.forEach((item) => itemObserver.observe(item));
  }
});

document.addEventListener("DOMContentLoaded", () => {
  const subTextsWrapper = document.querySelector(".done-projects__body");

  if (!subTextsWrapper) return;

  const observer = new IntersectionObserver(
    (entries, observer) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          subTextsWrapper.classList.add("visible");
          observer.disconnect();
        }
      });
    },
    { threshold: 0.3 }
  );

  observer.observe(subTextsWrapper);
});

document.addEventListener("DOMContentLoaded", () => {
  const items = document.querySelectorAll(".partners__item");

  if (items.length) {
    const itemObserver = new IntersectionObserver(
      (entries, observer) => {
        entries.forEach((entry) => {
          if (entry.isIntersecting) {
            const el = entry.target;
            const index = Array.from(items).indexOf(el);

            setTimeout(() => {
              el.classList.add("visible");
            }, index * 200);

            observer.unobserve(el);
          }
        });
      },
      {
        threshold: 0.2,
      }
    );

    items.forEach((item) => itemObserver.observe(item));
  }
});

document.addEventListener("DOMContentLoaded", () => {
  const subTextsWrapper = document.querySelector(".reviews__slider-container");

  if (!subTextsWrapper) return;

  const observer = new IntersectionObserver(
    (entries, observer) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          subTextsWrapper.classList.add("visible");
          observer.disconnect();
        }
      });
    },
    { threshold: 0.1 }
  );

  observer.observe(subTextsWrapper);
});

document.addEventListener("DOMContentLoaded", () => {
  const subTextsWrapper = document.querySelector(".news__body");

  if (!subTextsWrapper) return;

  const observer = new IntersectionObserver(
    (entries, observer) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          subTextsWrapper.classList.add("visible");
          observer.disconnect();
        }
      });
    },
    { threshold: 0.1 }
  );

  observer.observe(subTextsWrapper);
});

document.addEventListener("DOMContentLoaded", () => {
  const items = document.querySelectorAll(".advantages-list__item");

  if (items.length) {
    const itemObserver = new IntersectionObserver(
      (entries, observer) => {
        entries.forEach((entry) => {
          if (entry.isIntersecting) {
            const el = entry.target;
            const index = Array.from(items).indexOf(el);

            setTimeout(() => {
              el.classList.add("visible");
            }, index * 200);

            observer.unobserve(el);
          }
        });
      },
      {
        threshold: 0.2,
      }
    );

    items.forEach((item) => itemObserver.observe(item));
  }
});

document.addEventListener("DOMContentLoaded", () => {
  const mainTexts = document.querySelectorAll(".catalog__title");
  const subTextsWrapper = document.querySelector(".catalog__image");

  if (!mainTexts.length || !subTextsWrapper) return;

  const observer = new IntersectionObserver(
    (entries, observer) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          mainTexts.forEach((title) => title.classList.add("visible"));
          subTextsWrapper.classList.add("visible");
          observer.disconnect();
        }
      });
    },
    { threshold: 0.2 }
  );

  observer.observe(mainTexts[0]);
});

function observeAllTitles() {
  const titles = document.querySelectorAll(".anim-title");

  if (!titles.length) return;

  const titleObserver = new IntersectionObserver(
    (entries, observer) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          entry.target.classList.add("visible");
          observer.unobserve(entry.target);
        }
      });
    },
    { threshold: 0.2 }
  );

  titles.forEach((title) => titleObserver.observe(title));
}

document.addEventListener("DOMContentLoaded", () => {
  observeAllTitles();
});

function observeAllMiniTitles() {
  const titles = document.querySelectorAll(".mini-title");

  if (!titles.length) return;

  const titleObserver = new IntersectionObserver(
    (entries, observer) => {
      entries.forEach((entry) => {
        if (entry.isIntersecting) {
          entry.target.classList.add("visible");
          observer.unobserve(entry.target);
        }
      });
    },
    { threshold: 0.2 }
  );

  titles.forEach((title) => titleObserver.observe(title));
}

document.addEventListener("DOMContentLoaded", () => {
  observeAllMiniTitles();
});

document.addEventListener('DOMContentLoaded', () => {
	const backLinks = document.querySelectorAll('[data-go-back]');
	backLinks.forEach(link => {
		link.addEventListener('click', (e) => {
			e.preventDefault();
			history.back();
		});
	});
	
	console.log(backLinks)
});

document.addEventListener('DOMContentLoaded', function () {

    const FIELD_CONTAINERS = [
        '.footer__input-container',
        '.consultation__input-container',
        '.consultation__double-input',
        '.consultation__select-container',
        '.consultation__textarea-container',
        '.consultation__checkbox-container',
        '.consultation__file-container'
    ];
    const FIELD_CONTAINER_SELECTOR = FIELD_CONTAINERS.join(', ');

    /**
     * Позначити/зняти помилки у конкретній формі CF7.
     * @param {HTMLFormElement} form
     */
    function markFormErrors(form) {
        if (!form) return;

        // Очистити старі стани
        form.querySelectorAll('.has-error').forEach(el => el.classList.remove('has-error'));

        // Знайти всі невалідні поля CF7
        const invalidFields = form.querySelectorAll('.wpcf7-not-valid, [aria-invalid="true"]');

        if (invalidFields.length) {
            invalidFields.forEach(field => {
                // Знайти контейнер для цього поля
                let container = field.closest(FIELD_CONTAINER_SELECTOR);

                // Якщо поле всередині wrap-а, спробувати піднятися вище
                if (!container) {
                    // Часто CF7 обгортає input у span.wpcf7-form-control-wrap → беремо батьківський div
                    const wrap = field.closest('.wpcf7-form-control-wrap');
                    if (wrap) {
                        container = wrap.closest(FIELD_CONTAINER_SELECTOR);
                    }
                }

                // Якщо нічого не знайшли — fallback на найближчий .footer__form або .consultation__form
                if (!container) {
                    container = field.closest('.footer__form, .consultation__form, .consultation__form-container');
                }

                if (container) {
                    container.classList.add('has-error');
                }
            });

            // Якщо є помилки — пофарбувати відповідну кнопку
            const submitBtn = form.querySelector('.footer__submit, .custom-submit, .consultation__submit');
            if (submitBtn) {
                submitBtn.classList.add('has-error');
            }
        } else {
            // Немає помилок — прибрати зі Submit
            const submitBtn = form.querySelector('.footer__submit, .custom-submit, .consultation__submit');
            if (submitBtn) {
                submitBtn.classList.remove('has-error');
            }
        }
    }

    /**
     * Отримати форму з події CF7.
     * Подія йде або з <form.wpcf7-form>, або з wrapper .wpcf7.
     */
    function getFormFromCF7Event(e) {
        // Якщо target вже форма
        if (e.target && e.target.tagName && e.target.tagName.toLowerCase() === 'form') {
            return e.target;
        }
        // Якщо target wrapper .wpcf7
        if (e.target && e.target.classList && e.target.classList.contains('wpcf7')) {
            return e.target.querySelector('form.wpcf7-form');
        }
        // Спробуємо через unitTag (доступно у detail)
        if (e.detail && e.detail.unitTag) {
            const wrapper = document.getElementById(e.detail.unitTag);
            if (wrapper) {
                const f = wrapper.querySelector('form.wpcf7-form');
                if (f) return f;
            }
        }
        return null;
    }

    /**
     * Обробники подій CF7 (всі ключові стани).
     */
    ['wpcf7invalid','wpcf7spam','wpcf7mailfailed','wpcf7mailsent','wpcf7submit'].forEach(evtName => {
        document.addEventListener(evtName, function (e) {
            const form = getFormFromCF7Event(e);
            // Дочекаємось, поки CF7 розставить класи
            requestAnimationFrame(() => markFormErrors(form));
        });
    });

    /**
     * Live-валідація: при вводі/зміні знімаємо помилку з конкретного поля
     * і перевіряємо чи лишилися ще якісь помилки у формі.
     */
    document.addEventListener('input', handleFieldInput, true);
    document.addEventListener('change', handleFieldInput, true);
    document.addEventListener('blur', handleFieldInput, true);

    function handleFieldInput(e) {
        const field = e.target;
        if (!field.classList || !field.classList.contains('wpcf7-form-control')) return;

        const form = field.closest('form.wpcf7-form');
        if (!form) return;

        // Зняти клас невалідного з поля (як UX-підказка; CF7 переоцінить при submit)
        field.classList.remove('wpcf7-not-valid');
        field.removeAttribute('aria-invalid');

        // Зняти помилку з контейнера
        let container = field.closest(FIELD_CONTAINER_SELECTOR);
        if (!container) {
            const wrap = field.closest('.wpcf7-form-control-wrap');
            if (wrap) container = wrap.closest(FIELD_CONTAINER_SELECTOR);
        }
        if (container) {
            container.classList.remove('has-error');
        }

        // Перевірити, чи лишилися інші невалідні поля
        requestAnimationFrame(() => markFormErrors(form));
    }
});


document.addEventListener("DOMContentLoaded", function () {
    const galleryImages = document.querySelectorAll('.project-gallery__body .swiper-slide img');

    galleryImages.forEach((img, index) => {
     

        const link = document.createElement('a');
        link.href = img.src;
        link.setAttribute('data-fancybox', 'project-gallery');

        img.parentNode.insertBefore(link, img);
        link.appendChild(img);
    });
});


const LenisConstructor = window.Lenis?.default || window.Lenis;

        if (typeof LenisConstructor === 'function') {
            const lenis = new LenisConstructor({
                duration: 1.2,
                easing: (t) => Math.min(1, 1.001 - Math.pow(2, -10 * t)),
                smooth: true,
                smoothTouch: false
            });

            function raf(time) {
                lenis.raf(time);
                requestAnimationFrame(raf);
            }

            requestAnimationFrame(raf);

            // Smooth scroll for anchor links
            document.querySelectorAll('a[href^=\"#\"]').forEach(anchor => {
                anchor.addEventListener('click', function (e) {
                    const target = document.querySelector(this.getAttribute('href'));
                    if (target) {
                        e.preventDefault();
                        lenis.scrollTo(target);
                    }
                });
            });
        } else {
            console.error('Lenis is not available');
        }
        


})();