|
const getLocalUser = localStorage.getItem("username");
|
|
if (getLocalUser) {
|
|
document.getElementById("userProfile").innerHTML = `${getLocalUser}`;
|
|
} else {
|
|
document.getElementById("userProfile").innerHTML = "Hei";
|
|
}
|
|
|
|
function populateYearDropdown(startYear, endYear) {
|
|
const dropdown = document.getElementById('year-filter');
|
|
|
|
|
|
while (dropdown.options.length > 1) {
|
|
dropdown.remove(1);
|
|
}
|
|
|
|
|
|
for (let year = endYear; year >= startYear; year--) {
|
|
const option = document.createElement('option');
|
|
option.value = year;
|
|
option.textContent = year;
|
|
dropdown.appendChild(option);
|
|
}
|
|
}
|
|
|
|
|
|
populateYearDropdown(1900, 2025);
|
|
|
|
const profileContainer = document.getElementById("profileContainer");
|
|
const signInBtn = document.getElementById("signInBtn");
|
|
const storedUsername = localStorage.getItem("username");
|
|
const storedUserId = localStorage.getItem("userId")
|
|
|
|
if (storedUsername) {
|
|
profileContainer.style.display = "flex";
|
|
signInBtn.style.display = "none";
|
|
} else {
|
|
profileContainer.style.display = "none";
|
|
signInBtn.style.display = "block";
|
|
}
|
|
|
|
|
|
const userProfile = document.getElementById("userProfile");
|
|
const profileDropdown = document.getElementById("profileDropdown");
|
|
const profileOverlay = document.getElementById("profileOverlay");
|
|
const logoutBtn = document.getElementById("logoutBtn");
|
|
|
|
|
|
userProfile.addEventListener("click", () => {
|
|
profileDropdown.classList.add("active");
|
|
profileOverlay.classList.add("active");
|
|
});
|
|
|
|
|
|
profileOverlay.addEventListener("click", () => {
|
|
profileDropdown.classList.remove("active");
|
|
profileOverlay.classList.remove("active");
|
|
});
|
|
|
|
async function saveSearchToFirebase(query, year, feature) {
|
|
const auth = firebase.auth();
|
|
const db = firebase.firestore();
|
|
const user = auth.currentUser;
|
|
if (!user) {
|
|
console.log("User not logged in, cannot save search history");
|
|
return;
|
|
}
|
|
|
|
try {
|
|
|
|
const searchData = {
|
|
type: "search",
|
|
query: query,
|
|
year: year || "All Years",
|
|
feature: feature,
|
|
timestamp: firebase.firestore.FieldValue.serverTimestamp()
|
|
};
|
|
|
|
|
|
await db.collection("users")
|
|
.doc(user.uid)
|
|
.collection("activities")
|
|
.add(searchData);
|
|
|
|
console.log("Search activity saved successfully");
|
|
} catch (error) {
|
|
console.error("Error saving search activity:", error);
|
|
}
|
|
}
|
|
|
|
|
|
document.addEventListener("DOMContentLoaded", async () => {
|
|
|
|
const profileName = document.getElementById("profileName");
|
|
const profileEmail = document.getElementById("profileEmail");
|
|
const profilePhone = document.getElementById("profilePhone");
|
|
const profileAddress = document.getElementById("profileAddress");
|
|
const profileProfession = document.getElementById("profileProfession");
|
|
const profileHeaderName = document.getElementById("profileHeaderName");
|
|
|
|
|
|
const auth = firebase.auth();
|
|
const db = firebase.firestore();
|
|
|
|
auth.onAuthStateChanged(async (user) => {
|
|
if (user) {
|
|
const userId = user.uid;
|
|
|
|
|
|
profileName.value = localStorage.getItem("username") || "";
|
|
profilePhone.value = localStorage.getItem("phone") || "";
|
|
profileAddress.value = localStorage.getItem("address") || "";
|
|
profileProfession.value = localStorage.getItem("profession") || "";
|
|
profileHeaderName.innerHTML = `Welcome, ${storedUsername}`;
|
|
|
|
|
|
|
|
try {
|
|
|
|
const userDoc = await db.collection("users").doc(userId).get();
|
|
if (userDoc.exists) {
|
|
const userData = userDoc.data();
|
|
if (!profileName.value) profileName.value = userData.name || "";
|
|
if (!profilePhone.value) profilePhone.value = userData.phone || "";
|
|
if (!profileAddress.value) profileAddress.value = userData.address || "";
|
|
if (!profileProfession.value) profileProfession.value = userData.profession || "";
|
|
}
|
|
} catch (error) {
|
|
console.error("Error fetching user data:", error);
|
|
}
|
|
}
|
|
});
|
|
|
|
|
|
window.enableEdit = (fieldId) => {
|
|
const inputField = document.getElementById(fieldId);
|
|
inputField.removeAttribute("disabled");
|
|
inputField.focus();
|
|
inputField.addEventListener("blur", () => {
|
|
|
|
inputField.setAttribute("disabled", true);
|
|
});
|
|
};
|
|
|
|
|
|
const tabButtons = document.querySelectorAll(".tab-btn");
|
|
const tabContents = document.querySelectorAll(".tab-content");
|
|
|
|
tabButtons.forEach((btn) => {
|
|
btn.addEventListener("click", () => {
|
|
const tab = btn.getAttribute("data-tab");
|
|
tabButtons.forEach((b) => b.classList.remove("active"));
|
|
tabContents.forEach((c) => c.classList.remove("active"));
|
|
btn.classList.add("active");
|
|
document.getElementById(`${tab}-tab`).classList.add("active");
|
|
});
|
|
});
|
|
|
|
|
|
const avatarUpload = document.getElementById("avatarUpload");
|
|
const profileAvatar = document.getElementById("profileAvatar");
|
|
|
|
if (avatarUpload) {
|
|
avatarUpload.addEventListener("change", (e) => {
|
|
const file = e.target.files[0];
|
|
if (file) {
|
|
const reader = new FileReader();
|
|
reader.onload = (event) => {
|
|
profileAvatar.src = event.target.result;
|
|
|
|
};
|
|
reader.readAsDataURL(file);
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
const saveBtn = document.getElementById("saveBtn");
|
|
saveBtn.addEventListener("click", async () => {
|
|
const user = auth.currentUser;
|
|
if (!user) {
|
|
alert("No user logged in!");
|
|
return;
|
|
}
|
|
const userId = user.uid;
|
|
|
|
|
|
const updatedName = profileName.value.trim();
|
|
const updatedPhone = profilePhone.value.trim();
|
|
const updatedAddress = profileAddress.value.trim();
|
|
const updatedProfession = profileProfession.value.trim();
|
|
|
|
|
|
localStorage.setItem("username", updatedName);
|
|
localStorage.setItem("phone", updatedPhone);
|
|
localStorage.setItem("address", updatedAddress);
|
|
localStorage.setItem("profession", updatedProfession);
|
|
|
|
|
|
try {
|
|
await db.collection("users").doc(userId).set(
|
|
{
|
|
name: updatedName,
|
|
phone: updatedPhone,
|
|
address: updatedAddress,
|
|
profession: updatedProfession,
|
|
|
|
},
|
|
{ merge: true }
|
|
);
|
|
userProfile.textContent = updatedName;
|
|
showPaperAlert(
|
|
"Successfully Updated!",
|
|
"Profile Updation Status",
|
|
"fa-exclamation-circle",
|
|
4000
|
|
);
|
|
} catch (error) {
|
|
console.error("Error updating profile:", error);
|
|
showPaperAlert(
|
|
"Error in Updation",
|
|
"Profile Updation Status",
|
|
"fa-exclamation-circle",
|
|
4000
|
|
);
|
|
}
|
|
});
|
|
|
|
|
|
logoutBtn.addEventListener("click", async () => {
|
|
try {
|
|
await auth.signOut();
|
|
localStorage.clear();
|
|
window.location.href = "/home";
|
|
} catch (error) {
|
|
console.error("Logout error:", error);
|
|
}
|
|
});
|
|
});
|
|
|
|
class Paper {
|
|
constructor(x, y) {
|
|
this.x = x;
|
|
this.y = y;
|
|
this.size = Math.random() * 15 + 5;
|
|
this.rotation = Math.random() * 360;
|
|
this.speedX = Math.random() * 3 - 1.5;
|
|
this.speedY = Math.random() * 3 - 1.5;
|
|
this.rotationSpeed = Math.random() * 2 - 1;
|
|
this.opacity = 1;
|
|
this.life = 100;
|
|
this.element = document.createElement('div');
|
|
this.element.className = 'paper';
|
|
this.element.style.width = `${this.size}px`;
|
|
this.element.style.height = `${this.size}px`;
|
|
this.element.style.left = `${this.x}px`;
|
|
this.element.style.top = `${this.y}px`;
|
|
this.element.style.transform = `rotate(${this.rotation}deg)`;
|
|
this.element.style.opacity = this.opacity;
|
|
document.body.appendChild(this.element);
|
|
}
|
|
|
|
update() {
|
|
this.life--;
|
|
this.x += this.speedX;
|
|
this.y += this.speedY;
|
|
this.rotation += this.rotationSpeed;
|
|
this.opacity = this.life / 100;
|
|
|
|
this.element.style.left = `${this.x}px`;
|
|
this.element.style.top = `${this.y}px`;
|
|
this.element.style.transform = `rotate(${this.rotation}deg)`;
|
|
this.element.style.opacity = this.opacity;
|
|
|
|
if (this.life <= 0) {
|
|
this.element.remove();
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
}
|
|
|
|
|
|
let papers = [];
|
|
let frameCount = 0;
|
|
|
|
document.addEventListener('mousemove', (e) => {
|
|
if (frameCount % 2 === 0) {
|
|
papers.push(new Paper(e.clientX, e.clientY));
|
|
}
|
|
});
|
|
|
|
function animate() {
|
|
frameCount++;
|
|
papers = papers.filter(paper => paper.update());
|
|
requestAnimationFrame(animate);
|
|
}
|
|
|
|
animate();
|
|
|
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
|
|
const container = document.getElementById('beam-container');
|
|
const circle1 = document.getElementById('circle1');
|
|
const circle2 = document.getElementById('circle2');
|
|
const circle3 = document.getElementById('circle3');
|
|
const circle4 = document.getElementById('circle4');
|
|
const circle5 = document.getElementById('circle5');
|
|
const circle6 = document.getElementById('circle6');
|
|
const circle7 = document.getElementById('circle7');
|
|
|
|
|
|
const svgContainer = document.getElementById('beams-svg');
|
|
|
|
|
|
createBeam(circle1, circle6);
|
|
createBeam(circle2, circle6);
|
|
createBeam(circle3, circle6);
|
|
createBeam(circle4, circle6);
|
|
createBeam(circle5, circle6);
|
|
createBeam(circle6, circle7);
|
|
|
|
|
|
window.addEventListener('resize', () => {
|
|
|
|
svgContainer.innerHTML = '';
|
|
|
|
|
|
createBeam(circle1, circle6);
|
|
createBeam(circle2, circle6);
|
|
createBeam(circle3, circle6);
|
|
createBeam(circle4, circle6);
|
|
createBeam(circle5, circle6);
|
|
createBeam(circle6, circle7);
|
|
});
|
|
|
|
|
|
function createBeam(fromElement, toElement) {
|
|
|
|
const fromRect = fromElement.getBoundingClientRect();
|
|
const toRect = toElement.getBoundingClientRect();
|
|
const containerRect = container.getBoundingClientRect();
|
|
|
|
|
|
const fromX = fromRect.left + fromRect.width / 2 - containerRect.left;
|
|
const fromY = fromRect.top + fromRect.height / 2 - containerRect.top;
|
|
const toX = toRect.left + toRect.width / 2 - containerRect.left;
|
|
const toY = toRect.top + toRect.height / 2 - containerRect.top;
|
|
|
|
|
|
const beam = document.createElementNS('http://www.w3.org/2000/svg', 'line');
|
|
beam.setAttribute('x1', fromX);
|
|
beam.setAttribute('y1', fromY);
|
|
beam.setAttribute('x2', toX);
|
|
beam.setAttribute('y2', toY);
|
|
beam.classList.add('beam');
|
|
svgContainer.appendChild(beam);
|
|
|
|
|
|
const beamGlow = document.createElementNS('http://www.w3.org/2000/svg', 'line');
|
|
beamGlow.setAttribute('x1', fromX);
|
|
beamGlow.setAttribute('y1', fromY);
|
|
beamGlow.setAttribute('x2', toX);
|
|
beamGlow.setAttribute('y2', toY);
|
|
beamGlow.classList.add('beam-glow');
|
|
svgContainer.appendChild(beamGlow);
|
|
}
|
|
});
|
|
|
|
|
|
const inputFiles = [
|
|
{ y: 120, ext: 'ieee' },
|
|
{ y: 160, ext: 'arxiv' },
|
|
{ y: 200, ext: 'PMC' },
|
|
{ y: 240, ext: 'jstor' },
|
|
{ y: 280, ext: 'plos' }
|
|
];
|
|
|
|
const outputFiles = [
|
|
{ label: 'Trend Analysis', y: 100, logoSrc: '/assets/c1.png' },
|
|
{ label: 'Citation Network', y: 180, logoSrc: '/assets/c2.png' },
|
|
{ label: 'Venue & Publisher', y: 260, logoSrc: '/assets/c3.png' },
|
|
];
|
|
|
|
const svgContainer = document.querySelector('.paths-container');
|
|
const centerBox = document.querySelector('.center-box');
|
|
|
|
|
|
let isAnimating = false;
|
|
|
|
function createInputPath(startY) {
|
|
const startX = 100;
|
|
const endX = 400;
|
|
const endY = 200;
|
|
const controlX = (startX + endX) / 2;
|
|
return `M ${startX} ${startY} C ${controlX} ${startY}, ${controlX} ${endY}, ${endX} ${endY}`;
|
|
}
|
|
|
|
function createOutputPath(endY) {
|
|
const startX = 400;
|
|
const startY = 200;
|
|
const endX = 680;
|
|
const controlX = (startX + endX) / 2;
|
|
return `M ${startX} ${startY} C ${controlX} ${startY}, ${controlX} ${endY}, ${endX} ${endY}`;
|
|
}
|
|
|
|
function createInputPaper(data) {
|
|
const container = document.createElement('div');
|
|
container.className = 'paper-container';
|
|
|
|
const paperIcon = document.createElement('div');
|
|
paperIcon.className = 'paper-icon';
|
|
paperIcon.textContent = data.ext;
|
|
|
|
const label = document.createElement('span');
|
|
label.textContent = data.label || data.ext;
|
|
|
|
const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
|
path.setAttribute('class', 'path');
|
|
path.setAttribute('d', createInputPath(data.y));
|
|
svgContainer.appendChild(path);
|
|
|
|
container.appendChild(paperIcon);
|
|
container.appendChild(label);
|
|
document.querySelector('.container').appendChild(container);
|
|
|
|
container.style.left = '70px';
|
|
container.style.top = `${data.y}px`;
|
|
|
|
return { container, paperIcon, path, ext: data.ext };
|
|
}
|
|
|
|
function createOutputBox(data) {
|
|
const path = document.createElementNS('http://www.w3.org/2000/svg', 'path');
|
|
path.setAttribute('class', 'path');
|
|
path.setAttribute('d', createOutputPath(data.y));
|
|
svgContainer.appendChild(path);
|
|
|
|
|
|
const outputBox = document.createElement('div');
|
|
outputBox.className = 'output-box';
|
|
document.querySelector('.container').appendChild(outputBox);
|
|
outputBox.style.top = `${data.y}px`;
|
|
|
|
|
|
const logo = document.createElement('img');
|
|
logo.className = 'output-logo';
|
|
logo.src = data.logoSrc;
|
|
logo.alt = data.label + ' logo';
|
|
outputBox.appendChild(logo);
|
|
|
|
|
|
const title = document.createElement('div');
|
|
title.className = 'box-title';
|
|
title.textContent = data.label;
|
|
outputBox.appendChild(title);
|
|
|
|
return { path, outputBox };
|
|
}
|
|
|
|
function animatePaperAlongPath(path, ext, onComplete) {
|
|
const movingPaper = document.createElement('div');
|
|
movingPaper.className = 'moving-paper';
|
|
movingPaper.textContent = ext;
|
|
document.querySelector('.container').appendChild(movingPaper);
|
|
|
|
const length = path.getTotalLength();
|
|
let start = null;
|
|
const duration = 1200;
|
|
|
|
path.style.strokeOpacity = "1";
|
|
path.style.strokeDasharray = `${length}, ${length}`;
|
|
path.style.strokeDashoffset = length;
|
|
|
|
function animate(timestamp) {
|
|
if (!start) start = timestamp;
|
|
const progress = (timestamp - start) / duration;
|
|
|
|
if (progress <= 1) {
|
|
const point = path.getPointAtLength(length * progress);
|
|
movingPaper.style.left = `${point.x}px`;
|
|
movingPaper.style.top = `${point.y}px`;
|
|
|
|
|
|
path.style.strokeDashoffset = length * (1 - progress);
|
|
|
|
requestAnimationFrame(animate);
|
|
} else {
|
|
movingPaper.remove();
|
|
path.style.strokeOpacity = "0";
|
|
if (onComplete) onComplete();
|
|
}
|
|
}
|
|
|
|
requestAnimationFrame(animate);
|
|
}
|
|
|
|
|
|
function animateDotAlongPath(path, outputBox, onComplete) {
|
|
const movingDot = document.createElement('div');
|
|
movingDot.className = 'moving-dot';
|
|
document.querySelector('.container').appendChild(movingDot);
|
|
|
|
const length = path.getTotalLength();
|
|
let start = null;
|
|
const duration = 1000;
|
|
|
|
path.style.strokeOpacity = "1";
|
|
path.style.strokeDasharray = `${length}, ${length}`;
|
|
path.style.strokeDashoffset = length;
|
|
|
|
function animate(timestamp) {
|
|
if (!start) start = timestamp;
|
|
const progress = (timestamp - start) / duration;
|
|
|
|
if (progress <= 1) {
|
|
const point = path.getPointAtLength(length * progress);
|
|
movingDot.style.left = `${point.x}px`;
|
|
movingDot.style.top = `${point.y}px`;
|
|
|
|
|
|
path.style.strokeDashoffset = length * (1 - progress);
|
|
|
|
requestAnimationFrame(animate);
|
|
} else {
|
|
movingDot.remove();
|
|
path.style.strokeOpacity = "0";
|
|
|
|
outputBox.style.display = 'flex';
|
|
outputBox.classList.add('highlight');
|
|
setTimeout(() => outputBox.classList.remove('highlight'), 500);
|
|
|
|
if (onComplete) onComplete();
|
|
}
|
|
}
|
|
|
|
requestAnimationFrame(animate);
|
|
}
|
|
|
|
const inputs = inputFiles.map(createInputPaper);
|
|
const outputs = outputFiles.map(createOutputBox);
|
|
|
|
function pulseBox() {
|
|
centerBox.classList.add('pulse');
|
|
setTimeout(() => centerBox.classList.remove('pulse'), 300);
|
|
}
|
|
|
|
async function animateInputs() {
|
|
|
|
outputs.forEach(output => {
|
|
output.outputBox.style.opacity = '0';
|
|
});
|
|
|
|
|
|
for (let i = 0; i < inputs.length; i++) {
|
|
await new Promise(resolve => {
|
|
animatePaperAlongPath(inputs[i].path, inputs[i].ext, () => {
|
|
pulseBox();
|
|
resolve();
|
|
});
|
|
});
|
|
|
|
await new Promise(resolve => setTimeout(resolve, 200));
|
|
}
|
|
|
|
pulseBox();
|
|
return true;
|
|
}
|
|
|
|
async function animateOutputs() {
|
|
|
|
for (let i = 0; i < outputs.length; i++) {
|
|
await new Promise(resolve => {
|
|
animateDotAlongPath(outputs[i].path, outputs[i].outputBox, () => {
|
|
outputs[i].outputBox.style.opacity = '1';
|
|
resolve();
|
|
});
|
|
});
|
|
|
|
|
|
await new Promise(resolve => setTimeout(resolve, 300));
|
|
}
|
|
|
|
|
|
await new Promise(resolve => setTimeout(resolve, 1500));
|
|
|
|
|
|
outputs.forEach(output => {
|
|
output.outputBox.style.opacity = '0';
|
|
});
|
|
|
|
|
|
await new Promise(resolve => setTimeout(resolve, 500));
|
|
return true;
|
|
}
|
|
|
|
async function completeAnimationCycle() {
|
|
if (isAnimating) return;
|
|
isAnimating = true;
|
|
|
|
try {
|
|
await animateInputs();
|
|
await new Promise(resolve => setTimeout(resolve, 800));
|
|
await animateOutputs();
|
|
isAnimating = false;
|
|
setTimeout(completeAnimationCycle, 500);
|
|
} catch (error) {
|
|
console.error("Animation error:", error);
|
|
isAnimating = false;
|
|
}
|
|
}
|
|
|
|
setTimeout(completeAnimationCycle, 1000);
|
|
|
|
function showPaperAlert(message, title = "Alert", icon = "fa-exclamation-circle", duration = 7000) {
|
|
const paperAlert = document.getElementById('paperAlert');
|
|
const alertMessage = document.getElementById('alertMessage');
|
|
const alertTitle = document.getElementById('alertTitle');
|
|
const alertIcon = document.getElementById('alertIcon');
|
|
|
|
|
|
alertMessage.textContent = message;
|
|
alertTitle.textContent = title;
|
|
|
|
|
|
alertIcon.className = '';
|
|
alertIcon.classList.add('fas', icon);
|
|
|
|
|
|
paperAlert.classList.remove("hide");
|
|
paperAlert.classList.add("show", "showAlert");
|
|
|
|
|
|
setTimeout(() => {
|
|
hideAlert();
|
|
}, duration);
|
|
}
|
|
|
|
|
|
function hideAlert() {
|
|
const paperAlert = document.getElementById('paperAlert');
|
|
paperAlert.classList.remove("show");
|
|
paperAlert.classList.add("hide");
|
|
setTimeout(() => {
|
|
paperAlert.classList.remove("showAlert");
|
|
}, 500);
|
|
}
|
|
|
|
|
|
document.querySelector('#paperAlert .close-btn').addEventListener('click', function() {
|
|
hideAlert();
|
|
});
|
|
|
|
const featureCards = document.querySelectorAll('.feature-selection .glass');
|
|
const selectionMessage = document.getElementById('selectionMessage');
|
|
const selectedFeatureText = document.getElementById('selectedFeature');
|
|
const selectedFeature = {"feature":null}
|
|
|
|
let isLoggedIn = localStorage.getItem("username");
|
|
let selectedCard = null;
|
|
|
|
featureCards.forEach(card => {
|
|
card.addEventListener('click', () => {
|
|
if (!isLoggedIn) {
|
|
|
|
showPaperAlert(
|
|
"You must be Logged In to continue!",
|
|
"Authentication Required",
|
|
"fa-exclamation-circle",
|
|
7000
|
|
);
|
|
return;
|
|
}
|
|
const isAlreadySelected = card === selectedCard;
|
|
|
|
if (isAlreadySelected) {
|
|
card.classList.remove('selected');
|
|
selectedCard = null;
|
|
selectionMessage.classList.remove('visible');
|
|
} else {
|
|
if (selectedCard) {
|
|
selectedCard.classList.remove('selected');
|
|
}
|
|
|
|
card.classList.add('selected');
|
|
selectedCard = card;
|
|
|
|
selectedFeature.feature = card.getAttribute('data-feature');
|
|
|
|
selectedFeatureText.textContent = card.getAttribute('data-text');
|
|
selectionMessage.classList.add('visible');
|
|
}
|
|
});
|
|
});
|
|
|
|
|
|
|
|
const searchBtn = document.getElementById("searchbtn");
|
|
searchBtn.addEventListener("click", function () {
|
|
console.log("Search button clicked");
|
|
|
|
|
|
|
|
const isLoggedIn = localStorage.getItem("username");
|
|
if (!isLoggedIn) {
|
|
alert("You must be signed in to perform a search.");
|
|
return;
|
|
}
|
|
|
|
const searchInput = document.querySelector('#searchy');
|
|
console.log("searchInput" , searchInput)
|
|
if (!searchInput) {
|
|
console.error("Search input element not found");
|
|
alert("Search input not found. Please check the page structure.");
|
|
return;
|
|
}
|
|
|
|
const searchTopic = searchInput.value.trim();
|
|
const yearFilter = document.getElementById('year-filter');
|
|
const searchYear = yearFilter ? yearFilter.value : "";
|
|
const userId = localStorage.getItem("userId");
|
|
|
|
saveSearchToFirebase(searchTopic, searchYear, selectedFeature )
|
|
|
|
|
|
|
|
if (!searchTopic) {
|
|
alert("Please enter a search topic");
|
|
return;
|
|
}
|
|
|
|
console.log(`Searching for: ${searchTopic}, Year: ${searchYear}, Feature: ${selectedFeature}`);
|
|
|
|
|
|
let currentPage = 0;
|
|
const nextBtn = document.getElementById("nextBtn");
|
|
|
|
nextBtn.addEventListener("click", function () {
|
|
currentPage+=1
|
|
alert("just checking bro " +currentPage );
|
|
trendanalysis(currentPage);
|
|
});
|
|
|
|
|
|
|
|
function trendanalysis(pageNo){
|
|
const originalText = searchBtn.textContent;
|
|
searchBtn.textContent = "Processing...";
|
|
searchBtn.disabled = true;
|
|
nextBtn.style.display = "inline-block";
|
|
|
|
|
|
fetch('/check-data-exists/', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({
|
|
userId: userId,
|
|
topic: searchTopic,
|
|
year: searchYear
|
|
})
|
|
})
|
|
.then(response => {
|
|
if (!response.ok) {
|
|
throw new Error(`Network response was not ok: ${response.status}`);
|
|
}
|
|
return response.json();
|
|
})
|
|
.then(data => {
|
|
if (data.exists) {
|
|
console.log('Data exists, skipping analysis step');
|
|
showPaperAlert(
|
|
"Data exists",
|
|
"Trend Analysis.......",
|
|
"fa-exclamation-circle",
|
|
7000
|
|
);
|
|
return fetch('/analyze-trends/', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({
|
|
userId: userId,
|
|
topic: searchTopic,
|
|
year: searchYear,
|
|
page: pageNo
|
|
})
|
|
});
|
|
} else {
|
|
console.log('Data does not exist, starting full analysis');
|
|
showPaperAlert(
|
|
"Starting full analysis",
|
|
"ATrend Analysis.......",
|
|
"fa-exclamation-circle",
|
|
7000
|
|
);
|
|
return fetch('/analyze/', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({
|
|
userId: userId,
|
|
topic: searchTopic,
|
|
year: searchYear
|
|
})
|
|
})
|
|
.then(response => {
|
|
if (!response.ok) {
|
|
throw new Error(`Analysis failed: ${response.status}`);
|
|
}
|
|
return response.json();
|
|
})
|
|
.then(analysisData => {
|
|
console.log('Analysis complete:', analysisData);
|
|
|
|
showPaperAlert(
|
|
"Analysis complete",
|
|
"Trend Analysis.......",
|
|
"fa-exclamation-circle",
|
|
7000
|
|
);
|
|
return fetch('/analyze-trends/', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({
|
|
userId: userId,
|
|
topic: searchTopic,
|
|
year: searchYear,
|
|
page: pageNo
|
|
})
|
|
});
|
|
});
|
|
}
|
|
})
|
|
.then(response => {
|
|
if (!response.ok) {
|
|
throw new Error(`Trend analysis failed: ${response.status}`);
|
|
}
|
|
return response.json();
|
|
})
|
|
.then(trendData => {
|
|
console.log('Trend analysis complete:', trendData);
|
|
showPaperAlert(
|
|
"Analysis complete",
|
|
"Trend Analysis.......",
|
|
"fa-exclamation-circle",
|
|
7000
|
|
);
|
|
loadingOverlay.hide()
|
|
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
alert("There was an error processing your request. Please try again: " + error.message);
|
|
showPaperAlert(
|
|
`There was an error processing your request. Please try again:` + error.message,
|
|
"Trend Analysis.......",
|
|
"fa-exclamation-circle",
|
|
7000
|
|
);
|
|
loadingOverlay.hide()
|
|
})
|
|
.finally(() => {
|
|
|
|
searchBtn.textContent = originalText;
|
|
searchBtn.disabled = false;
|
|
});
|
|
}
|
|
|
|
|
|
|
|
if (selectedFeature.feature === 'trends') {
|
|
console.log("here here")
|
|
loadingOverlay.show("Loading Trend Analysis")
|
|
trendanalysis(0);
|
|
}
|
|
else if (selectedFeature.feature === 'citations') {
|
|
loadingOverlay.show("Loading Citation Network Analysis")
|
|
nextBtn.style.display = "none";
|
|
currentPage = 0;
|
|
showPaperAlert(
|
|
"Analysis Started",
|
|
"Citation Network Analysis.......",
|
|
"fa-exclamation-circle",
|
|
7000
|
|
);
|
|
|
|
const originalText = this.textContent;
|
|
this.textContent = "Processing...";
|
|
this.disabled = true;
|
|
|
|
|
|
fetch('/check-data-exists-citation/', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({
|
|
userId: userId,
|
|
topic: searchTopic,
|
|
year: searchYear
|
|
})
|
|
})
|
|
.then(response => {
|
|
if (!response.ok) {
|
|
throw new Error(`Network response was not ok: ${response.status}`);
|
|
}
|
|
return response.json();
|
|
})
|
|
.then(data => {
|
|
if (data.exists) {
|
|
console.log('Data exists, fetching citation data...');
|
|
loadingOverlay.hide()
|
|
window.open(`/citation-data?userId=${encodeURIComponent(userId)}&topic=${encodeURIComponent(searchTopic)}&year=${encodeURIComponent(searchYear)}`, '_blank');
|
|
} else {
|
|
console.log('Data does not exist, starting full analysis...');
|
|
showPaperAlert(
|
|
"Data Collecting....",
|
|
"Citation Network Analysis.......",
|
|
"fa-exclamation-circle",
|
|
7000
|
|
);
|
|
return fetch('/save', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({
|
|
userId: userId,
|
|
topic: searchTopic,
|
|
year: searchYear
|
|
})
|
|
})
|
|
.then(response => {
|
|
if (!response.ok) {
|
|
throw new Error(`Save failed: ${response.status}`);
|
|
}
|
|
return response.json();
|
|
})
|
|
.then(saveData => {
|
|
console.log('Data saved successfully:', saveData);
|
|
loadingOverlay.hide()
|
|
window.open(`/citation-data?userId=${encodeURIComponent(userId)}&topic=${encodeURIComponent(searchTopic)}&year=${encodeURIComponent(searchYear)}`, '_blank');
|
|
});
|
|
}
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
showPaperAlert(
|
|
"There was an error processing your request. Please try again: " + error.message,
|
|
"Citation Network Analysis.......",
|
|
"fa-exclamation-circle",
|
|
7000
|
|
);
|
|
loadingOverlay.hide()
|
|
})
|
|
.finally(() => {
|
|
|
|
this.textContent = originalText;
|
|
this.disabled = false;
|
|
});
|
|
}
|
|
|
|
else if (selectedFeature.feature === 'venues') {
|
|
nextBtn.style.display = "none";
|
|
currentPage = 0;
|
|
const originalText = this.textContent;
|
|
this.textContent = "Processing...";
|
|
this.disabled = true;
|
|
console.log(" here here venue")
|
|
showPaperAlert(
|
|
"Analysis Started",
|
|
"Venue/Publisher Analysis.......",
|
|
"fa-exclamation-circle",
|
|
7000
|
|
);
|
|
loadingOverlay.show("Started Loading.....")
|
|
fetch('/check-data-exists-venue/', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({
|
|
userId: userId,
|
|
topic: searchTopic,
|
|
year: searchYear
|
|
})
|
|
})
|
|
.then(response => {
|
|
if (!response.ok) {
|
|
|
|
throw new Error(`Network response was not ok: ${response.status}`);
|
|
|
|
}
|
|
|
|
return response.json();
|
|
})
|
|
.then(data => {
|
|
if (data.exists) {
|
|
console.log('Data exists, loading dashboard directly');
|
|
|
|
|
|
return fetch('/load_and_display_dashboard/', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({
|
|
userId: userId,
|
|
topic: searchTopic,
|
|
year: searchYear
|
|
})
|
|
});
|
|
} else {
|
|
console.log('Data does not exist, starting search process');
|
|
showPaperAlert(
|
|
"Data Collectiong....",
|
|
"Venue/Publisher Analysis.......",
|
|
"fa-exclamation-circle",
|
|
7000
|
|
);
|
|
return fetch('/search/', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({
|
|
userId: userId,
|
|
topic: searchTopic,
|
|
year: searchYear
|
|
})
|
|
})
|
|
.then(response => {
|
|
if (!response.ok) {
|
|
throw new Error(`Search failed: ${response.status}`);
|
|
}
|
|
return response.json();
|
|
})
|
|
.then(searchData => {
|
|
console.log('Search complete:', searchData);
|
|
|
|
return fetch('/load_and_display_dashboard/', {
|
|
method: 'POST',
|
|
headers: {
|
|
'Content-Type': 'application/json',
|
|
},
|
|
body: JSON.stringify({
|
|
userId: userId,
|
|
topic: searchTopic,
|
|
year: searchYear
|
|
})
|
|
});
|
|
});
|
|
}
|
|
})
|
|
.then(response => {
|
|
if (!response.ok) {
|
|
throw new Error(`Dashboard loading failed: ${response.status}`);
|
|
}
|
|
return response.json();
|
|
})
|
|
.then(dashboardData => {
|
|
|
|
console.log('Dashboard loaded successfully:', dashboardData);
|
|
loadingOverlay.hide();
|
|
|
|
})
|
|
.catch(error => {
|
|
console.error('Error:', error);
|
|
showPaperAlert(
|
|
"There was an error processing your request. Please try again: " + error.message,
|
|
"Venue/Publisher Analysis.......",
|
|
"fa-exclamation-circle",
|
|
7000
|
|
);
|
|
})
|
|
.finally(() => {
|
|
this.textContent = originalText;
|
|
this.disabled = false;
|
|
});
|
|
|
|
} else {
|
|
alert("Invalid feature selected. Please choose a valid feature.");
|
|
}
|
|
});
|
|
|
|
|
|
const loadingOverlay = {
|
|
overlay: document.getElementById('loading-overlay'),
|
|
cyclone: null,
|
|
loadingText: null,
|
|
animationInterval: null,
|
|
paperInterval: null,
|
|
|
|
initialize() {
|
|
this.cyclone = document.getElementById('cyclone');
|
|
this.loadingText = document.getElementById('loading-text');
|
|
this.setupAnimation();
|
|
|
|
|
|
this.overlay.style.backgroundColor = 'rgba(137, 138, 183, 0.9)';
|
|
},
|
|
|
|
setupAnimation() {
|
|
|
|
for (let i = 0; i < 10; i++) {
|
|
this.createPaper(i);
|
|
}
|
|
},
|
|
|
|
show(message = 'Processing...') {
|
|
this.loadingText.textContent = message;
|
|
this.overlay.classList.add('active');
|
|
|
|
|
|
this.paperInterval = setInterval(() => {
|
|
this.createPaper();
|
|
}, 120);
|
|
|
|
|
|
let dots = 0;
|
|
this.animationInterval = setInterval(() => {
|
|
dots = (dots + 1) % 4;
|
|
this.loadingText.textContent = message + '.'.repeat(dots);
|
|
}, 500);
|
|
},
|
|
|
|
hide() {
|
|
this.overlay.classList.remove('active');
|
|
|
|
|
|
clearInterval(this.paperInterval);
|
|
clearInterval(this.animationInterval);
|
|
|
|
|
|
setTimeout(() => {
|
|
while (this.cyclone.firstChild) {
|
|
this.cyclone.removeChild(this.cyclone.firstChild);
|
|
}
|
|
}, 300);
|
|
},
|
|
|
|
createPaper(index) {
|
|
const paper = document.createElement('div');
|
|
paper.className = 'paper';
|
|
|
|
|
|
const size = 8 + Math.random() * 12;
|
|
paper.style.width = `${size}px`;
|
|
paper.style.height = `${size * 1.3}px`;
|
|
|
|
|
|
const grayness = 65 + Math.random() * 20;
|
|
paper.style.backgroundColor = `hsl(0, 0%, ${grayness}%)`;
|
|
|
|
|
|
const skewX = Math.random() * 10 - 5;
|
|
const skewY = Math.random() * 10 - 5;
|
|
paper.style.transform = `skew(${skewX}deg, ${skewY}deg)`;
|
|
|
|
|
|
const startAngle = Math.random() * Math.PI * 2;
|
|
const startRadius = 60 + Math.random() * 20;
|
|
const startX = 100 + startRadius * Math.cos(startAngle);
|
|
const startY = -20;
|
|
|
|
paper.style.left = `${startX}px`;
|
|
paper.style.top = `${startY}px`;
|
|
|
|
this.cyclone.appendChild(paper);
|
|
|
|
|
|
this.animatePaperInCyclone(paper, startAngle);
|
|
},
|
|
|
|
animatePaperInCyclone(paper, initialAngle) {
|
|
|
|
const duration = 6000 + Math.random() * 2000;
|
|
const startTime = Date.now();
|
|
|
|
|
|
let angle = initialAngle || 0;
|
|
let height = -20;
|
|
const maxHeight = 350;
|
|
const rotationSpeed = 1.0 + Math.random() * 0.5;
|
|
|
|
const animateFrame = () => {
|
|
if (!this.overlay.classList.contains('active')) {
|
|
if (paper.parentNode === this.cyclone) {
|
|
this.cyclone.removeChild(paper);
|
|
}
|
|
return;
|
|
}
|
|
|
|
const now = Date.now();
|
|
const elapsed = now - startTime;
|
|
const progress = elapsed / duration;
|
|
|
|
if (progress < 1) {
|
|
|
|
|
|
height = -20 + (maxHeight + 20) * Math.min(1, progress * 1.2);
|
|
|
|
|
|
|
|
const heightProgress = height / maxHeight;
|
|
const currentRadius = Math.max(10, 80 - 60 * heightProgress);
|
|
|
|
|
|
const adjustedRotation = rotationSpeed * (1 + heightProgress * 0.5);
|
|
angle += adjustedRotation * 0.03;
|
|
|
|
|
|
const x = 100 + currentRadius * Math.cos(angle);
|
|
const y = height;
|
|
|
|
|
|
paper.style.left = `${x}px`;
|
|
paper.style.top = `${y}px`;
|
|
|
|
|
|
const rotation = angle * (180 / Math.PI);
|
|
|
|
const flutter = Math.sin(elapsed * 0.01) * (5 + heightProgress * 10);
|
|
paper.style.transform = `rotate(${rotation + flutter}deg) scale(${0.8 + Math.sin(progress * Math.PI * 4) * 0.1})`;
|
|
|
|
|
|
if (progress > 0.8) {
|
|
paper.style.opacity = (1 - progress) * 5;
|
|
}
|
|
|
|
requestAnimationFrame(animateFrame);
|
|
} else {
|
|
|
|
if (paper.parentNode === this.cyclone) {
|
|
this.cyclone.removeChild(paper);
|
|
}
|
|
}
|
|
};
|
|
|
|
requestAnimationFrame(animateFrame);
|
|
}
|
|
};
|
|
|
|
document.addEventListener('DOMContentLoaded', () => {
|
|
loadingOverlay.initialize();
|
|
});
|
|
const words = document.querySelectorAll('.liquid-word');
|
|
const splashContainer = document.getElementById('splashContainer');
|
|
let currentIndex = 0;
|
|
|
|
|
|
words.forEach(word => {
|
|
const letters = word.textContent.split('');
|
|
word.innerHTML = '';
|
|
|
|
letters.forEach(letter => {
|
|
const charSpan = document.createElement('span');
|
|
charSpan.className = 'liquid-char';
|
|
charSpan.textContent = letter;
|
|
word.appendChild(charSpan);
|
|
|
|
|
|
const paperDrop = document.createElement('div');
|
|
paperDrop.className = 'paper-drop';
|
|
charSpan.appendChild(paperDrop);
|
|
|
|
|
|
for (let i = 0; i < 3; i++) {
|
|
const paperBg = document.createElement('div');
|
|
paperBg.className = 'paper-piece';
|
|
paperBg.style.width = `${Math.random() * 20 + 20}px`;
|
|
paperBg.style.height = `${Math.random() * 15 + 15}px`;
|
|
paperBg.style.transform = `rotate(${Math.random() * 40 - 20}deg)`;
|
|
|
|
|
|
const offsetX = (Math.random() - 0.5) * 30;
|
|
const offsetY = (Math.random() - 0.5) * 30;
|
|
paperBg.style.left = `calc(50% + ${offsetX}px)`;
|
|
paperBg.style.top = `calc(50% + ${offsetY}px)`;
|
|
|
|
|
|
const colors = ['#ffffff', '#f8f8f8', '#f0f0f0', '#fffafa', '#f5f5f5'];
|
|
paperBg.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];
|
|
|
|
charSpan.appendChild(paperBg);
|
|
}
|
|
});
|
|
});
|
|
|
|
|
|
function createPaperSplashes(centerX, centerY) {
|
|
for (let i = 0; i < 15; i++) {
|
|
setTimeout(() => {
|
|
const paper = document.createElement('div');
|
|
paper.className = 'paper-piece';
|
|
|
|
|
|
const size = Math.random() * 20 + 10;
|
|
paper.style.width = `${size}px`;
|
|
paper.style.height = `${size * (Math.random() * 0.5 + 0.5)}px`;
|
|
|
|
|
|
const rotation = Math.random() * 360;
|
|
paper.style.setProperty('--rotation', `${rotation}deg`);
|
|
|
|
|
|
const angle = Math.random() * Math.PI * 2;
|
|
const distance = Math.random() * 100 + 20;
|
|
const x = centerX + Math.cos(angle) * distance;
|
|
const y = centerY + Math.sin(angle) * distance;
|
|
|
|
paper.style.left = `${x}px`;
|
|
paper.style.top = `${y}px`;
|
|
|
|
|
|
const colors = ['#ffffff', '#f8f8f8', '#f0f0f0', '#fffafa', '#f5f5f5'];
|
|
paper.style.backgroundColor = colors[Math.floor(Math.random() * colors.length)];
|
|
|
|
|
|
if (Math.random() > 0.7) {
|
|
paper.style.border = '1px solid rgba(0,0,0,0.05)';
|
|
}
|
|
|
|
|
|
paper.style.animation = `paperSplash ${Math.random() * 0.8 + 0.6}s forwards`;
|
|
|
|
splashContainer.appendChild(paper);
|
|
|
|
|
|
setTimeout(() => paper.remove(), 1500);
|
|
}, i * 40);
|
|
}
|
|
}
|
|
|
|
|
|
function animateLettersIn(word) {
|
|
const chars = word.querySelectorAll('.liquid-char');
|
|
|
|
chars.forEach((char, i) => {
|
|
setTimeout(() => {
|
|
|
|
char.style.animation = 'paperIn 0.7s forwards';
|
|
char.style.opacity = '1';
|
|
|
|
|
|
const paperDrop = char.querySelector('.paper-drop');
|
|
setTimeout(() => {
|
|
paperDrop.style.animation = 'paperDrop 0.5s forwards';
|
|
}, 350);
|
|
|
|
|
|
const paperPieces = char.querySelectorAll('.paper-piece');
|
|
paperPieces.forEach((piece, j) => {
|
|
setTimeout(() => {
|
|
piece.style.opacity = '1';
|
|
piece.style.transform += ' scale(1)';
|
|
}, j * 100 + 300);
|
|
});
|
|
|
|
}, i * 100);
|
|
});
|
|
}
|
|
|
|
|
|
function animateLettersOut(word) {
|
|
const chars = word.querySelectorAll('.liquid-char');
|
|
|
|
chars.forEach((char, i) => {
|
|
setTimeout(() => {
|
|
char.style.animation = 'paperOut 0.5s forwards';
|
|
|
|
|
|
const paperPieces = char.querySelectorAll('.paper-piece');
|
|
paperPieces.forEach(piece => {
|
|
piece.style.opacity = '0';
|
|
});
|
|
}, i * 60);
|
|
});
|
|
}
|
|
|
|
|
|
function transitionWords() {
|
|
|
|
const currentWord = words[currentIndex];
|
|
const rect = currentWord.getBoundingClientRect();
|
|
const centerX = rect.width / 2;
|
|
const centerY = rect.height / 2;
|
|
|
|
|
|
animateLettersOut(currentWord);
|
|
|
|
setTimeout(() => {
|
|
|
|
currentWord.classList.remove('active');
|
|
|
|
|
|
currentIndex = (currentIndex + 1) % words.length;
|
|
const nextWord = words[currentIndex];
|
|
|
|
|
|
nextWord.classList.add('active');
|
|
|
|
|
|
createPaperSplashes(centerX, centerY);
|
|
|
|
|
|
setTimeout(() => {
|
|
animateLettersIn(nextWord);
|
|
}, 200);
|
|
|
|
}, 500);
|
|
}
|
|
|
|
|
|
setTimeout(() => {
|
|
animateLettersIn(words[0]);
|
|
}, 500);
|
|
|
|
|
|
setInterval(transitionWords, 3500);
|
|
|
|
|
|
const carousel = document.getElementById('carousel');
|
|
const pages = document.querySelectorAll('.page');
|
|
const nextBtn2 = document.getElementById('nextBtn2');
|
|
const prevBtn = document.getElementById('prevBtn');
|
|
const dots = document.querySelectorAll('.dot');
|
|
const pageShadows = document.querySelectorAll('.page-shadow');
|
|
|
|
let currentPage = 0;
|
|
let totalSlides = 6;
|
|
|
|
|
|
pages.forEach((page, index) => {
|
|
page.style.transform = 'rotateY(0deg)';
|
|
page.style.zIndex = 6 - index;
|
|
});
|
|
|
|
|
|
function nextPage() {
|
|
if (currentPage < pages.length) {
|
|
|
|
if (currentPage > 0) {
|
|
pageShadows[currentPage-1].style.opacity = '0';
|
|
}
|
|
|
|
pages[currentPage].style.transform = 'rotateY(-180deg)';
|
|
pages[currentPage].style.zIndex = 10 + currentPage;
|
|
|
|
if (currentPage < pages.length - 1) {
|
|
pageShadows[currentPage].style.opacity = '1';
|
|
}
|
|
|
|
currentPage++;
|
|
|
|
|
|
const newRotationDegree = (currentPage % totalSlides) * (360 / totalSlides);
|
|
carousel.style.transform = `rotateY(${-newRotationDegree}deg)`;
|
|
|
|
|
|
updatePagination(currentPage % totalSlides);
|
|
}
|
|
}
|
|
|
|
|
|
function prevPage() {
|
|
if (currentPage > 0) {
|
|
currentPage--;
|
|
|
|
|
|
if (currentPage > 0) {
|
|
pageShadows[currentPage-1].style.opacity = '1';
|
|
}
|
|
|
|
pages[currentPage].style.transform = 'rotateY(0deg)';
|
|
setTimeout(() => {
|
|
pages[currentPage].style.zIndex = 10 - currentPage;
|
|
}, 300);
|
|
|
|
pageShadows[currentPage].style.opacity = '0';
|
|
|
|
|
|
const newRotationDegree = (currentPage % totalSlides) * (360 / totalSlides);
|
|
carousel.style.transform = `rotateY(${-newRotationDegree}deg)`;
|
|
|
|
|
|
updatePagination(currentPage % totalSlides);
|
|
}
|
|
}
|
|
|
|
|
|
function resetBook() {
|
|
pages.forEach((page, index) => {
|
|
page.style.transition = 'none';
|
|
page.style.transform = 'rotateY(0deg)';
|
|
setTimeout(() => {
|
|
page.style.zIndex = 5 - index;
|
|
page.style.transition = 'transform 0.6s ease, z-index 0s 0.3s';
|
|
}, 50);
|
|
});
|
|
|
|
pageShadows.forEach(shadow => {
|
|
shadow.style.opacity = '0';
|
|
});
|
|
|
|
currentPage = 0;
|
|
|
|
|
|
carousel.style.transform = 'rotateY(0deg)';
|
|
updatePagination(0);
|
|
}
|
|
|
|
|
|
function updatePagination(index) {
|
|
dots.forEach((dot, i) => {
|
|
if (i === index) {
|
|
dot.classList.add('active');
|
|
} else {
|
|
dot.classList.remove('active');
|
|
}
|
|
});
|
|
}
|
|
|
|
|
|
nextBtn2.addEventListener('click', nextPage);
|
|
prevBtn.addEventListener('click', prevPage);
|
|
|
|
|
|
dots.forEach((dot, index) => {
|
|
dot.addEventListener('click', () => {
|
|
|
|
const currentInCycle = currentPage % totalSlides;
|
|
|
|
|
|
let pagesToMove;
|
|
|
|
if (index > currentInCycle) {
|
|
pagesToMove = index - currentInCycle;
|
|
} else if (index < currentInCycle) {
|
|
pagesToMove = totalSlides - currentInCycle + index;
|
|
} else {
|
|
return;
|
|
}
|
|
|
|
|
|
for (let i = 0; i < pagesToMove; i++) {
|
|
setTimeout(() => nextPage(), i * 400);
|
|
}
|
|
});
|
|
});
|
|
|
|
|
|
pages.forEach((page, index) => {
|
|
page.addEventListener('click', () => {
|
|
if (index === currentPage - 1) {
|
|
prevPage();
|
|
} else if (index === currentPage) {
|
|
nextPage();
|
|
}
|
|
});
|
|
});
|
|
|
|
const canvas = document.getElementById('bgParticles');
|
|
if (canvas) {
|
|
const ctx = canvas.getContext('2d');
|
|
let particles = [];
|
|
const colors = ['#ff6ec4', '#7873f5', '#1fd1f9', '#43e97b'];
|
|
let width = window.innerWidth;
|
|
let height = window.innerHeight;
|
|
canvas.width = width;
|
|
canvas.height = height;
|
|
|
|
function randomBetween(a, b) { return a + Math.random() * (b - a); }
|
|
|
|
function createParticles(num) {
|
|
particles = [];
|
|
for (let i = 0; i < num; i++) {
|
|
particles.push({
|
|
x: randomBetween(0, width),
|
|
y: randomBetween(0, height),
|
|
r: randomBetween(2, 5),
|
|
color: colors[Math.floor(Math.random() * colors.length)],
|
|
dx: randomBetween(-0.7, 0.7),
|
|
dy: randomBetween(-0.7, 0.7),
|
|
alpha: randomBetween(0.3, 0.8)
|
|
});
|
|
}
|
|
}
|
|
|
|
function drawParticles() {
|
|
ctx.clearRect(0, 0, width, height);
|
|
for (let p of particles) {
|
|
ctx.save();
|
|
ctx.globalAlpha = p.alpha;
|
|
ctx.beginPath();
|
|
ctx.arc(p.x, p.y, p.r, 0, Math.PI * 2);
|
|
ctx.fillStyle = p.color;
|
|
ctx.shadowColor = p.color;
|
|
ctx.shadowBlur = 16;
|
|
ctx.fill();
|
|
ctx.restore();
|
|
|
|
p.x += p.dx;
|
|
p.y += p.dy;
|
|
if (p.x < 0 || p.x > width) p.dx *= -1;
|
|
if (p.y < 0 || p.y > height) p.dy *= -1;
|
|
}
|
|
requestAnimationFrame(drawParticles);
|
|
}
|
|
|
|
createParticles(48);
|
|
drawParticles();
|
|
|
|
window.addEventListener('resize', () => {
|
|
width = window.innerWidth;
|
|
height = window.innerHeight;
|
|
canvas.width = width;
|
|
canvas.height = height;
|
|
createParticles(48);
|
|
});
|
|
}
|
|
|