Skip to content
Trang chủ
Về chúng tôi
Dịch Vụ
The Infiniti Riviera Point Q.7
Thiết Kế Thi Công Nội Thất Trọn Gói
DV – Tư Vấn, Thiết Kế 3D
DV – Thi Công, Hoàn Thiện Trang Trí Nội Thất
Trang Trí Cảnh Quan Và Setup Cây Xanh
Đồ Nội Thất Rời Luxury
Dự án
Tuyển dụng
Kinh nghiệm
Liên hệ
Tuyển dụng
Décor – Tuyển dụng nhân sự nội thất
Tuyển dụng nhân sự | Nội thất Tuyển dụng nhân viên giám sát Nội thất,...
Trang chủ
Về chúng tôi
Dịch Vụ
The Infiniti Riviera Point Q.7
Thiết Kế Thi Công Nội Thất Trọn Gói
DV – Tư Vấn, Thiết Kế 3D
DV – Thi Công, Hoàn Thiện Trang Trí Nội Thất
Trang Trí Cảnh Quan Và Setup Cây Xanh
Đồ Nội Thất Rời Luxury
Dự án
Tuyển dụng
Kinh nghiệm
Liên hệ
x
x
(function () { function initDecorFloatingToc() { const holder = document.getElementById("decorFloatingToc"); const panel = document.getElementById("decorFloatingTocPanel"); const inner = document.getElementById("decorFloatingTocInner"); const fill = document.getElementById("decorFloatingTocFill"); const thumb = document.getElementById("decorFloatingTocThumb"); const article = document.getElementById("decorArticleMain"); const links = Array.from(document.querySelectorAll(".decor-floating-toc__item")); if (!holder || !panel || !inner || !fill || !thumb || !article || !links.length) return; const items = links.map(link => { const href = link.getAttribute("href"); const target = href ? document.querySelector(href) : null; return { link, target }; }).filter(item => item.target); if (!items.length) return; function syncHolderHeight() { if (window.innerWidth <= 991) { holder.style.minHeight = "0px"; return; } holder.style.minHeight = Math.max(article.offsetHeight, panel.offsetHeight) + "px"; } function moveIndicator(link) { const innerRect = inner.getBoundingClientRect(); const linkRect = link.getBoundingClientRect(); const center = (linkRect.top - innerRect.top) + (linkRect.height / 2); thumb.style.top = center + "px"; fill.style.height = center + "px"; } function setActive(item) { links.forEach(link => link.classList.remove("active")); item.link.classList.add("active"); moveIndicator(item.link); } function getCurrentItem() { const triggerY = window.innerHeight * 0.42; let current = items[0]; for (const item of items) { const rect = item.target.getBoundingClientRect(); if (rect.top <= triggerY) { current = item; } else { break; } } return current; } function updateFloatingPosition() { if (window.innerWidth <= 991) { panel.style.position = "relative"; panel.style.top = "auto"; panel.style.left = "auto"; panel.style.width = "100%"; return; } const holderRect = holder.getBoundingClientRect(); const holderTopDoc = window.scrollY + holderRect.top; const holderBottomDoc = holderTopDoc + holder.offsetHeight; const panelHeight = panel.offsetHeight; const viewportPadding = 28; const preferredTop = (window.innerHeight - panelHeight) / 2; const fixedTop = Math.max( viewportPadding, Math.min(preferredTop, window.innerHeight - panelHeight - viewportPadding) ); const desiredTopDoc = window.scrollY + fixedTop; const maxTopDoc = holderBottomDoc - panelHeight; if (desiredTopDoc <= holderTopDoc) { panel.style.position = "absolute"; panel.style.top = "0px"; panel.style.left = "0px"; panel.style.width = "100%"; } else if (desiredTopDoc >= maxTopDoc) { panel.style.position = "absolute"; panel.style.top = Math.max(0, holder.offsetHeight - panelHeight) + "px"; panel.style.left = "0px"; panel.style.width = "100%"; } else { panel.style.position = "fixed"; panel.style.top = fixedTop + "px"; panel.style.left = holderRect.left + "px"; panel.style.width = holderRect.width + "px"; } } let ticking = false; function updateAll() { syncHolderHeight(); updateFloatingPosition(); setActive(getCurrentItem()); ticking = false; } function requestUpdate() { if (!ticking) { window.requestAnimationFrame(updateAll); ticking = true; } } if (!holder.dataset.decorInit) { window.addEventListener("scroll", requestUpdate, { passive: true }); window.addEventListener("resize", requestUpdate); window.addEventListener("load", requestUpdate); links.forEach(link => { link.addEventListener("click", function () { setTimeout(requestUpdate, 180); }); }); if (document.fonts && document.fonts.ready) { document.fonts.ready.then(requestUpdate); } holder.dataset.decorInit = "true"; } requestUpdate(); } document.addEventListener("DOMContentLoaded", initDecorFloatingToc); document.body.addEventListener("experimental-flatsome-pjax-request-done", initDecorFloatingToc); })();