Dify-Learning / static /js /main.js
AtZa
Upload 16 files
7cb4836 verified
// Main JavaScript functionality for the Dify Learning Platform
document.addEventListener('DOMContentLoaded', function() {
// Initialize tooltips
initializeTooltips();
// Initialize animations
initializeAnimations();
// Initialize progress tracking
initializeProgressTracking();
// Initialize search functionality
initializeSearch();
});
/**
* Initialize Bootstrap tooltips
*/
function initializeTooltips() {
var tooltipTriggerList = [].slice.call(document.querySelectorAll('[data-bs-toggle="tooltip"]'));
var tooltipList = tooltipTriggerList.map(function (tooltipTriggerEl) {
return new bootstrap.Tooltip(tooltipTriggerEl);
});
}
/**
* Initialize scroll animations
*/
function initializeAnimations() {
// Fade in elements on scroll
const observerOptions = {
threshold: 0.1,
rootMargin: '0px 0px -50px 0px'
};
const observer = new IntersectionObserver(function(entries) {
entries.forEach(entry => {
if (entry.isIntersecting) {
entry.target.classList.add('fade-in');
}
});
}, observerOptions);
// Observe elements for animation
document.querySelectorAll('.tutorial-card, .project-card, .feature-item').forEach(el => {
observer.observe(el);
});
}
/**
* Initialize progress tracking
*/
function initializeProgressTracking() {
// Track page views
trackPageView();
// Track tutorial interactions
document.querySelectorAll('.tutorial-card .btn').forEach(btn => {
btn.addEventListener('click', function(e) {
const tutorialTitle = this.closest('.tutorial-card').querySelector('.card-title').textContent;
trackEvent('tutorial_started', { tutorial: tutorialTitle });
});
});
// Track project interactions
document.querySelectorAll('.project-card .btn').forEach(btn => {
btn.addEventListener('click', function(e) {
const projectTitle = this.closest('.project-card').querySelector('.card-title').textContent;
trackEvent('project_started', { project: projectTitle });
});
});
}
/**
* Initialize search functionality
*/
function initializeSearch() {
const searchInput = document.getElementById('search-input');
if (searchInput) {
searchInput.addEventListener('input', debounce(handleSearch, 300));
}
}
/**
* Handle search functionality
*/
function handleSearch(event) {
const query = event.target.value.toLowerCase().trim();
const tutorials = document.querySelectorAll('.tutorial-card');
const projects = document.querySelectorAll('.project-card');
// Filter tutorials
tutorials.forEach(card => {
const title = card.querySelector('.card-title').textContent.toLowerCase();
const description = card.querySelector('.card-text').textContent.toLowerCase();
const isVisible = title.includes(query) || description.includes(query) || query === '';
card.closest('.path-item, .col-md-6, .col-lg-4')?.style.setProperty('display', isVisible ? '' : 'none');
});
// Filter projects
projects.forEach(card => {
const title = card.querySelector('.card-title').textContent.toLowerCase();
const description = card.querySelector('.card-text').textContent.toLowerCase();
const isVisible = title.includes(query) || description.includes(query) || query === '';
card.closest('.col-md-6, .col-lg-4')?.style.setProperty('display', isVisible ? '' : 'none');
});
// Show/hide sections based on results
updateSearchResults(query);
}
/**
* Update search results display
*/
function updateSearchResults(query) {
const tutorialSection = document.querySelector('.learning-path');
const projectSection = document.querySelector('#projects');
if (query) {
const visibleTutorials = document.querySelectorAll('.tutorial-card:not([style*="display: none"])');
const visibleProjects = document.querySelectorAll('.project-card:not([style*="display: none"])');
// Show no results message if needed
if (visibleTutorials.length === 0 && visibleProjects.length === 0) {
showNoResultsMessage();
} else {
hideNoResultsMessage();
}
} else {
hideNoResultsMessage();
}
}
/**
* Show no results message
*/
function showNoResultsMessage() {
let noResultsMsg = document.getElementById('no-results-message');
if (!noResultsMsg) {
noResultsMsg = document.createElement('div');
noResultsMsg.id = 'no-results-message';
noResultsMsg.className = 'alert alert-info text-center';
noResultsMsg.innerHTML = `
<i data-feather="search" class="me-2"></i>
No tutorials or projects found matching your search.
`;
document.querySelector('.container').appendChild(noResultsMsg);
feather.replace();
}
noResultsMsg.style.display = 'block';
}
/**
* Hide no results message
*/
function hideNoResultsMessage() {
const noResultsMsg = document.getElementById('no-results-message');
if (noResultsMsg) {
noResultsMsg.style.display = 'none';
}
}
/**
* Track page views for analytics
*/
function trackPageView() {
const pageData = {
page: window.location.pathname,
title: document.title,
timestamp: new Date().toISOString()
};
// Store in localStorage for demo purposes
const visits = JSON.parse(localStorage.getItem('dify_visits') || '[]');
visits.push(pageData);
localStorage.setItem('dify_visits', JSON.stringify(visits.slice(-100))); // Keep last 100 visits
}
/**
* Track custom events
*/
function trackEvent(eventName, eventData = {}) {
const event = {
name: eventName,
data: eventData,
timestamp: new Date().toISOString(),
page: window.location.pathname
};
// Store in localStorage for demo purposes
const events = JSON.parse(localStorage.getItem('dify_events') || '[]');
events.push(event);
localStorage.setItem('dify_events', JSON.stringify(events.slice(-100))); // Keep last 100 events
console.log('Event tracked:', event);
}
/**
* Utility function to debounce function calls
*/
function debounce(func, wait) {
let timeout;
return function(...args) {
const later = () => {
clearTimeout(timeout);
func.apply(this, args);
};
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
}
/**
* Smooth scroll to element
*/
function smoothScrollTo(element, offset = 80) {
const targetPosition = element.offsetTop - offset;
window.scrollTo({
top: targetPosition,
behavior: 'smooth'
});
}
/**
* Show loading spinner
*/
function showLoader(container) {
const loader = document.createElement('div');
loader.className = 'text-center py-4';
loader.innerHTML = `
<div class="spinner-border text-primary" role="status">
<span class="visually-hidden">Loading...</span>
</div>
`;
container.appendChild(loader);
return loader;
}
/**
* Hide loading spinner
*/
function hideLoader(loader) {
if (loader && loader.parentNode) {
loader.parentNode.removeChild(loader);
}
}
/**
* Show toast notification
*/
function showToast(message, type = 'info') {
const toast = document.createElement('div');
toast.className = `toast align-items-center text-white bg-${type} border-0`;
toast.setAttribute('role', 'alert');
toast.setAttribute('aria-live', 'assertive');
toast.setAttribute('aria-atomic', 'true');
toast.innerHTML = `
<div class="d-flex">
<div class="toast-body">
${message}
</div>
<button type="button" class="btn-close btn-close-white me-2 m-auto" data-bs-dismiss="toast"></button>
</div>
`;
// Add to toast container or create one
let toastContainer = document.getElementById('toast-container');
if (!toastContainer) {
toastContainer = document.createElement('div');
toastContainer.id = 'toast-container';
toastContainer.className = 'toast-container position-fixed top-0 end-0 p-3';
toastContainer.style.zIndex = '9999';
document.body.appendChild(toastContainer);
}
toastContainer.appendChild(toast);
// Initialize and show toast
const bsToast = new bootstrap.Toast(toast);
bsToast.show();
// Remove from DOM after hiding
toast.addEventListener('hidden.bs.toast', () => {
toast.remove();
});
}
/**
* Copy text to clipboard
*/
async function copyToClipboard(text) {
try {
await navigator.clipboard.writeText(text);
showToast('Copied to clipboard!', 'success');
} catch (err) {
console.error('Failed to copy:', err);
showToast('Failed to copy to clipboard', 'danger');
}
}
/**
* Format time duration
*/
function formatDuration(minutes) {
if (minutes < 60) {
return `${minutes} min`;
} else {
const hours = Math.floor(minutes / 60);
const remainingMinutes = minutes % 60;
return remainingMinutes > 0 ? `${hours}h ${remainingMinutes}m` : `${hours}h`;
}
}
/**
* Calculate reading time for content
*/
function calculateReadingTime(text, wordsPerMinute = 200) {
const wordCount = text.split(/\s+/).length;
const minutes = Math.ceil(wordCount / wordsPerMinute);
return Math.max(1, minutes);
}
/**
* Initialize progress bars with animation
*/
function animateProgressBar(progressBar, targetWidth) {
let currentWidth = 0;
const increment = targetWidth / 20;
const interval = setInterval(() => {
currentWidth += increment;
if (currentWidth >= targetWidth) {
currentWidth = targetWidth;
clearInterval(interval);
}
progressBar.style.width = `${currentWidth}%`;
}, 50);
}
// Export functions for use in other scripts
window.DifyLearning = {
trackEvent,
showToast,
copyToClipboard,
formatDuration,
calculateReadingTime,
smoothScrollTo,
showLoader,
hideLoader,
animateProgressBar
};