summaryrefslogtreecommitdiff
path: root/static/blog-script.js
diff options
context:
space:
mode:
Diffstat (limited to 'static/blog-script.js')
-rw-r--r--static/blog-script.js344
1 files changed, 344 insertions, 0 deletions
diff --git a/static/blog-script.js b/static/blog-script.js
new file mode 100644
index 0000000..73719a8
--- /dev/null
+++ b/static/blog-script.js
@@ -0,0 +1,344 @@
+// DOM Elements
+const searchInput = document.getElementById('searchInput');
+const searchBtn = document.getElementById('searchBtn');
+const blogGrid = document.getElementById('blogGrid');
+const categoryLinks = document.querySelectorAll('.category-link');
+const sortSelect = document.getElementById('sortBy');
+const paginationNumbers = document.querySelectorAll('.pagination-number');
+const prevBtn = document.getElementById('prevBtn');
+const nextBtn = document.getElementById('nextBtn');
+
+// Blog posts data (in a real app, this would come from an API)
+const blogPosts = Array.from(document.querySelectorAll('.blog-post'));
+
+// Search functionality
+const performSearch = () => {
+ const searchTerm = searchInput.value.toLowerCase().trim();
+
+ blogPosts.forEach(post => {
+ const title = post.querySelector('.post-title').textContent.toLowerCase();
+ const excerpt = post.querySelector('.post-excerpt').textContent.toLowerCase();
+ const category = post.querySelector('.post-category').textContent.toLowerCase();
+
+ const matches = title.includes(searchTerm) ||
+ excerpt.includes(searchTerm) ||
+ category.includes(searchTerm);
+
+ post.style.display = matches || searchTerm === '' ? 'block' : 'none';
+ });
+
+ // Update results count
+ const visiblePosts = blogPosts.filter(post => post.style.display !== 'none');
+ updateResultsMessage(visiblePosts.length, searchTerm);
+};
+
+const updateResultsMessage = (count, searchTerm) => {
+ let existingMessage = document.querySelector('.search-results-message');
+
+ if (existingMessage) {
+ existingMessage.remove();
+ }
+
+ if (searchTerm) {
+ const message = document.createElement('div');
+ message.className = 'search-results-message';
+ message.style.cssText = `
+ padding: 1rem;
+ background: var(--surface);
+ border-radius: 0.5rem;
+ margin-bottom: 2rem;
+ color: var(--text-secondary);
+ text-align: center;
+ `;
+ message.textContent = `Found ${count} article${count !== 1 ? 's' : ''} for "${searchTerm}"`;
+
+ blogGrid.parentNode.insertBefore(message, blogGrid);
+ }
+};
+
+// Search event listeners
+searchBtn.addEventListener('click', performSearch);
+searchInput.addEventListener('keypress', (e) => {
+ if (e.key === 'Enter') {
+ performSearch();
+ }
+});
+
+// Real-time search
+searchInput.addEventListener('input', () => {
+ if (searchInput.value.length > 2 || searchInput.value.length === 0) {
+ performSearch();
+ }
+});
+
+// Category filtering
+categoryLinks.forEach(link => {
+ link.addEventListener('click', (e) => {
+ e.preventDefault();
+
+ // Update active state
+ categoryLinks.forEach(l => l.classList.remove('active'));
+ link.classList.add('active');
+
+ const category = link.dataset.category;
+
+ blogPosts.forEach(post => {
+ if (category === 'all') {
+ post.style.display = 'block';
+ } else {
+ const postCategory = post.dataset.category;
+ post.style.display = postCategory === category ? 'block' : 'none';
+ }
+ });
+
+ // Clear search when filtering by category
+ searchInput.value = '';
+ const existingMessage = document.querySelector('.search-results-message');
+ if (existingMessage) {
+ existingMessage.remove();
+ }
+
+ // Update pagination
+ updatePagination();
+ });
+});
+
+// Sorting functionality
+sortSelect.addEventListener('change', () => {
+ const sortBy = sortSelect.value;
+ const postsArray = Array.from(blogPosts);
+
+ postsArray.sort((a, b) => {
+ const dateA = new Date(a.querySelector('.post-date').textContent);
+ const dateB = new Date(b.querySelector('.post-date').textContent);
+
+ switch (sortBy) {
+ case 'newest':
+ return dateB - dateA;
+ case 'oldest':
+ return dateA - dateB;
+ case 'popular':
+ // In a real app, this would sort by view count or engagement
+ return Math.random() - 0.5;
+ default:
+ return 0;
+ }
+ });
+
+ // Re-append sorted posts to the grid
+ postsArray.forEach(post => {
+ blogGrid.appendChild(post);
+ });
+});
+
+// Pagination functionality
+let currentPage = 1;
+const postsPerPage = 6;
+
+const updatePagination = () => {
+ const visiblePosts = blogPosts.filter(post => post.style.display !== 'none');
+ const totalPages = Math.ceil(visiblePosts.length / postsPerPage);
+
+ // Show/hide posts based on current page
+ visiblePosts.forEach((post, index) => {
+ const startIndex = (currentPage - 1) * postsPerPage;
+ const endIndex = startIndex + postsPerPage;
+
+ if (index >= startIndex && index < endIndex) {
+ post.style.display = 'block';
+ } else {
+ post.style.display = 'none';
+ }
+ });
+
+ // Update pagination buttons
+ prevBtn.disabled = currentPage === 1;
+ nextBtn.disabled = currentPage === totalPages || totalPages === 0;
+
+ // Update page numbers
+ paginationNumbers.forEach((btn, index) => {
+ btn.classList.toggle('active', index + 1 === currentPage);
+ });
+};
+
+// Pagination event listeners
+prevBtn.addEventListener('click', () => {
+ if (currentPage > 1) {
+ currentPage--;
+ updatePagination();
+ scrollToTop();
+ }
+});
+
+nextBtn.addEventListener('click', () => {
+ const visiblePosts = blogPosts.filter(post => post.style.display !== 'none');
+ const totalPages = Math.ceil(visiblePosts.length / postsPerPage);
+
+ if (currentPage < totalPages) {
+ currentPage++;
+ updatePagination();
+ scrollToTop();
+ }
+});
+
+paginationNumbers.forEach((btn, index) => {
+ btn.addEventListener('click', () => {
+ currentPage = index + 1;
+ updatePagination();
+ scrollToTop();
+ });
+});
+
+const scrollToTop = () => {
+ blogGrid.scrollIntoView({ behavior: 'smooth', block: 'start' });
+};
+
+// Newsletter form handlers
+document.querySelectorAll('.newsletter-form, .newsletter-form-large').forEach(form => {
+ form.addEventListener('submit', (e) => {
+ e.preventDefault();
+ const email = form.querySelector('input[type="email"]').value;
+
+ if (email) {
+ showToast(`Thanks for subscribing! We'll send updates to ${email}`, 'success');
+ form.reset();
+ }
+ });
+});
+
+// Toast notification function
+const showToast = (message, type = 'success') => {
+ const toast = document.createElement('div');
+ toast.className = 'toast';
+ toast.style.cssText = `
+ position: fixed;
+ top: 2rem;
+ right: 2rem;
+ background: ${type === 'success' ? 'var(--success)' : 'var(--error)'};
+ color: white;
+ padding: 1rem 1.5rem;
+ border-radius: 0.5rem;
+ box-shadow: var(--shadow-lg);
+ z-index: 1000;
+ transform: translateX(100%);
+ transition: transform 0.3s ease;
+ `;
+ toast.textContent = message;
+
+ document.body.appendChild(toast);
+
+ // Show toast
+ setTimeout(() => {
+ toast.style.transform = 'translateX(0)';
+ }, 100);
+
+ // Hide toast
+ setTimeout(() => {
+ toast.style.transform = 'translateX(100%)';
+ setTimeout(() => {
+ document.body.removeChild(toast);
+ }, 300);
+ }, 4000);
+};
+
+// Read more link handlers
+document.querySelectorAll('.read-more').forEach(link => {
+ link.addEventListener('click', (e) => {
+ e.preventDefault();
+ const postTitle = link.closest('.blog-post').querySelector('.post-title').textContent;
+ showToast(`Opening article: "${postTitle}"`, 'success');
+
+ // In a real app, this would navigate to the full article
+ setTimeout(() => {
+ window.location.href = `article.html?title=${encodeURIComponent(postTitle)}`;
+ }, 1000);
+ });
+});
+
+// Navbar background on scroll
+window.addEventListener('scroll', () => {
+ const navbar = document.querySelector('.navbar');
+ if (window.scrollY > 50) {
+ navbar.style.background = 'rgba(255, 255, 255, 0.98)';
+ } else {
+ navbar.style.background = 'rgba(255, 255, 255, 0.95)';
+ }
+});
+
+// Intersection Observer for animations
+const observerOptions = {
+ threshold: 0.1,
+ rootMargin: '0px 0px -50px 0px'
+};
+
+const observer = new IntersectionObserver((entries) => {
+ entries.forEach(entry => {
+ if (entry.isIntersecting) {
+ entry.target.style.opacity = '1';
+ entry.target.style.transform = 'translateY(0)';
+ }
+ });
+}, observerOptions);
+
+// Observe blog posts for animation
+document.querySelectorAll('.blog-post').forEach(post => {
+ post.style.opacity = '0';
+ post.style.transform = 'translateY(30px)';
+ post.style.transition = 'opacity 0.6s ease, transform 0.6s ease';
+ observer.observe(post);
+});
+
+// Initialize page
+document.addEventListener('DOMContentLoaded', () => {
+ updatePagination();
+
+ // Add loading animation to hero elements
+ const heroTitle = document.querySelector('.hero-title');
+ const heroSubtitle = document.querySelector('.hero-subtitle');
+ const heroSearch = document.querySelector('.hero-search');
+
+ [heroTitle, heroSubtitle, heroSearch].forEach((element, index) => {
+ if (element) {
+ element.style.opacity = '0';
+ element.style.transform = 'translateY(30px)';
+ element.style.transition = 'opacity 0.8s ease, transform 0.8s ease';
+
+ setTimeout(() => {
+ element.style.opacity = '1';
+ element.style.transform = 'translateY(0)';
+ }, 200 + (index * 200));
+ }
+ });
+});
+
+// Button click handlers
+document.querySelectorAll('.btn').forEach(btn => {
+ btn.addEventListener('click', (e) => {
+ const buttonText = btn.textContent.toLowerCase();
+
+ if (buttonText.includes('trial') || buttonText.includes('start')) {
+ e.preventDefault();
+ showToast('Starting your free trial! Redirecting to registration...', 'success');
+ setTimeout(() => {
+ window.location.href = 'signup.html';
+ }, 2000);
+ }
+ });
+});
+
+// Sidebar sticky behavior enhancement
+window.addEventListener('scroll', () => {
+ const sidebar = document.querySelector('.blog-sidebar');
+ const footer = document.querySelector('.footer');
+
+ if (sidebar && footer) {
+ const sidebarRect = sidebar.getBoundingClientRect();
+ const footerRect = footer.getBoundingClientRect();
+
+ if (footerRect.top < window.innerHeight && sidebarRect.bottom > footerRect.top) {
+ sidebar.style.transform = `translateY(${footerRect.top - sidebarRect.bottom - 20}px)`;
+ } else {
+ sidebar.style.transform = 'translateY(0)';
+ }
+ }
+});