Files
2025-08-20 16:42:17 +05:45

772 lines
24 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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