orchestrions.html

October 18, 2025 ยท View on GitHub

Historic Orchestrions Around the World

Historic Orchestrions Around the World

A collection of rare and remarkable mechanical orchestras

    <div id="loading" class="loading">Loading orchestrions...</div>
    <div id="error" style="display: none;"></div>
    <div id="orchestrions" class="locations-container"></div>

    <footer>
        <p>Data compiled from museum archives and historical records</p>
    </footer>
</div>

<script>
    async function loadOrchestrions() {
        try {
            const response = await fetch('https://gist.githubusercontent.com/simonw/2a0b26633802149a44e15cf1cd396f86/raw/836dde6b9b9452ac797d98b403872034f7536c9d/orchestrions.json');
            if (!response.ok) {
                throw new Error(`HTTP error! status: ${response.status}`);
            }
            const data = await response.json();
            displayOrchestrions(data);
        } catch (error) {
            document.getElementById('loading').style.display = 'none';
            const errorDiv = document.getElementById('error');
            errorDiv.style.display = 'block';
            errorDiv.className = 'error';
            errorDiv.textContent = `Error loading data: ${error.message}`;
        }
    }

    function displayOrchestrions(orchestrions) {
        document.getElementById('loading').style.display = 'none';

        // Group orchestrions by venue
        const grouped = {};
        orchestrions.forEach(orch => {
            const key = `${orch.venue}|${orch.city}|${orch.country}|${orch.latitude}|${orch.longitude}`;
            if (!grouped[key]) {
                grouped[key] = {
                    venue: orch.venue,
                    city: orch.city,
                    country: orch.country,
                    latitude: orch.latitude,
                    longitude: orch.longitude,
                    orchestrions: []
                };
            }
            grouped[key].orchestrions.push(orch);
        });

        const locations = Object.values(grouped);

        // Display statistics
        const countries = new Set(orchestrions.map(o => o.country));
        const statsHtml = `
            <div class="stat"><strong>${orchestrions.length}</strong> Orchestrions</div>
            <div class="stat"><strong>${locations.length}</strong> Locations</div>
            <div class="stat"><strong>${countries.size}</strong> Countries</div>
        `;
        document.getElementById('stats').innerHTML = statsHtml;

        // Display locations and orchestrions
        const container = document.getElementById('orchestrions');
        container.innerHTML = locations.map(location => {
            const googleMapsUrl = `https://www.google.com/maps?q=${location.latitude},${location.longitude}`;
            const count = location.orchestrions.length;

            return `
                <div class="location-group">
                    <div class="location-header">
                        <div class="venue-name">
                            ${escapeHtml(location.venue)}
                            ${count > 1 ? `<span class="orchestrion-count">${count} orchestrions</span>` : ''}
                        </div>
                        <div class="location">
                            <span class="location-icon">๐Ÿ“</span>
                            <span>${escapeHtml(location.city)}, ${escapeHtml(location.country)}</span>
                        </div>
                        <a href="${googleMapsUrl}" target="_blank" rel="noopener" class="map-link">
                            View on Google Maps โ†’
                        </a>
                    </div>

                    <div class="orchestrions-list">
                        ${location.orchestrions.map((orch, idx) => `
                            <div class="card">
                                ${count > 1 ? `
                                    <div class="card-header">
                                        <div class="orchestrion-title">Orchestrion ${idx + 1}</div>
                                    </div>
                                ` : ''}

                                ${orch.description ? `
                                    <div class="section">
                                        <div class="section-title">Description</div>
                                        <div class="section-content">${formatText(orch.description)}</div>
                                    </div>
                                ` : ''}

                                ${orch.history ? `
                                    <div class="section">
                                        <div class="section-title">History</div>
                                        <div class="section-content">${formatText(orch.history)}</div>
                                    </div>
                                ` : ''}

                                ${orch.notes ? `
                                    <div class="section">
                                        <div class="section-title">Notes</div>
                                        <div class="section-content">${formatText(orch.notes)}</div>
                                    </div>
                                ` : ''}
                            </div>
                        `).join('')}
                    </div>
                </div>
            `;
        }).join('');
    }

    function escapeHtml(text) {
        const div = document.createElement('div');
        div.textContent = text;
        return div.innerHTML;
    }

    function formatText(text) {
        // Convert markdown-style links [text](url) to HTML links
        return escapeHtml(text).replace(
            /\[([^\]]+)\]\(([^)]+)\)/g,
            '<a href="\$2" target="_blank" rel="noopener">\$1</a>'
        );
    }

    // Load data when page loads
    loadOrchestrions();
</script>