{% extends "base.html" %} {% block title %}Advanced Orchid Search - Orchid Continuum{% endblock %} {% block content %}

Advanced Orchid Search

Professional botanical search with comprehensive filtering capabilities

{% if search_stats %}
{{ search_stats.total_found }} Total Found {{ search_stats.has_images }} With Images {{ search_stats.species_count }} Species {{ search_stats.hybrid_count }} Hybrids {{ search_stats.flowering_count }} Currently Flowering {% if search_stats.featured_count %} {{ search_stats.featured_count }} Featured {% endif %}
{% endif %}
Quick Actions:
External Database Search

Search global biodiversity databases for comprehensive orchid information from EOL.org and GBIF.

External Database Results 0
Ready to search external databases...
NEW: Biological Analysis Filters

Advanced biological search capabilities powered by AI analysis, trait discovery, and ecological relationships.

Taxonomic Classification
Geographic Distribution
Breeding & Parentage
Flowering Characteristics
Growing Requirements
Plant Morphology
Conservation & Identification Status
System & Media Filters
{% if query or genus or country or orchid_type %} Reset Search {% endif %}
{% if query or genus or country or orchid_type or flowering_status %}
Comprehensive search across {{ search_stats.total_found or 'all' }} orchid records including names, descriptions, locations, parentage, morphology, and cultural information
{% endif %}
{% if search_stats.total_found > 0 and (orchid_coordinates or regional_distribution) %}
Geographic Distribution of Search Results
{{ mapping_stats.total_with_coordinates }}
With Precise Coordinates
{{ mapping_stats.total_regions }}
Different Regions
{{ "%.1f"|format(mapping_stats.coordinate_coverage) }}%
Coordinate Coverage
{% if regional_distribution %}
Regional Distribution
{% for region, data in regional_distribution.items() %}
{{ region }}
{{ data.count }} orchids
{{ data.genera }} genera
{{ data.species }} species
{% if data.flowering > 0 %}
{{ data.flowering }} flowering
{% endif %}
{% endfor %}
{% else %}
No regional distribution data available for current search results.
{% endif %}
Quick Geographic Filters
{% for country in filter_options.countries[:8] %} {{ country }} {% endfor %}
{% endif %} {% if filter_options %}
AI-Generated Insights
Trait Discovery & Inheritance
Pollinator Relationships
Mycorrhizal Associations
Ecological Interactions
Advanced Morphological Traits
Behavioral Mechanisms
Advanced Conservation Status
{% endif %} {% if orchids is defined and (query or genus or species or country or region or orchid_type or flowering_status or growth_habit or climate_preference or has_image or is_featured) %}

{% if query %} Search Results for "{{ query }}" {% else %} Filtered Search Results {% endif %}

{% if orchids %} Export View on Globe {% endif %}
{% if search_stats %}
Search Statistics:
{{ search_stats.total_found }} total orchids found
{{ search_stats.has_images }} with high-quality images
Composition:
{{ search_stats.species_count }} species, {{ search_stats.hybrid_count }} hybrids
{{ search_stats.flowering_count }} currently flowering
{% endif %}
{% if orchids %}
{% for orchid in orchids %}
{% if orchid.google_drive_id or orchid.image_url or orchid.image_filename %} {% set image_url = '/api/drive-photo/' + orchid.google_drive_id if orchid.google_drive_id else orchid.image_url %}
{{ orchid.display_name }}
{% if orchid.decimal_latitude and orchid.decimal_longitude %}
{% endif %}
{% else %}
{% endif %}
{{ orchid.display_name }}
{% if orchid.scientific_name and orchid.scientific_name != orchid.display_name %}

{{ orchid.scientific_name }}

{% endif %}
{% if orchid.genus %} {{ orchid.genus }} {% endif %} {% if orchid.is_species %} Species {% elif orchid.is_hybrid %} Hybrid {% endif %} {% if orchid.is_flowering %} 🌸 Flowering {% endif %} {% if orchid.climate_preference %} {{ orchid.climate_preference|title }} {% endif %} {% if orchid.is_featured %} ⭐ Featured {% endif %}
{% if orchid.country or orchid.region %}
{% if orchid.country %}{{ orchid.country }}{% endif %}{% if orchid.country and orchid.region %}, {% endif %}{% if orchid.region %}{{ orchid.region }}{% endif %}
{% endif %} {% if orchid.pod_parent and orchid.pollen_parent %}
{{ orchid.pod_parent }} Γ— {{ orchid.pollen_parent }}
{% endif %} {% if orchid.ai_description %}

{{ orchid.ai_description[:80] }}{% if orchid.ai_description|length > 80 %}...{% endif %}

{% elif orchid.cultural_notes %}

{{ orchid.cultural_notes[:80] }}{% if orchid.cultural_notes|length > 80 %}...{% endif %}

{% endif %}
View Details
{{ orchid.view_count or 0 }}
{% endfor %}
{% if orchids|length >= results_per_page %}
Showing {{ orchids|length }} results. For better performance, consider using more specific filters to narrow your search.
{% else %} Showing all {{ orchids|length }} matching results {% endif %}
{% else %}

No orchids found with current filters

Try adjusting your search criteria or clearing some filters.

Browse Gallery
{% endif %} {% else %}

Professional Orchid Search

By Genus

Search popular orchid genera

{% for genus in filter_options.genera[:6] %} {{ genus }} {% endfor %}
By Location

Find orchids by origin

{% for country in filter_options.countries[:6] %} {{ country }} {% endfor %}
Species vs Hybrids

Browse by type

Special Features

Featured & flowering

Advanced Search Capabilities
What you can search:
  • Scientific names, common names, authors
  • Geographic locations and native habitats
  • Parentage information and breeding data
  • Flowering characteristics and bloom seasons
  • Growing requirements and cultural notes
  • Plant morphology and physical characteristics
Advanced features:
  • Multi-field comprehensive text search
  • Conservation status and identification tracking
  • RHS registration and verification status
  • Image availability and photographer credits
  • Multiple sorting options and result export
  • Integration with mapping and conservation systems
{% endif %}
// Toggle between regional and coordinate map views function toggleMapView(viewType) { const regionalView = document.getElementById('regional-view'); const coordinatesView = document.getElementById('coordinates-view'); const regionalBtn = document.getElementById('regional-btn'); const coordinatesBtn = document.getElementById('coordinates-btn'); // Reset button states regionalBtn.classList.remove('active'); coordinatesBtn.classList.remove('active'); if (viewType === 'regional') { regionalView.style.display = 'block'; coordinatesView.style.display = 'none'; regionalBtn.classList.add('active'); } else if (viewType === 'coordinates') { regionalView.style.display = 'none'; coordinatesView.style.display = 'block'; coordinatesBtn.classList.add('active'); // Initialize coordinate map if not already done initializeCoordinateMap(); } feather.replace(); } // Initialize interactive coordinate map function initializeCoordinateMap() { if (searchMap || !window.L) { return; // Map already exists or Leaflet not loaded } const mapContainer = document.getElementById('search-map'); if (!mapContainer) return; // Initialize map searchMap = L.map('search-map').setView([20, 0], 2); // Add tile layer L.tileLayer('https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', { attribution: 'Β© OpenStreetMap contributors' }).addTo(searchMap); // Add orchid coordinates if available {% if orchid_coordinates %} const orchidCoordinates = {{ orchid_coordinates|tojson }}; orchidCoordinates.forEach(coord => { const marker = L.marker([coord.lat, coord.lng]) .addTo(searchMap) .bindPopup(`
${coord.name}
Genus: ${coord.genus}
Location: ${coord.location}
Region: ${coord.region}
View Details
`); currentMapMarkers.push(marker); }); // Fit map to show all markers if (currentMapMarkers.length > 0) { const group = new L.featureGroup(currentMapMarkers); searchMap.fitBounds(group.getBounds().pad(0.1)); } {% endif %} } // Focus map on specific orchid coordinates function focusOnOrchid(lat, lng) { if (searchMap) { searchMap.setView([lat, lng], 8); // Find and open popup for this coordinate currentMapMarkers.forEach(marker => { const pos = marker.getLatLng(); if (Math.abs(pos.lat - lat) < 0.001 && Math.abs(pos.lng - lng) < 0.001) { marker.openPopup(); } }); } } // Show all coordinates in expanded view function showAllCoordinates() { toggleMapView('coordinates'); if (searchMap && currentMapMarkers.length > 0) { const group = new L.featureGroup(currentMapMarkers); searchMap.fitBounds(group.getBounds().pad(0.1)); } } // Filter search results by region function filterByRegion(region) { const form = document.getElementById('searchForm'); const regionInput = form.querySelector('input[name="region"]'); if (regionInput) { regionInput.value = region; } else { // Create hidden input for region filter const hiddenInput = document.createElement('input'); hiddenInput.type = 'hidden'; hiddenInput.name = 'region'; hiddenInput.value = region; form.appendChild(hiddenInput); } form.submit(); } // Open 3D Globe view with current search filters function openGlobeView() { const form = document.getElementById('searchForm'); const formData = new FormData(form); const params = new URLSearchParams(formData); // Build URL with search parameters for 3D globe let globeUrl = '/space-earth-globe'; // Add genus filter if specified const genus = params.get('genus'); if (genus && genus !== '') { globeUrl += '?genus=' + encodeURIComponent(genus); } // Open 3D globe in new window/tab window.open(globeUrl, '_blank', 'width=1200,height=800'); } // Enhanced image gallery viewing function openImageGallery(orchidId, imageSrc, orchidName) { // Create modal for full-size image viewing const modal = document.createElement('div'); modal.className = 'modal fade'; modal.id = 'imageGalleryModal'; modal.innerHTML = ` `; document.body.appendChild(modal); const bsModal = new bootstrap.Modal(modal); bsModal.show(); // Clean up modal after hiding modal.addEventListener('hidden.bs.modal', function() { document.body.removeChild(modal); }); } // Auto-submit on some filter changes for better UX document.addEventListener('DOMContentLoaded', function() { const autoSubmitSelects = ['genus', 'country', 'orchid_type', 'flowering_status', 'sort_by']; autoSubmitSelects.forEach(id => { const select = document.getElementById(id); if (select) { select.addEventListener('change', function() { // Optional: Add a small delay for better UX setTimeout(() => { document.getElementById('searchForm').submit(); }, 100); }); } }); // Initialize mapping functionality {% if search_stats.total_found > 0 and (orchid_coordinates or regional_distribution) %} // Set default map view to regional toggleMapView('regional'); // Load Leaflet CSS and JS for coordinate maps if (!window.L) { const leafletCSS = document.createElement('link'); leafletCSS.rel = 'stylesheet'; leafletCSS.href = 'https://unpkg.com/leaflet@1.7.1/dist/leaflet.css'; document.head.appendChild(leafletCSS); const leafletJS = document.createElement('script'); leafletJS.src = 'https://unpkg.com/leaflet@1.7.1/dist/leaflet.js'; leafletJS.onload = function() { console.log('πŸ—ΊοΈ Leaflet loaded for search maps'); }; document.head.appendChild(leafletJS); } {% endif %} // Initialize feather icons feather.replace(); // Initialize AI Chat initializeSearchAIChat(); }); // Quick Filter Functions for Enhanced Dropdowns function quickFilter(filterType, filterValue) { console.log(`πŸ” Quick filter applied: ${filterType} = ${filterValue}`); // Get current URL parameters const urlParams = new URLSearchParams(window.location.search); // Apply the quick filter based on type switch(filterType) { case 'genus': urlParams.set('genus', filterValue); break; case 'type': if (filterValue === 'species') { urlParams.set('orchid_type', 'species'); urlParams.delete('is_hybrid'); } else if (filterValue === 'hybrids') { urlParams.set('is_hybrid', 'true'); urlParams.delete('orchid_type'); } else if (filterValue === 'primary_hybrids') { urlParams.set('is_hybrid', 'true'); urlParams.set('parentage_type', 'primary'); } break; case 'region': urlParams.set('region', filterValue); break; case 'climate': urlParams.set('habitat_type', filterValue); break; case 'parentage': if (filterValue === 'known_parents') { urlParams.set('has_parentage', 'true'); } else if (filterValue === 'awarded_parents') { urlParams.set('parent_awards', 'true'); } else if (filterValue === 'species_cross') { urlParams.set('parentage_type', 'species_cross'); } break; case 'generation': urlParams.set('generation', filterValue); break; case 'bloom_season': urlParams.set('flowering_season', filterValue); break; case 'flowering': if (filterValue === 'currently') { urlParams.set('flowering_status', 'currently_flowering'); } break; case 'flower_size': if (filterValue === 'large') { urlParams.set('min_flower_size', '10'); } else if (filterValue === 'small') { urlParams.set('max_flower_size', '3'); } break; case 'fragrance': if (filterValue === 'fragrant') { urlParams.set('fragrant', 'true'); } break; case 'difficulty': urlParams.set('care_difficulty', filterValue); break; case 'medium': urlParams.set('growing_medium', filterValue); break; case 'light': urlParams.set('light_requirements', filterValue); break; case 'growth': urlParams.set('growth_habit', filterValue); break; case 'pattern': urlParams.set('growth_pattern', filterValue); break; case 'size': urlParams.set('plant_size', filterValue); break; case 'cites': urlParams.set('cites_appendix', filterValue); break; case 'status': urlParams.set('conservation_status', filterValue); break; case 'rarity': urlParams.set('rarity_level', filterValue); break; case 'source': urlParams.set('ingestion_source', filterValue); break; case 'quality': if (filterValue === 'with_images') { urlParams.set('has_images', 'true'); } else if (filterValue === 'with_coordinates') { urlParams.set('has_coordinates', 'true'); } else if (filterValue === 'validated') { urlParams.set('validation_status', 'validated'); } else if (filterValue === 'featured') { urlParams.set('is_featured', 'true'); } break; case 'recent': const days = filterValue === 'week' ? 7 : 30; const dateThreshold = new Date(); dateThreshold.setDate(dateThreshold.getDate() - days); urlParams.set('created_after', dateThreshold.toISOString().split('T')[0]); break; } // Redirect to apply the filter window.location.search = urlParams.toString(); } // Nursery Directory Toggle function toggleNurseryDirectory() { // Check if nursery directory panel exists let nurseryPanel = document.getElementById('nurseryDirectoryPanel'); if (!nurseryPanel) { // Create nursery directory panel nurseryPanel = createNurseryDirectoryPanel(); document.querySelector('.container').appendChild(nurseryPanel); } // Toggle visibility const isVisible = nurseryPanel.style.display !== 'none'; nurseryPanel.style.display = isVisible ? 'none' : 'block'; if (!isVisible) { // Load nursery data loadNurseryData(); nurseryPanel.scrollIntoView({ behavior: 'smooth' }); } } // Orchid Society Directory Toggle function toggleSocietyDirectory() { // Check if society directory panel exists let societyPanel = document.getElementById('societyDirectoryPanel'); if (!societyPanel) { // Create society directory panel societyPanel = createSocietyDirectoryPanel(); document.querySelector('.container').appendChild(societyPanel); } // Toggle visibility const isVisible = societyPanel.style.display !== 'none'; societyPanel.style.display = isVisible ? 'none' : 'block'; if (!isVisible) { // Load society data loadSocietyData(); societyPanel.scrollIntoView({ behavior: 'smooth' }); } } // Create Nursery Directory Panel function createNurseryDirectoryPanel() { const panel = document.createElement('div'); panel.id = 'nurseryDirectoryPanel'; panel.className = 'card border-0 shadow-sm mt-4'; panel.style.display = 'none'; panel.innerHTML = `
Orchid Nursery Directory
Loading nurseries...
`; return panel; } // Create Society Directory Panel function createSocietyDirectoryPanel() { const panel = document.createElement('div'); panel.id = 'societyDirectoryPanel'; panel.className = 'card border-0 shadow-sm mt-4'; panel.style.display = 'none'; panel.innerHTML = `
Orchid Society Directory
Loading societies...
`; return panel; } // Export Search Results function exportSearchResults() { const currentUrl = new URL(window.location); const exportUrl = '/api/export-search-results' + currentUrl.search; // Open export URL in new tab window.open(exportUrl, '_blank'); } // Load Nursery Data (placeholder - will be implemented with actual API) async function loadNurseryData() { try { const response = await fetch('/api/nursery-directory'); const data = await response.json(); const resultsDiv = document.getElementById('nurseryResults'); if (data.nurseries && data.nurseries.length > 0) { resultsDiv.innerHTML = data.nurseries.map(nursery => `
${nursery.name}

${nursery.location}
Specialty: ${nursery.specialty || 'General'}

${nursery.website ? `Website` : ''} ${nursery.phone ? `Call` : ''}
`).join(''); } else { resultsDiv.innerHTML = '
No nurseries found. API coming soon!
'; } } catch (error) { console.error('Error loading nursery data:', error); document.getElementById('nurseryResults').innerHTML = `
Nursery Directory Coming Soon!

We're building a comprehensive directory of orchid nurseries worldwide. This feature will include:

`; } } // Load Society Data (placeholder - will be implemented with actual API) async function loadSocietyData() { try { const response = await fetch('/api/society-directory'); const data = await response.json(); const resultsDiv = document.getElementById('societyResults'); if (data.societies && data.societies.length > 0) { resultsDiv.innerHTML = data.societies.map(society => `
${society.name}

${society.location}
Type: ${society.type || 'Local Society'}

${society.website ? `Website` : ''} ${society.email ? `Contact` : ''}
`).join(''); } else { resultsDiv.innerHTML = '
No societies found. API coming soon!
'; } } catch (error) { console.error('Error loading society data:', error); document.getElementById('societyResults').innerHTML = `
Orchid Society Directory Coming Soon!

We're building a comprehensive directory of orchid societies worldwide. This feature will include:

`; } } // AI Search Chat Functionality function initializeSearchAIChat() { let chatHistory = []; let isChatOpen = false; // Create chat elements createChatElements(); // Chat interface removed - event listeners cleaned up function createChatElements() { // Chat elements are created in HTML template - just initialize const chatWindow = document.getElementById('aiChatWindow'); const chatToggle = document.getElementById('chatToggle'); // Initially hidden chatWindow.style.display = 'none'; } function toggleChat() { const chatWindow = document.getElementById('aiChatWindow'); const chatToggle = document.getElementById('chatToggle'); isChatOpen = !isChatOpen; if (isChatOpen) { chatWindow.style.display = 'block'; chatToggle.style.display = 'none'; // Welcome message if first time opening if (chatHistory.length === 0) { addMessage('assistant', "πŸ‘‹ Hi! I'm your AI search assistant. I can help you refine your search, identify orchids, explain biological features, and guide your botanical research. What would you like to know?"); } } else { chatWindow.style.display = 'none'; chatToggle.style.display = 'block'; } } function sendMessage() { const input = document.getElementById('chatInput'); const message = input.value.trim(); if (!message) return; // Add user message to chat addMessage('user', message); input.value = ''; // Show loading indicator showTypingIndicator(); // Get current search context const searchContext = getCurrentSearchContext(); // Send to AI fetch('/api/chat-search-assist', { method: 'POST', headers: { 'Content-Type': 'application/json', }, body: JSON.stringify({ message: message, search_context: searchContext }) }) .then(response => response.json()) .then(data => { hideTypingIndicator(); if (data.success) { addMessage('assistant', data.response); // Apply suggested actions if any if (data.suggested_actions && data.suggested_actions.length > 0) { applySuggestedActions(data.suggested_actions); } } else { addMessage('assistant', data.fallback_response || 'Sorry, I\'m having trouble right now. Please try again.'); } }) .catch(error => { hideTypingIndicator(); console.error('Chat error:', error); addMessage('assistant', 'I apologize, but I\'m experiencing technical difficulties. Please try again in a moment.'); }); } function addMessage(sender, text) { const messagesContainer = document.getElementById('chatMessages'); const messageDiv = document.createElement('div'); messageDiv.className = `chat-message ${sender}-message`; const timestamp = new Date().toLocaleTimeString([], {hour: '2-digit', minute:'2-digit'}); messageDiv.innerHTML = `
${text}
${timestamp}
`; messagesContainer.appendChild(messageDiv); messagesContainer.scrollTop = messagesContainer.scrollHeight; chatHistory.push({sender, text, timestamp}); } function showTypingIndicator() { const messagesContainer = document.getElementById('chatMessages'); const typingDiv = document.createElement('div'); typingDiv.id = 'typingIndicator'; typingDiv.className = 'chat-message assistant-message typing'; typingDiv.innerHTML = `
`; messagesContainer.appendChild(typingDiv); messagesContainer.scrollTop = messagesContainer.scrollHeight; } function hideTypingIndicator() { const typingIndicator = document.getElementById('typingIndicator'); if (typingIndicator) { typingIndicator.remove(); } } function getCurrentSearchContext() { // Extract current search filters from the form const form = document.getElementById('searchForm'); const formData = new FormData(form); const context = {}; for (let [key, value] of formData.entries()) { if (value && value.trim()) { context[key] = value.trim(); } } return context; } function applySuggestedActions(actions) { actions.forEach(action => { if (action.type === 'filter') { const field = document.getElementById(action.field); if (field) { field.value = action.value; addMessage('assistant', `🎯 I've applied the ${action.field} filter: ${action.value}. Click Search to update results.`); } } else if (action.type === 'search') { const searchField = document.querySelector('input[name="q"]'); if (searchField) { searchField.value = action.query; addMessage('assistant', `πŸ” I've updated your search query to: "${action.query}". Click Search to find results.`); } } }); } // Load and display image counts on page load async function loadImageCounts() { try { console.log('πŸ“Š Loading image counts...'); const response = await fetch('/api/image-counts'); const data = await response.json(); if (data.success) { console.log('βœ… Image counts loaded:', data); // Update genus counts const genusCounts = data.genus_counts; document.querySelectorAll('.genus-count').forEach(element => { const genus = element.getAttribute('data-genus'); const count = genusCounts[genus] || 0; element.textContent = count > 0 ? count : '0'; // Apply color coding based on count element.className = element.className.replace(/bg-\w+/, ''); if (count > 50) { element.classList.add('bg-success'); } else if (count > 10) { element.classList.add('bg-primary'); } else if (count > 0) { element.classList.add('bg-secondary'); } else { element.classList.add('bg-light', 'text-dark'); } }); // Update type counts const typeCounts = data.type_counts; const speciesElement = document.getElementById('species-count'); const hybridsElement = document.getElementById('hybrids-count'); const primaryHybridsElement = document.getElementById('primary-hybrids-count'); if (speciesElement) { speciesElement.textContent = typeCounts.species || 0; } if (hybridsElement) { hybridsElement.textContent = typeCounts.hybrids || 0; } if (primaryHybridsElement) { primaryHybridsElement.textContent = typeCounts.primary_hybrids || 0; } // Update total count in search stats if present const totalWithImages = data.total_with_images; console.log(`πŸ“Š Total images found: ${totalWithImages}`); // Store counts for caching window.orchidImageCounts = data; } else { console.error('❌ Failed to load image counts:', data.error); // Set all counts to "?" on error document.querySelectorAll('.genus-count, #species-count, #hybrids-count, #primary-hybrids-count').forEach(element => { element.textContent = '?'; }); } } catch (error) { console.error('❌ Error loading image counts:', error); // Set all counts to "?" on error document.querySelectorAll('.genus-count, #species-count, #hybrids-count, #primary-hybrids-count').forEach(element => { element.textContent = '?'; }); } } // Load counts when page loads document.addEventListener('DOMContentLoaded', function() { // Load image counts after a brief delay to ensure page is fully rendered setTimeout(loadImageCounts, 100); }); } {% endblock %}