File size: 6,283 Bytes
948605a 323ad41 948605a 323ad41 948605a |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
// Main application state
let allProjects = [];
let filteredProjects = [];
let currentPlatformFilter = 'all';
let currentUsecaseFilter = 'all';
let currentSearchQuery = '';
let currentSort = 'name';
// Load projects data
async function loadProjects() {
try {
const response = await fetch('projects.json');
allProjects = await response.json();
filteredProjects = [...allProjects];
renderProjects();
updateProjectCount();
} catch (error) {
console.error('Error loading projects:', error);
document.getElementById('projects-grid').innerHTML = `
<div class="no-results">
<h3>Error loading projects</h3>
<p>Unable to load the projects data. Please try refreshing the page.</p>
</div>
`;
}
}
// Apply all filters
function applyFilters() {
filteredProjects = allProjects.filter(project => {
// Platform filter
const platformMatch = currentPlatformFilter === 'all' ||
project.platforms.includes(currentPlatformFilter);
// Use case filter
const usecaseMatch = currentUsecaseFilter === 'all' ||
project.usecases.includes(currentUsecaseFilter);
// Search query
const searchMatch = currentSearchQuery === '' ||
project.name.toLowerCase().includes(currentSearchQuery.toLowerCase()) ||
project.description.toLowerCase().includes(currentSearchQuery.toLowerCase());
return platformMatch && usecaseMatch && searchMatch;
});
sortProjects();
renderProjects();
updateProjectCount();
}
// Sort projects
function sortProjects() {
switch (currentSort) {
case 'name':
filteredProjects.sort((a, b) => a.name.localeCompare(b.name));
break;
case 'platform':
filteredProjects.sort((a, b) => {
const platformA = a.platforms[0] || '';
const platformB = b.platforms[0] || '';
return platformA.localeCompare(platformB);
});
break;
case 'usecase':
filteredProjects.sort((a, b) => {
const usecaseA = a.usecases[0] || '';
const usecaseB = b.usecases[0] || '';
return usecaseA.localeCompare(usecaseB);
});
break;
}
}
// Render projects to the grid
function renderProjects() {
const grid = document.getElementById('projects-grid');
if (filteredProjects.length === 0) {
grid.innerHTML = `
<div class="no-results">
<h3>No projects found</h3>
<p>Try adjusting your filters or search query.</p>
</div>
`;
return;
}
grid.innerHTML = filteredProjects.map(project => createProjectCard(project)).join('');
}
// Create a project card HTML
function createProjectCard(project) {
const platformTags = project.platforms
.map(p => `<span class="meta-tag platform-tag">${formatTag(p)}</span>`)
.join('');
const usecaseTags = project.usecases
.map(u => `<span class="meta-tag usecase-tag">${formatTag(u)}</span>`)
.join('');
const starBadge = project.github_repo
? `<img src="https://img.shields.io/github/stars/${project.github_repo}?style=flat-square" alt="GitHub stars" class="github-stars-badge">`
: '';
return `
<div class="project-card">
<h3>
<a href="${project.url}" target="_blank" rel="noopener">${escapeHtml(project.name)}</a>
${starBadge}
</h3>
<p class="project-description">${escapeHtml(project.description)}</p>
<div class="project-meta">
${platformTags}
${usecaseTags}
</div>
</div>
`;
}
// Format tag names for display
function formatTag(tag) {
return tag
.split('-')
.map(word => word.charAt(0).toUpperCase() + word.slice(1))
.join(' ');
}
// Escape HTML to prevent XSS
function escapeHtml(text) {
const div = document.createElement('div');
div.textContent = text;
return div.innerHTML;
}
// Update project count display
function updateProjectCount() {
const count = document.getElementById('project-count');
count.textContent = `(${filteredProjects.length} of ${allProjects.length})`;
}
// Set up event listeners
function setupEventListeners() {
// Platform filter buttons
document.querySelectorAll('#platform-filters .filter-btn').forEach(btn => {
btn.addEventListener('click', () => {
// Remove active class from all platform buttons
document.querySelectorAll('#platform-filters .filter-btn').forEach(b => {
b.classList.remove('active');
});
// Add active class to clicked button
btn.classList.add('active');
// Update filter
currentPlatformFilter = btn.dataset.filter;
applyFilters();
});
});
// Use case filter buttons
document.querySelectorAll('#usecase-filters .filter-btn').forEach(btn => {
btn.addEventListener('click', () => {
// Remove active class from all usecase buttons
document.querySelectorAll('#usecase-filters .filter-btn').forEach(b => {
b.classList.remove('active');
});
// Add active class to clicked button
btn.classList.add('active');
// Update filter
currentUsecaseFilter = btn.dataset.filter;
applyFilters();
});
});
// Search input
const searchInput = document.getElementById('search-input');
searchInput.addEventListener('input', (e) => {
currentSearchQuery = e.target.value;
applyFilters();
});
// Sort select
const sortSelect = document.getElementById('sort-select');
sortSelect.addEventListener('change', (e) => {
currentSort = e.target.value;
sortProjects();
renderProjects();
});
}
// Initialize the application
document.addEventListener('DOMContentLoaded', () => {
setupEventListeners();
loadProjects();
});
|