1

Filters

Category
Price
Level
Rating
Duration
Features
Language

Development Courses

Explore courses from experienced, real-world experts.

2 results
Applied filters: Development Clear all filters
React.js Complete Course - Curriculum Outline
Web Development

React.js Complete Course - Curriculum Outline

{ if (input.value === '') { input.checked = true; // Check 'All' options } else { input.checked = false; // Uncheck everything else } }); // Close offcanvas if open const filtersOffcanvas = bootstrap.Offcanvas.getInstance(document.getElementById('filtersOffcanvas')); if (filtersOffcanvas) { filtersOffcanvas.hide(); } // Force PJAX request $.pjax({ container: '#search-results', url: url.toString(), push: false, replace: false, timeout: 10000 }); } // Remove individual filter function removeFilter(filterType, filterValue) { console.log('Removing filter:', filterType, filterValue); // Debug log const url = new URL(window.location); if (filterType === 'features' && filterValue) { // Remove specific feature const features = url.searchParams.getAll('features[]'); const updatedFeatures = features.filter(f => f !== filterValue); url.searchParams.delete('features[]'); updatedFeatures.forEach(f => url.searchParams.append('features[]', f)); // Update checkboxes document.querySelectorAll('input[name="features[]"][value="' + filterValue + '"]').forEach(checkbox => { checkbox.checked = false; }); } else { // Remove other filters url.searchParams.delete(filterType); // Update form inputs to 'All' option document.querySelectorAll('input[name="' + filterType + '"]').forEach(input => { if (input.value === '' || input.value === 'all') { input.checked = true; // Check 'All' option } else { input.checked = false; // Uncheck others } }); } // Force PJAX request $.pjax({ container: '#search-results', url: url.toString(), push: false, replace: false, timeout: 10000 }).done(function() { console.log('Filter removed successfully'); }).fail(function() { console.log('PJAX failed, redirecting normally'); window.location.href = url.toString(); }); } function preventFormSubmission() { // Prevent all forms with data-pjax attribute from normal submission $(document).on('submit', 'form[data-pjax]', function(e) { e.preventDefault(); return false; }); } function initializeFilters() { // Prevent form submissions $(document).off('submit.preventform').on('submit.preventform', 'form[data-pjax]', function(e) { e.preventDefault(); return false; }); // Bind filter change events using event delegation $(document).off('change.filters').on('change.filters', '.filter-checkbox, .filter-radio', function(e) { e.preventDefault(); handleFilterChange(); }); // Bind clear all filter events $(document).off('click.clearfilters').on('click.clearfilters', '#clearAllFiltersBtn, #clearAllFilters, .clear-all-filters, #clearAllFiltersOffcanvas', function(e) { e.preventDefault(); e.stopPropagation(); console.log('Clear all filters clicked'); clearAllFilters(); return false; }); // Bind remove individual filter events - FIXED $(document).off('click.removefilter').on('click.removefilter', '.remove-filter', function(e) { e.preventDefault(); e.stopPropagation(); const filterType = $(this).attr('data-filter') || $(this).data('filter'); const filterValue = $(this).attr('data-value') || $(this).data('value'); console.log('Remove filter button clicked:', filterType, filterValue); removeFilter(filterType, filterValue); return false; }); // Filters button click handler $(document).off('click.filtersbutton').on('click.filtersbutton', '#filtersButton', function(e) { e.preventDefault(); e.stopPropagation(); console.log('Filters button clicked'); return false; }); // Show more/less functionality $(document).off('click.showmore').on('click.showmore', '[data-bs-toggle="collapse"]', function(e) { e.stopPropagation(); const button = $(this); const showMore = button.find('.show-more'); const showLess = button.find('.show-less'); setTimeout(() => { if (showMore.length && showLess.length) { if (showMore.is(':hidden')) { showMore.show(); showLess.hide(); } else { showMore.hide(); showLess.show(); } } }, 100); }); } // Document ready $(document).ready(function() { initializeFilters(); // Debug logging console.log('Search filters initialized'); }); // Reinitialize after PJAX updates $(document).on('pjax:complete', function() { initializeFilters(); console.log('Filters reinitialized after PJAX'); }); // Handle PJAX errors $(document).on('pjax:error', function(xhr, textStatus, error, options) { console.log('PJAX Error:', error); // Fallback to normal page load on error window.location.href = options.url; }); // Additional debugging for button clicks $(document).on('click', 'button', function(e) { console.log('Button clicked:', $(this).attr('id') || $(this).attr('class'), 'Event:', e); }); // Prevent browser back/forward from causing issues $(document).on('pjax:popstate', function() { // Reinitialize filters when user uses browser navigation setTimeout(initializeFilters, 100); }); // Filter change handler let filterTimeout = null; function handleFilterChange() { if (filterTimeout) { clearTimeout(filterTimeout); } filterTimeout = setTimeout(function() { const currentUrl = new URL(window.location.href); const searchQuery = currentUrl.searchParams.get('q') || ''; currentUrl.search = ''; if (searchQuery) { currentUrl.searchParams.set('q', searchQuery); } document.querySelectorAll('.filter-checkbox:checked, .filter-radio:checked').forEach(input => { if (input.value !== '') { if (input.name === 'features[]') { currentUrl.searchParams.append('features[]', input.value); } else { currentUrl.searchParams.set(input.name, input.value); } } }); $.pjax({ container: '#search-results', url: currentUrl.toString(), push: false, replace: false, timeout: 10000 }); }, 300); } // Event listeners document.addEventListener('DOMContentLoaded', function () { // Filter change listeners document.addEventListener('change', function(e) { if (e.target.matches('.filter-checkbox, .filter-radio')) { handleFilterChange(); } }); // Clear all filters buttons document.addEventListener('click', function(e) { if (e.target.matches('#clearAllFilters, .clear-all-filters')) { clearAllFilters(); } // Remove individual filter if (e.target.matches('.remove-filter')) { const filterType = e.target.getAttribute('data-filter'); const filterValue = e.target.getAttribute('data-value'); removeFilter(filterType, filterValue); } }); // Show more/less functionality document.addEventListener('click', function(e) { if (e.target.closest('[data-bs-toggle="collapse"]')) { const button = e.target.closest('[data-bs-toggle="collapse"]'); const showMore = button.querySelector('.show-more'); const showLess = button.querySelector('.show-less'); setTimeout(() => { if (showMore && showLess) { if (showMore.style.display === 'none') { showMore.style.display = 'inline'; showLess.style.display = 'none'; } else { showMore.style.display = 'none'; showLess.style.display = 'inline'; } } }, 100); } }); // Auto-close offcanvas on filter change (optional) document.addEventListener('change', function(e) { if (e.target.matches('.filter-checkbox, .filter-radio')) { // Optionally close after a short delay // setTimeout(() => { // const offcanvas = bootstrap.Offcanvas.getInstance(document.getElementById('filtersOffcanvas')); // if (offcanvas) offcanvas.hide(); // }, 1000); } }); }); class GradSearch { constructor() { this.searchInput = null; this.searchSuggestions = null; this.searchForm = null; this.debounceTimer = null; this.selectedIndex = -1; this.suggestions = []; this.isLoading = false; setTimeout(() => { this.init(); }, 100); } init() { this.searchInput = document.getElementById('search-input'); this.searchSuggestions = document.getElementById('search-suggestions'); this.searchForm = document.getElementById('main-search-form'); if (!this.searchInput || !this.searchSuggestions || !this.searchForm) { console.error('Search elements not found'); return; } console.log('GradSearch initialized'); this.bindEvents(); } bindEvents() { this.searchInput.addEventListener('input', (e) => { this.handleInput(e.target.value); }); this.searchInput.addEventListener('focus', () => { const value = this.searchInput.value.trim(); if (value.length === 0) { this.loadPopularTerms(); } else { this.loadSuggestions(value); } }); document.addEventListener('click', (e) => { if (!this.searchInput.closest('.search-container').contains(e.target)) { this.hideSuggestions(); } }); this.searchInput.addEventListener('keydown', (e) => { this.handleKeydown(e); }); this.searchForm.addEventListener('submit', (e) => { if (this.selectedIndex >= 0) { e.preventDefault(); this.selectSuggestion(this.selectedIndex); } }); } handleInput(value) { clearTimeout(this.debounceTimer); this.selectedIndex = -1; if (value.trim().length === 0) { this.loadPopularTerms(); return; } this.debounceTimer = setTimeout(() => { this.loadSuggestions(value); }, 200); // Faster response for better UX } async loadSuggestions(query) { if (this.isLoading) return; this.isLoading = true; this.showLoadingState(); try { const response = await fetch('/search/suggestions?q=' + encodeURIComponent(query)); if (!response.ok) throw new Error('Network response was not ok'); const data = await response.json(); this.renderSuggestions(data, query); this.showSuggestions(); } catch (error) { console.error('Search error:', error); this.showErrorState(); } finally { this.isLoading = false; } } async loadPopularTerms() { try { const response = await fetch('/search/suggestions'); if (!response.ok) throw new Error('Network response was not ok'); const data = await response.json(); this.renderSuggestions(data, ''); this.showSuggestions(); } catch (error) { console.error('Error loading popular terms:', error); this.showErrorState(); } } showLoadingState() { this.searchSuggestions.innerHTML = '

Searching...
'; this.showSuggestions(); } showErrorState() { this.searchSuggestions.innerHTML = '
Unable to load suggestions
'; } renderSuggestions(data, query) { let html = ''; this.suggestions = []; // Popular searches when no query if (query === '') { if (data.popularTerms && data.popularTerms.length > 0) { html += '
'; html += '
'; html += 'Popular searches'; html += '
'; data.popularTerms.forEach((term) => { html += '
'; html += '
'; html += '' + this.escapeHtml(term) + ''; html += '
'; this.suggestions.push({type: 'keyword', value: term}); }); html += '
'; } if (data.trendingTerms && data.trendingTerms.length > 0) { html += '
'; html += '
'; html += 'Trending searches'; html += '
'; data.trendingTerms.forEach((term) => { html += '
'; html += ''; html += '' + this.escapeHtml(term) + ''; html += '
'; this.suggestions.push({type: 'keyword', value: term}); }); html += '
'; } } // Search suggestions for current query if (query && query.trim().length > 0) { // Search for exact query html += '
'; html += '
'; html += '
'; html += ' "' + this.escapeHtml(query) + '"'; html += '
'; html += '
'; this.suggestions.push({type: 'search', value: query}); // Search suggestions from database if (data.searchSuggestions && data.searchSuggestions.length > 0) { data.searchSuggestions.forEach((suggestion) => { if (suggestion.toLowerCase() !== query.toLowerCase()) { html += '
'; html += '
'; html += '
'; html += '' + this.escapeHtml(suggestion) + ''; html += '
'; html += '
'; this.suggestions.push({type: 'keyword', value: suggestion}); } }); } // Related keywords from database if (data.relatedKeywords && data.relatedKeywords.length > 0) { data.relatedKeywords.forEach((keyword) => { html += '
'; html += '
'; html += '
'; html += '' + this.escapeHtml(keyword) + ''; html += '
'; html += '
'; this.suggestions.push({type: 'keyword', value: keyword}); }); } } // Course suggestions if (data.courses && data.courses.length > 0) { html += '
'; html += '
'; html += 'Courses'; html += '
'; data.courses.forEach((course) => { html += '
'; if (course.thumbnail) { html += '' + this.escapeHtml(course.title) + ''; } else { html += '
'; html += ''; html += '
'; } html += '
'; html += '
' + this.escapeHtml(course.title) + '
'; html += '
'; html += this.escapeHtml(course.instructor); if (course.average_rating > 0) { html += ' • ' + course.average_rating + ' '; } if (course.price > 0) { if (course.discount_price > 0) { html += ' • $' + course.discount_price; } else { html += ' • $' + course.price; } } else { html += ' • Free'; } html += '
'; html += '
'; html += '
'; this.suggestions.push({type: 'course', value: course.url}); }); html += '
'; } if (query && this.suggestions.length === 1) { html += '
No suggestions found for "' + this.escapeHtml(query) + '"
'; } this.searchSuggestions.innerHTML = html; this.attachClickHandlers(); } attachClickHandlers() { this.searchSuggestions.querySelectorAll('[data-index]').forEach((item) => { item.addEventListener('click', (e) => { e.preventDefault(); e.stopPropagation(); const index = parseInt(e.currentTarget.getAttribute('data-index')); this.selectSuggestion(index); }); }); } selectSuggestion(index) { if (index < 0 || index >= this.suggestions.length) return; const suggestion = this.suggestions[index]; if (suggestion.type === 'keyword' || suggestion.type === 'search') { this.searchInput.value = suggestion.value; this.hideSuggestions(); this.searchForm.submit(); } else if (suggestion.type === 'course') { window.location.href = suggestion.value; } } showSuggestions() { this.searchSuggestions.classList.add('show'); } hideSuggestions() { this.searchSuggestions.classList.remove('show'); this.selectedIndex = -1; this.updateSelection(); } handleKeydown(e) { if (!this.searchSuggestions.classList.contains('show')) { return; } switch (e.key) { case 'ArrowDown': e.preventDefault(); this.selectedIndex = Math.min(this.selectedIndex + 1, this.suggestions.length - 1); this.updateSelection(); break; case 'ArrowUp': e.preventDefault(); this.selectedIndex = Math.max(this.selectedIndex - 1, -1); this.updateSelection(); break; case 'Enter': if (this.selectedIndex >= 0) { e.preventDefault(); this.selectSuggestion(this.selectedIndex); } break; case 'Escape': this.hideSuggestions(); this.searchInput.blur(); break; } } updateSelection() { this.searchSuggestions.querySelectorAll('.suggestion-item, .course-suggestion').forEach(item => { item.classList.remove('active'); }); if (this.selectedIndex >= 0) { const selectedItem = this.searchSuggestions.querySelector('[data-index="' + this.selectedIndex + '"]'); if (selectedItem) { selectedItem.classList.add('active'); selectedItem.scrollIntoView({block: 'nearest', behavior: 'smooth'}); } } } escapeHtml(text) { if (!text) return ''; const div = document.createElement('div'); div.textContent = text; return div.innerHTML; } } if (document.readyState === 'loading') { document.addEventListener('DOMContentLoaded', function() { window.gradSearch = new GradSearch(); }); } else { window.gradSearch = new GradSearch(); } document.addEventListener('DOMContentLoaded', function() { // Mobile submenu functionality const submenuToggles = document.querySelectorAll('[data-bs-toggle="submenu"]'); submenuToggles.forEach(function(toggle) { toggle.addEventListener('click', function() { const submenu = this.nextElementSibling; const isOpen = submenu && submenu.classList.contains('open'); const toggleIcon = this.querySelector('.menu-toggle-icon'); // Close all other submenus document.querySelectorAll('.submenu').forEach(function(menu) { menu.classList.remove('open'); }); document.querySelectorAll('[data-bs-toggle="submenu"]').forEach(function(otherToggle) { otherToggle.classList.remove('expanded'); otherToggle.classList.add('collapsed'); const otherIcon = otherToggle.querySelector('.menu-toggle-icon'); if (otherIcon) { otherIcon.classList.remove('fa-rotate-90'); } }); // Toggle current submenu if (!isOpen && submenu) { submenu.classList.add('open'); this.classList.add('expanded'); this.classList.remove('collapsed'); if (toggleIcon) { toggleIcon.classList.add('fa-rotate-90'); } } }); }); }); document.addEventListener('DOMContentLoaded', function() { const popoverTrigger = document.getElementById('popover-target'); if (!popoverTrigger) { return; // Exit silently if element doesn't exist } const popover = new bootstrap.Popover(popoverTrigger, { container: 'body', trigger: 'manual', html: true }); let hideTimeout; popoverTrigger.addEventListener('mouseenter', function() { popover.show(); const popoverId = popoverTrigger.getAttribute('aria-describedby'); const popoverEl = document.getElementById(popoverId); if (popoverEl) { popoverEl.addEventListener('mouseenter', function() { clearTimeout(hideTimeout); }); popoverEl.addEventListener('mouseleave', function() { hideTimeout = setTimeout(function() { popover.hide(); }, 200); }); } }); popoverTrigger.addEventListener('mouseleave', function() { hideTimeout = setTimeout(function() { popover.hide(); }, 200); }); });