Files
new_raffles/public/raffles/assets/js/style.js
2025-07-27 17:40:56 +05:45

696 lines
19 KiB
JavaScript

document.addEventListener("DOMContentLoaded", function () {
let intouchBtn = document.getElementById("get-in-touch");
let intouchPopup = document.getElementById("get-in-touch-page");
let closeBtns = document.getElementById("close-btn");
// Show login popup
intouchBtn.addEventListener("click", function () {
intouchPopup.classList.add("active");
// alert("clicked ")
});
// 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 30;
return 40;
}
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 = 0.25;
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, `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.querySelector('.next-btn button');
const bananalast = document.getElementById('b5');
const monkeyImages = [
"assets/images/icons/monkey1.png",
"assets/images/icons/monkey2.png",
"assets/images/icons/monkey3.png",
"assets/images/icons/monkey4.png",
"assets/images/icons/monkey5.png",
"assets/images/icons/monkey6.png",
"assets/images/icons/monkey7.png",
];
nextBtn.addEventListener('click', () => {
if (currentStep < totalSteps) {
currentStep++;
// Move monkey
if (window.innerWidth <= 540) {
const percent = ((currentStep -1) / (totalSteps - 0.2)) * 100;
monkeyContainer.style.left = percent + '%';
}
else if (window.innerWidth <= 768) {
const percent = ((currentStep -1) / (totalSteps - 0.3)) * 100;
monkeyContainer.style.left = percent + '%';
}
else if (window.innerWidth <= 992) {
const percent = ((currentStep -1) / (totalSteps - 0.7)) * 100;
monkeyContainer.style.left = percent + '%';
}
else if (window.innerWidth <= 1180) {
const percent = ((currentStep -1) / (totalSteps - 0.2)) * 100;
monkeyContainer.style.left = percent + '%';
}
else{
const percent = ((currentStep -1) / (totalSteps - 0.5)) * 100;
monkeyContainer.style.left = percent + '%';
}
// 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');
}
// At final step (Step 5), hide Next and show Done
if (currentStep === totalSteps) {
nextBtn.style.display = 'none';
doneBtn.style.display = 'block';
}
}w
});
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));
// });