document.addEventListener("DOMContentLoaded", function () { const openButtons = document.querySelectorAll(".open-intouch"); // let intouchBtn = document.getElementById("get-in-touch"); let intouchPopup = document.getElementById("get-in-touch-page"); let closeBtns = document.getElementById("close-btn"); const mobileRedirectURL = "book-counsellor.php"; // Change to your desired mobile page URL openButtons.forEach((button) => { button.addEventListener("click", function () { if (window.innerWidth > 992) { // Desktop and tablets intouchPopup.classList.add("active"); } else { // Mobile – redirect to a page window.location.href = mobileRedirectURL; } }); }); // Hide both popups when clicking any close button closeBtns.addEventListener("click", function () { intouchPopup.classList.remove("active"); }); // Hide popups when clicking outside them window.addEventListener("click", function (event) { if (event.target.classList.contains("get-in-touch-page")) { intouchPopup.classList.remove("active"); } }); }); // university image animation window.addEventListener("DOMContentLoaded", () => { const section = document.getElementById("animated-section"); const leftItems = document.querySelectorAll(".left-group .line-item"); const rightItems = document.querySelectorAll(".right-group .line-item"); const observer = new IntersectionObserver( (entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { leftItems.forEach((item, i) => { setTimeout( () => item.classList.add("visible"), i * 300 ); }); rightItems.forEach((item, i) => { setTimeout( () => item.classList.add("visible"), i * 300 ); }); } else { leftItems.forEach((item) => item.classList.remove("visible") ); rightItems.forEach((item) => item.classList.remove("visible") ); } }); }, { threshold: 0.5 } ); observer.observe(section); }); // tabs in free resources function showTab(id) { // Remove active class from all buttons document .querySelectorAll(".tab-btn") .forEach((btn) => btn.classList.remove("active")); // Hide all tab contents document .querySelectorAll(".tab-content") .forEach((tab) => tab.classList.remove("active")); // Show the selected tab document.getElementById(id).classList.add("active"); } // NEW: Attach click event on all tab buttons document.querySelectorAll(".tab-btn").forEach((button) => { button.addEventListener("click", function () { // Remove active from all document .querySelectorAll(".tab-btn") .forEach((btn) => btn.classList.remove("active")); // Add active to clicked button this.classList.add("active"); }); }); // counter section document.addEventListener("DOMContentLoaded", function () { const counters = document.querySelectorAll(".counter"); const observer = new IntersectionObserver((entries) => { entries.forEach((entry) => { const counter = entry.target; if (entry.isIntersecting) { if (!counter.classList.contains("started")) { startCounting(counter); counter.classList.add("started"); } } else { resetCounter(counter); counter.classList.remove("started"); } }); }); counters.forEach((counter) => { observer.observe(counter); }); function startCounting(counter) { let start = 0; const targetNumber = parseInt(counter.getAttribute("data-target")); const duration = 2000; // 2 seconds const increment = targetNumber / (duration / 16); const timer = setInterval(() => { start += increment; if (start >= targetNumber) { counter.textContent = targetNumber; clearInterval(timer); } else { counter.textContent = Math.floor(start); } }, 16); } function resetCounter(counter) { counter.textContent = 0; } }); // course finder ball bouncing window.addEventListener("DOMContentLoaded", () => { const canvas = document.getElementById("flagCanvas"); const ctx = canvas.getContext("2d"); const ballSection = document.getElementById("ball-section"); // Get responsive ball size function getBallSize() { const width = window.innerWidth; if (width < 480) return 20; if (width < 768) return 25; return 35; } let ballSize = getBallSize(); // Responsive canvas sizing function resizeCanvas() { canvas.width = ballSection.clientWidth; canvas.height = ballSection.clientHeight; ballSize = getBallSize(); } resizeCanvas(); window.addEventListener("resize", resizeCanvas); const gravity = 1; const friction = 0.8; const elasticity = 0.75; const flags = ["us", "gb", "np", "dk", "ca", "au"]; let balls = []; class Ball { constructor(x, y, radius, imageSrc) { this.x = x; this.y = y; this.radius = radius; this.dx = (Math.random() - 0.5) * 2; this.dy = 0; this.image = new Image(); this.image.src = imageSrc; this.dragging = false; this.offsetX = 0; this.offsetY = 0; this.elasticity = elasticity; this.hasSettled = false; } draw() { ctx.save(); ctx.beginPath(); ctx.arc(this.x, this.y, this.radius, 0, Math.PI * 2); ctx.closePath(); ctx.clip(); const img = this.image; const size = Math.min(img.width, img.height); const sx = (img.width - size) / 2; const sy = (img.height - size) / 2; ctx.drawImage( img, sx, sy, size, size, this.x - this.radius, this.y - this.radius, this.radius * 2, this.radius * 2 ); ctx.restore(); } update(others) { if (!this.dragging) { this.dy += gravity; this.x += this.dx; this.y += this.dy; // Floor if (this.y + this.radius > canvas.height) { this.y = canvas.height - this.radius; this.dy *= -this.elasticity; this.dx *= friction; if (Math.abs(this.dy) < 0.5) { this.dy = 0; this.hasSettled = true; } } // Walls if (this.x - this.radius < 0) { this.x = this.radius; this.dx *= -friction; } else if (this.x + this.radius > canvas.width) { this.x = canvas.width - this.radius; this.dx *= -friction; } } // Collisions if (this.dragging || !this.hasSettled) { for (let other of others) { if (other !== this) { this.resolveBallCollision(other); } } } this.draw(); } resolveBallCollision(other) { const dx = other.x - this.x; const dy = other.y - this.y; const dist = Math.sqrt(dx * dx + dy * dy); const minDist = this.radius + other.radius; if (dist < minDist) { const nx = dx / dist; const ny = dy / dist; const overlap = minDist - dist; const impulse = 0.5; this.x -= nx * overlap * impulse; this.y -= ny * overlap * impulse; other.x += nx * overlap * impulse; other.y += ny * overlap * impulse; const tx = -ny; const ty = nx; const dpTan1 = this.dx * tx + this.dy * ty; const dpTan2 = other.dx * tx + other.dy * ty; const dpNorm1 = this.dx * nx + this.dy * ny; const dpNorm2 = other.dx * nx + other.dy * ny; this.dx = tx * dpTan1 + nx * dpNorm2; this.dy = ty * dpTan1 + ny * dpNorm2; other.dx = tx * dpTan2 + nx * dpNorm1; other.dy = ty * dpTan2 + ny * dpNorm1; } } } function createBalls() { balls = []; for (let i = 0; i < 30; i++) { const flag = flags[i % flags.length]; const x = Math.random() * (canvas.width - ballSize * 2) + ballSize; const y = -Math.random() * 300; balls.push( new Ball( x, y, ballSize, `raffles/assets/images/logo/country/${flag}.png` ) ); } } createBalls(); let draggedBall = null; let lastMouse = { x: 0, y: 0 }; canvas.addEventListener("pointerdown", (e) => { const rect = canvas.getBoundingClientRect(); const scaleX = canvas.width / rect.width; const scaleY = canvas.height / rect.height; const mouseX = (e.clientX - rect.left) * scaleX; const mouseY = (e.clientY - rect.top) * scaleY; for (let ball of balls) { const dx = mouseX - ball.x; const dy = mouseY - ball.y; if (Math.sqrt(dx * dx + dy * dy) < ball.radius) { ball.dragging = true; draggedBall = ball; ball.offsetX = dx; ball.offsetY = dy; ball.hasSettled = false; lastMouse = { x: mouseX, y: mouseY }; break; } } }); canvas.addEventListener("pointermove", (e) => { if (draggedBall) { const rect = canvas.getBoundingClientRect(); const scaleX = canvas.width / rect.width; const scaleY = canvas.height / rect.height; const mouseX = (e.clientX - rect.left) * scaleX; const mouseY = (e.clientY - rect.top) * scaleY; draggedBall.x = mouseX - draggedBall.offsetX; draggedBall.y = mouseY - draggedBall.offsetY; draggedBall.dx = (mouseX - lastMouse.x) * 0.4; draggedBall.dy = (mouseY - lastMouse.y) * 0.4; lastMouse = { x: mouseX, y: mouseY }; } }); window.addEventListener("pointerup", () => { if (draggedBall) { draggedBall.dragging = false; draggedBall = null; } }); // Animation loop let animationId = null; let isAnimating = false; function animate() { ctx.clearRect(0, 0, canvas.width, canvas.height); balls.forEach((ball) => ball.update(balls)); animationId = requestAnimationFrame(animate); } // Intersection Observer const observer = new IntersectionObserver( (entries) => { entries.forEach((entry) => { if (entry.isIntersecting) { if (!isAnimating) { createBalls(); isAnimating = true; animate(); } } else { if (isAnimating) { cancelAnimationFrame(animationId); isAnimating = false; } } }); }, { threshold: 0.1 } ); observer.observe(ballSection); }); // scroll detect in slider // JS script // JS for updating label on scroll window.addEventListener("load", () => { console.log("Window loaded. Running scroll indicator script."); const scrollLabel = document.getElementById("scroll-indicator-label"); console.log("Scroll Label Element:", scrollLabel); const sections = document.querySelectorAll(".scroll-section"); console.log("Found Sections:", sections); if (!scrollLabel || sections.length === 0) { console.error( "Could not find scroll label or sections to observe. Exiting." ); return; } const observer = new IntersectionObserver( (entries) => { console.log("IntersectionObserver callback fired:", entries); entries.forEach((entry) => { console.log( "Observing entry:", entry.target, "Is intersecting:", entry.isIntersecting ); if (entry.isIntersecting) { // --- CHANGE IS HERE --- const sectionId = entry.target.id; // Get the ID of the intersecting section // --- END OF CHANGE --- console.log("Intersecting section ID:", sectionId); if (sectionId) { // Check if ID exists // Optional: Format the ID if needed (example: replace hyphens, capitalize) // let displayText = sectionId.replace(/-/g, ' ').replace(/\b\w/g, l => l.toUpperCase()); // scrollLabel.textContent = displayText; // Simple version: Use the ID directly scrollLabel.textContent = sectionId; console.log("Updated scroll label text to:", sectionId); } else { console.warn( "Intersecting section is missing an ID attribute:", entry.target ); } } }); }, { threshold: 0.5, // Trigger when 50% of the section is visible // Consider adjusting rootMargin if you have sticky headers/footers // rootMargin: "-50px 0px -50px 0px" // Example: ignore top/bottom 50px } ); sections.forEach((section) => { if (!section.id) { console.warn( "Section is missing an ID, it won't update the label:", section ); } console.log("Observing section:", section); observer.observe(section); }); console.log("Intersection observer setup complete."); }); // Optional: Add a check outside the load event to see if the script file itself is loaded console.log("Scroll indicator script file loaded."); // aeroplane flying const plane = document.getElementById("plane"); let planeX = 100; let planeYBase = 200; // starting height let vx; if (window.innerWidth < 600) { // mobile vx = 1; } else if (window.innerWidth < 1200) { // tablet vx = 2; } else { // desktop vx = 3; } // horizontal speed let direction = 1; // 1 = right, -1 = left // const amplitude = 150; let amplitude; if (window.innerWidth < 768) { // mobile amplitude = 90; } else { // desktop amplitude = 150; } // const numWaves = 2; let numWaves; if (window.innerWidth < 768) { // mobile numWaves = 1; } else { // desktop numWaves = 3; } let dodgeOffset = 0; const dodgeDecay = 0.9; let downwardMovement = 0; // current Y offset let targetDownwardMovement = 0; // target Y offset let downwardStep = 200; // increase per edge hit let goingDown = true; function updatePosition() { const w = window.innerWidth; const h = document.body.scrollHeight; const maxPlaneY = h - 200; // bounce left/right if (planeX <= 0 || planeX >= w - plane.width) { vx *= -1; direction *= -1; plane.style.transform = `scaleX(${direction > 0 ? 1 : -1})`; if (goingDown) { targetDownwardMovement += downwardStep; if (planeYBase + targetDownwardMovement >= maxPlaneY) { targetDownwardMovement = maxPlaneY - planeYBase; goingDown = false; } } else { targetDownwardMovement -= downwardStep; if (targetDownwardMovement <= 0) { targetDownwardMovement = 0; goingDown = true; } } } planeX += vx; // Smoothly move downwardMovement towards targetDownwardMovement downwardMovement += (targetDownwardMovement - downwardMovement) * 0.05; // progress across screen let progress = planeX / (w - plane.width); if (direction < 0) { progress = 1 - progress; } const angle = progress * numWaves * 2 * Math.PI; const waveY = Math.sin(angle) * amplitude; const finalY = planeYBase + downwardMovement + waveY + dodgeOffset; plane.style.left = planeX + "px"; plane.style.top = finalY + "px"; dodgeOffset *= dodgeDecay; requestAnimationFrame(updatePosition); } document.addEventListener("mousemove", function (e) { const viewportOffset = plane.getBoundingClientRect(); const planeCenterX = viewportOffset.left + plane.width / 2; const planeCenterY = viewportOffset.top + plane.height / 2; const dx = e.clientX - planeCenterX; const dy = e.clientY - planeCenterY; const dist = Math.sqrt(dx * dx + dy * dy); if (dist < 100) { dodgeOffset -= (dy / dist) * 10; } }); updatePosition(); // gallery image const images = Array.from(document.querySelectorAll(".gallery img")); const lightbox = document.getElementById("lightbox"); const lightboxImg = document.getElementById("lightbox-img"); let currentIndex = 0; images.forEach((img, index) => { img.addEventListener("click", () => { currentIndex = index; showImage(); }); }); function showImage() { lightboxImg.src = images[currentIndex].src; lightbox.classList.add("active"); } function closeLightbox() { lightbox.classList.remove("active"); } function changeSlide(step) { currentIndex = (currentIndex + step + images.length) % images.length; showImage(); } document.addEventListener("keydown", (e) => { if (!lightbox.classList.contains("active")) return; if (e.key === "ArrowRight") changeSlide(1); if (e.key === "ArrowLeft") changeSlide(-1); if (e.key === "Escape") closeLightbox(); }); // cost calculator progress let currentStep = 1; const totalSteps = 5; const monkey = document.getElementById("monkey").querySelector("img"); const monkeyContainer = document.getElementById("monkey"); const nextBtn = document.getElementById("nextBtn"); const prevBtn = document.getElementById("prevBtn"); const doneBtn = document.getElementById("doneBtn"); const monkeyImages = [ "raffles/assets/images/icons/monkey2.png", "raffles/assets/images/icons/monkey2.png", "raffles/assets/images/icons/monkey3.png", "raffles/assets/images/icons/monkey4.png", "raffles/assets/images/icons/monkey5.png", "raffles/assets/images/icons/monkey6.png", "raffles/assets/images/icons/monkey7.png", ]; // Function to update monkey position based on screen size function updateMonkeyPosition() { let percent; if (window.innerWidth <= 540) { percent = ((currentStep - 1) / (totalSteps - 0.2)) * 100; } else if (window.innerWidth <= 768) { percent = ((currentStep - 1) / (totalSteps - 0.3)) * 100; } else if (window.innerWidth <= 992) { percent = ((currentStep - 1) / (totalSteps - 0.7)) * 100; } else if (window.innerWidth <= 1180) { percent = ((currentStep - 1) / (totalSteps - 0.2)) * 100; } else { percent = ((currentStep - 1) / (totalSteps - 0.5)) * 100; } monkeyContainer.style.left = percent + "%"; } // Function to update button visibility function updateButtonVisibility() { if (currentStep === 1) { prevBtn.style.display = "none"; // Hide Previous on first step } else { prevBtn.style.display = "flex"; // Show Previous on other steps } if (currentStep === totalSteps) { nextBtn.style.display = "none"; doneBtn.style.display = "block"; } else { nextBtn.style.display = "flex"; doneBtn.style.display = "none"; } } // Next button click event nextBtn.addEventListener("click", () => { if (currentStep < totalSteps) { currentStep++; // Update monkey position updateMonkeyPosition(); // Change monkey image monkey.src = monkeyImages[currentStep - 1]; // Update step content const currentContent = document.getElementById("step" + (currentStep - 1)); const nextContent = document.getElementById("step" + currentStep); if (currentContent && nextContent) { currentContent.classList.remove("active"); nextContent.classList.add("active"); } // Update button visibility updateButtonVisibility(); } }); // Previous button click event prevBtn.addEventListener("click", () => { if (currentStep > 1) { // Update step content first const currentContent = document.getElementById("step" + currentStep); const prevContent = document.getElementById("step" + (currentStep - 1)); if (currentContent && prevContent) { currentContent.classList.remove("active"); prevContent.classList.add("active"); } currentStep--; // Update monkey position updateMonkeyPosition(); // Change monkey image (go back to previous image) monkey.src = monkeyImages[currentStep - 1]; // Update button visibility updateButtonVisibility(); } }); // Initialize button visibility on page load updateButtonVisibility(); // Update on window resize window.addEventListener("resize", updateMonkeyPosition); doneBtn.addEventListener("click", () => { bananalast.classList.add("active"); if (window.innerWidth <= 992) { // On mobile: show 7th image and move down monkey.src = monkeyImages[6]; // 7th image (index 6) monkeyContainer.style.top = "142%"; monkeyContainer.style.left = "40%"; // Optional: keep it centered or adjust as needed } else { // On desktop: show 6th image and move right monkey.src = monkeyImages[5]; // 6th image (index 5) monkeyContainer.style.left = "110%"; monkeyContainer.style.top = "-120%"; // Reset top if changed previously } }); // Final monkey image // document.addEventListener("DOMContentLoaded", function () { // const animatedSections = document.querySelectorAll('[data-custom-animations="true"]'); // const observer = new IntersectionObserver(entries => { // entries.forEach(entry => { // const el = entry.target; // if (entry.isIntersecting) { // el.classList.add("lqd-animations-done"); // Add class when in view // console.log('added') // } else { // el.classList.remove("lqd-animations-done"); // Remove class when out of view // console.log('removed') // } // }); // }, { // threshold: 0.1 // You can adjust this if needed // }); // animatedSections.forEach(section => observer.observe(section)); // }); // free resources