Select Page

User:Aoppo/Globstory.js

Note: After saving, you have to bypass your browser's cache to see the changes. Google Chrome, Firefox, Microsoft Edge and Safari: Hold down the ⇧ Shift key and click the Reload toolbar button. For details and instructions about other browsers, see Wikipedia:Bypass your cache.
// GlobStory Wikipedia Integration for common.js with improved location and year detection
mw.loader.using(['mediawiki.util', 'mediawiki.api'], function() {
    mw.hook('wikipage.content').add(function($content) {
        'use strict';

        // Check if the script has already been executed
        if (window.globStoryInitialized) {
            return;
        }
        window.globStoryInitialized = true;

        // Main function to initialize GlobStory
        var initGlobStory = function() {
        
        // Create and add CSS
        const style = document.createElement('style');
        style.textContent = `
            /* Main container styles */
            .globstory-container {
                position: fixed;
                right: 0;
                top: 0;
                height: 100vh;
                width: 30%;
                background: white;
                box-shadow: -2px 0 5px rgba(0, 0, 0, 0.1);
                z-index: 1000;
                display: flex;
                flex-direction: column;
                transition: width 0.3s ease, top 0.3s ease, bottom 0.3s ease;
            }

            /* One-time popup styles */
            .globstory-popup {
                display: none;
                position: fixed;
                bottom: 20px;
                left: 50%;
                transform: translateX(-50%);
                background: white;
                padding: 15px;
                border-radius: 8px;
                box-shadow: 0 0 10px rgba(0,0,0,0.2);
                z-index: 1300;
                max-width: 300px;
                text-align: center;
            }
            
            .globstory-popup.active {
                display: block;
            }
            
            .globstory-popup-close {
                position: absolute;
                top: 5px;
                right: 10px;
                cursor: pointer;
                font-weight: bold;
            }
            
            /* Collapsed state */
            .globstory-container.collapsed {
                width: 40px;
            }
            
            /* Adjust Wikipedia content when map is shown */
            .globstory-active #content {
                margin-right: 30%;
                transition: margin-right 0.3s ease;
                width: auto !important;
            }
            
            .globstory-active.collapsed #content {
                margin-right: 40px;
                width: auto !important;
            }
            
            /* Ensure content is responsive when tool is hidden */
            .globstory-active #content,
            .globstory-active.collapsed #content {
                max-width: calc(100% - 40px);
                box-sizing: border-box;
            }

            /* Adjust content padding when map is collapsed */
            .globstory-active.collapsed #mw-content-text {
                padding-right: 40px;
            }

            /* Ensure the toggle button doesn't overlap content */
            .globstory-container.collapsed .globstory-toggle {
                z-index: 1001;
            }
            
            /* Toggle button */
            .globstory-toggle {
                position: absolute;
                left: -40px;
                top: 50%;
                background: #007BFF;
                color: white;
                width: 40px;
                height: 80px;
                border: none;
                border-radius: 5px 0 0 5px;
                cursor: pointer;
                display: flex;
                align-items: center;
                justify-content: center;
                font-size: 20px;
                box-shadow: -2px 0 5px rgba(0, 0, 0, 0.1);
            }
            
            /* Toggle button on hover */
            .globstory-toggle:hover {
                background: #0056b3;
            }
            
            /* Map container */
            .globstory-map {
                flex: 1;
                border: none;
                width: 100%;
            }
            
            /* Controls bar */
            .globstory-controls {
                display: flex;
                align-items: center;
                justify-content: space-between;
                padding: 8px;
                background-color: #f1f1f1;
                border-bottom: 1px solid #ddd;
            }
            
            /* Control buttons */
            .globstory-btn {
                padding: 6px 10px;
                margin: 0 3px;
                background-color: #007BFF;
                color: white;
                border: none;
                border-radius: 4px;
                cursor: pointer;
                font-size: 14px;
            }
            
            .globstory-btn:hover {
                background-color: #0056b3;
            }
            
            /* Year input */
            .globstory-year-input {
                padding: 6px;
                width: 70px;
                text-align: center;
                border: 1px solid #ccc;
                border-radius: 4px;
                margin: 0 5px;
            }
            
            /* Help and Settings buttons */
            .globstory-help,
            .globstory-settings {
                background: #FFA500;
                color: white;
                width: 30px;
                height: 30px;
                border: none;
                border-radius: 50%;
                cursor: pointer;
                display: flex;
                align-items: center;
                justify-content: center;
                font-weight: bold;
                margin-left: 5px;
            }

            .globstory-button-controls {
                display: flex;
                align-items: center;
            }

            .globstory-year-controls {
                display: flex;
                align-items: center;
                flex-grow: 1;
                justify-content: center;
            }
            
            /* Help and Settings modals */
            .globstory-help-modal,
            .globstory-settings-modal {
                display: none;
                position: fixed;
                top: 50%;
                left: 50%;
                transform: translate(-50%, -50%);
                background: white;
                padding: 20px;
                border-radius: 8px;
                box-shadow: 0 0 20px rgba(0,0,0,0.2);
                z-index: 1200;
                max-width: 600px;
                max-height: 80vh;
                overflow-y: auto;
            }
            
            .globstory-help-modal.active,
            .globstory-settings-modal.active {
                display: block;
            }

            /* Settings styles */
            .globstory-settings {
                margin-left: auto;
            }

            .globstory-settings-modal label {
                display: block;
                margin-top: 10px;
            }
            
            /* Modal overlay */
            .globstory-overlay {
                display: none;
                position: fixed;
                top: 0;
                left: 0;
                width: 100%;
                height: 100%;
                background: rgba(0,0,0,0.5);
                z-index: 1100;
            }
            
            .globstory-overlay.active {
                display: block;
            }
            
            /* Close button for modal */
            .globstory-close {
                position: absolute;
                top: 10px;
                right: 10px;
                font-size: 24px;
                font-weight: bold;
                cursor: pointer;
                color: #333;
            }
            
            /* Highlighted text */
            .globstory-country,
            .globstory-year {
                cursor: pointer;
            }
            
            /* Styles for different year types */
            .globstory-year.decade {
                background-color: rgba(144, 238, 144, 0.3);
            }
            
            .globstory-year.bc-era {
                background-color: rgba(255, 222, 173, 0.3);
            }
            
            /* Mobile responsiveness */
            @media (max-width: 768px) {
                .globstory-container {
                    width: 100%;
                    height: 50vh;
                    right: 0;
                    transition: top 0.3s ease, bottom 0.3s ease;
                }
                
                .globstory-container.collapsed {
                    height: 40px;
                    width: 100%;
                }
                
                .globstory-toggle {
                    left: 50%;
                    transform: translateX(-50%);
                    width: 80px;
                    height: 40px;
                }
                
                .globstory-active #content {
                    margin-right: 0;
                    transition: margin-top 0.3s ease, margin-bottom 0.3s ease;
                }
                
                .globstory-active.collapsed #content {
                    margin-bottom: 40px;
                    margin-right: 0;
                }

                .globstory-container.top {
                    top: 0;
                    bottom: auto;
                }

                .globstory-container.bottom {
                    top: auto;
                    bottom: 0;
                }

                .globstory-container.top .globstory-toggle {
                    top: auto;
                    bottom: -40px;
                    border-radius: 0 0 5px 5px;
                }

                .globstory-container.bottom .globstory-toggle {
                    top: -40px;
                    bottom: auto;
                    border-radius: 5px 5px 0 0;
                }

                .globstory-active .globstory-container.top ~ #content {
                    margin-top: 50vh;
                    margin-bottom: 0;
                }

                .globstory-active .globstory-container.bottom ~ #content {
                    margin-top: 0;
                    margin-bottom: 50vh;
                }
            }
        `;
        document.head.appendChild(style);
        
        // Create main container
        const container = document.createElement('div');
        container.className = 'globstory-container';
        container.id = 'globstory-container';
        
        // Create toggle button
        const toggleBtn = document.createElement('button');
        toggleBtn.className = 'globstory-toggle';
        toggleBtn.innerHTML = '«';
        toggleBtn.title = 'Toggle GlobStory Map';
        container.appendChild(toggleBtn);
        
        // Create controls
        const controls = document.createElement('div');
        controls.className = 'globstory-controls';
        
        // Year navigation buttons
        const yearMinus100 = createButton('<<', 'Jump 100 years back');
        const yearMinus10 = createButton('<', 'Jump 10 years back');
        const yearInput = document.createElement('input');
        yearInput.type = 'number';
        yearInput.className = 'globstory-year-input';
        yearInput.value = new Date().getFullYear();
        const yearPlus10 = createButton('>', 'Jump 10 years forward');
        const yearPlus100 = createButton('>>', 'Jump 100 years forward');
        
        // Help button
        const helpBtn = createButton('?', 'GlobStory Help');
        helpBtn.className = 'globstory-help';
        
        // Settings button
        const settingsBtn = createButton('⚙', 'GlobStory Settings');
        settingsBtn.className = 'globstory-settings';
        
        // Create control groups
        const yearControls = document.createElement('div');
        yearControls.className = 'globstory-year-controls';
        yearControls.appendChild(yearMinus100);
        yearControls.appendChild(yearMinus10);
        yearControls.appendChild(yearInput);
        yearControls.appendChild(yearPlus10);
        yearControls.appendChild(yearPlus100);

        const buttonControls = document.createElement('div');
        buttonControls.className = 'globstory-button-controls';
        buttonControls.appendChild(helpBtn);
        buttonControls.appendChild(settingsBtn);

        // Append control groups
        controls.appendChild(yearControls);
        controls.appendChild(buttonControls);
        container.appendChild(controls);
        
        // Create settings modal
        const settingsModal = document.createElement('div');
        settingsModal.className = 'globstory-settings-modal';
        settingsModal.innerHTML = `
            <span class="globstory-close">&times;</span>
            <h2>GlobStory Settings</h2>
            <label>
                <input type="checkbox" id="globstory-auto-open" ${localStorage.getItem('globstory-auto-open') === 'true' ? 'checked' : ''}>
                Open map by default
            </label>
            <label>
                <input type="checkbox" id="globstory-map-position-top" ${localStorage.getItem('globstory-map-position-top') === 'true' ? 'checked' : ''}>
                Show map at the top on mobile devices
            </label>
        `;
        document.body.appendChild(settingsModal);

        // Create one-time popup
        const popup = document.createElement('div');
        popup.className = 'globstory-popup';
        popup.innerHTML = `
            <span class="globstory-popup-close">&times;</span>
            <p>On mobile devices, long-press highlighted words to interact with the GlobStory map.</p>
        `;
        document.body.appendChild(popup);
        
        // Create map iframe
        const mapIframe = document.createElement('iframe');
        mapIframe.className = 'globstory-map';
        mapIframe.src = `https://embed.openhistoricalmap.org/#map=3/43.021/7.471&layers=O&date=${new Date().getFullYear()}-12-08`;
        mapIframe.frameBorder = '0';
        mapIframe.scrolling = 'no';
        container.appendChild(mapIframe);
        
        // Variables to track current map state
        let currentMapZoom = "3"; // Default zoom level
        let currentMapLat = "43.021"; // Default latitude 
        let currentMapLon = "7.471"; // Default longitude
        
        // Create help modal
        const helpModal = document.createElement('div');
        helpModal.className = 'globstory-help-modal';
        helpModal.innerHTML = `
            <span class="globstory-close">&times;</span>
            <h2>Welcome to GlobStory Wikipedia Integration</h2>
            <p>This extension enhances your Wikipedia experience by adding an interactive historical map that dynamically responds to content.</p>
            
            <h3>How to use:</h3>
            <ul>
                <li><strong>Highlighted Elements:</strong>
                    <ul>
                        <li>Country and place names are highlighted in <span style="background-color: #ffff9980;">yellow</span></li>
                        <li>Years and dates are highlighted in <span style="background-color: #90ee9080;">green</span></li>
                        <li>On desktop: Hover over highlighted text for 1 second to see the corresponding location or time period on the map</li>
                        <li>On mobile: Long-press (0.5 seconds) on highlighted text to interact with the map</li>
                    </ul>
                </li>
                <li><strong>Map Navigation:</strong>
                    <ul>
                        <li>Use the year controls to navigate through different time periods</li>
                        <li>The map will update to show historical borders for the selected year</li>
                    </ul>
                </li>
                <li><strong>Toggle the Map:</strong>
                    <ul>
                        <li>Click the toggle button to hide or show the map</li>
                        <li>On mobile, you can choose to display the map at the top or bottom of the screen in the settings</li>
                    </ul>
                </li>
                <li><strong>Settings:</strong>
                    <ul>
                        <li>Click the settings icon (⚙) to access additional options</li>
                        <li>You can set the map to open by default and choose its position on mobile devices</li>
                    </ul>
                </li>
            </ul>
            
            <p>To learn more about GlobStory, visit <a href="https://globstory.it" target="_blank">globstory.it</a></p>
        `;
        
        // Create overlay
        const overlay = document.createElement('div');
        overlay.className = 'globstory-overlay';
        
        // Add elements to the page
        document.body.appendChild(container);
        document.body.appendChild(helpModal);
        document.body.appendChild(overlay);
        
        // Check if the map should be open by default
        if (localStorage.getItem('globstory-auto-open') !== 'true') {
            container.classList.add('collapsed');
            document.body.classList.add('collapsed');
        }
        
        // Add the 'globstory-active' class to the body
        document.body.classList.add('globstory-active');
        
        // Initialize hover functionality for country and year detection
        initializeHighlighting();
        
        // Event listeners
        toggleBtn.addEventListener('click', toggleMap);
        yearMinus100.addEventListener('click', () => adjustYear(-100));
        yearMinus10.addEventListener('click', () => adjustYear(-10));
        yearPlus10.addEventListener('click', () => adjustYear(10));
        yearPlus100.addEventListener('click', () => adjustYear(100));
        
        yearInput.addEventListener('change', () => {
            const year = parseInt(yearInput.value, 10);
            updateMapYear(year);
        });
        
        helpBtn.addEventListener('click', () => {
            helpModal.classList.add('active');
            overlay.classList.add('active');
        });
        
        settingsBtn.addEventListener('click', () => {
            settingsModal.classList.add('active');
            overlay.classList.add('active');
        });
        
        document.querySelectorAll('.globstory-close, .globstory-popup-close').forEach(closeBtn => {
            closeBtn.addEventListener('click', closeModals);
        });
        
        overlay.addEventListener('click', closeModals);
        
        document.getElementById('globstory-auto-open').addEventListener('change', (e) => {
            localStorage.setItem('globstory-auto-open', e.target.checked);
        });

        document.getElementById('globstory-map-position-top').addEventListener('change', (e) => {
            localStorage.setItem('globstory-map-position-top', e.target.checked);
            updateMapPosition();
        });

        // Show one-time popup if it hasn't been shown before
        if (localStorage.getItem('globstory-popup-shown') !== 'true') {
            popup.classList.add('active');
            localStorage.setItem('globstory-popup-shown', 'true');
        }

        // Update map position based on user preference
        updateMapPosition();
        
        // Helper functions
        function createButton(text, title) {
            const button = document.createElement('button');
            button.className = 'globstory-btn';
            button.textContent = text;
            button.title = title;
            return button;
        }
        
        function toggleMap() {
            container.classList.toggle('collapsed');
            document.body.classList.toggle('collapsed');
            
            if (container.classList.contains('collapsed')) {
                toggleBtn.innerHTML = '&raquo;';
            } else {
                toggleBtn.innerHTML = '&laquo;';
            }
        }
        
        function adjustYear(delta) {
            const currentYear = parseInt(yearInput.value, 10);
            const newYear = currentYear + delta;
            yearInput.value = newYear;
            updateMapYear(newYear);
        }
        
        // Helper function to extract current state from iframe
        function updateCurrentMapStateFromIframe() {
            try {
                const src = mapIframe.src;
                if (src.includes('#')) {
                    const hashParams = src.split('#')[1].split('&');
                    
                    hashParams.forEach(param => {
                        if (param.startsWith("map=")) {
                            const mapValues = param.split("=")[1].split("/");
                            if (mapValues.length >= 3) {
                                currentMapZoom = mapValues[0] || currentMapZoom;
                                currentMapLat = mapValues[1] || currentMapLat;
                                currentMapLon = mapValues[2] || currentMapLon;
                            }
                        }
                    });
                }
            } catch (e) {
                console.error("Error extracting map state:", e);
            }
        }

        // Helper function to update the map with current state
        function updateMapWithCurrentState(year) {
            const dateParam = year ? `&date=${year}-12-08` : '';
            mapIframe.src = `https://embed.openhistoricalmap.org/#map=${currentMapZoom}/${currentMapLat}/${currentMapLon}&layers=O${dateParam}`;
        }
        
        function updateMapYear(year) {
            // Try to get the current state from the iframe src
            updateCurrentMapStateFromIframe();
            
            // Use current state variables
            updateMapWithCurrentState(year);
        }
        
        function closeModals() {
            helpModal.classList.remove('active');
            settingsModal.classList.remove('active');
            overlay.classList.remove('active');
            popup.classList.remove('active');
        }

        function updateMapPosition() {
            const isTop = localStorage.getItem('globstory-map-position-top') === 'true';
            container.classList.toggle('top', isTop);
            container.classList.toggle('bottom', !isTop);
        }
        
        // IMPROVED HIGHLIGHTING FUNCTION
        function initializeHighlighting() {
            // Select all paragraph elements in the content
            const contentElement = document.getElementById('mw-content-text');
            if (!contentElement) return;
            
            const paragraphs = contentElement.querySelectorAll('p');
            
            paragraphs.forEach(paragraph => {
                // Process text nodes to identify places and years
                processTextNodes(paragraph);
            });
            
            // Add hover and long-press functionality for highlighted elements
            let hoverTimeout;
            let longPressTimeout;
            
            contentElement.addEventListener('mouseover', handleMouseOver);
            contentElement.addEventListener('mouseout', handleMouseOut);
            contentElement.addEventListener('touchstart', handleTouchStart);
            contentElement.addEventListener('touchend', handleTouchEnd);
            
            function handleMouseOver(e) {
                const target = e.target;
                
                if (target.classList.contains('globstory-country') || target.classList.contains('globstory-year')) {
                    clearTimeout(hoverTimeout);
                    
                    hoverTimeout = setTimeout(() => {
                        handleInteraction(target);
                    }, 1000); // Trigger after 1 second hover
                }
            }
            
            function handleMouseOut() {
                clearTimeout(hoverTimeout);
            }
            
            function handleTouchStart(e) {
                const target = e.target;
                
                if (target.classList.contains('globstory-country') || target.classList.contains('globstory-year')) {
                    clearTimeout(longPressTimeout);
                    
                    longPressTimeout = setTimeout(() => {
                        handleInteraction(target);
                    }, 500); // Trigger after 0.5 second long-press
                }
            }
            
            function handleTouchEnd() {
                clearTimeout(longPressTimeout);
            }
            
            function handleInteraction(target) {
                if (target.classList.contains('globstory-country')) {
                    // Handle country interaction
                    const countryName = target.dataset.place || target.dataset.country;
                    updateMapLocation(countryName);
                } else if (target.classList.contains('globstory-year')) {
                    // Handle year interaction
                    const year = parseInt(target.dataset.year, 10);
                    // Set the year input value to the numerical year (including negative for BC)
                    yearInput.value = year;
                    updateMapYear(year);
                }
            }
        }
        
        // IMPROVED TEXT PROCESSING FUNCTION
        function processTextNodes(container) {
            // Create a TreeWalker to find all text nodes in the container
            const walker = document.createTreeWalker(
                container,
                NodeFilter.SHOW_TEXT,
                {
                    acceptNode: function(node) {
                        // Skip script and style contents
                        if (node.parentNode.nodeName === 'SCRIPT' || 
                            node.parentNode.nodeName === 'STYLE') {
                            return NodeFilter.FILTER_REJECT;
                        }
                        return NodeFilter.FILTER_ACCEPT;
                    }
                }
            );

            const textNodes = [];
            let currentNode;
            while (currentNode = walker.nextNode()) {
                textNodes.push(currentNode);
            }
            
            // Process each text node found
            textNodes.forEach(node => {
                const text = node.textContent;
                if (!text.trim()) return; // Skip empty nodes
                
                // Collect all matches for places and years
                const allMatches = [];
                
                // 1. Detect places (including multi-word places)
                // Matches: Single capitalized words + Multi-word places with specific connectors
                const placeNameRegex = /\b(([A-Z][a-z]{2,})(\s+([A-Z][a-z]+|de|del|di|da|von|van|am|auf|la|le|el|al|der|den|das|du|des|do|of|on|in|by|sur|sous|aux)){0,3})\b/g;
                let match;
                while ((match = placeNameRegex.exec(text)) !== null) {
                    allMatches.push({
                        text: match[0],
                        index: match.index,
                        type: 'place'
                    });
                }
                
                // 2. Detect decades (e.g., "1990s", "20s")
                const decadeRegex = /\b([0-9]{2,4})s\b/g;
                while ((match = decadeRegex.exec(text)) !== null) {
                    const yearValue = parseInt(match[1], 10);
                    if (yearValue >= 0 && yearValue <= 2100) {
                        allMatches.push({
                            text: match[0],
                            index: match.index,
                            type: 'year',
                            year: yearValue,
                            isDecade: true,
                            isBCEra: false
                        });
                    }
                }
                
                // 3. Detect BC/BCE years
                const bcRegex = /\b([0-9]{1,5})\s*(BC|BCE|a\.C\.|AEC)\b/gi;
                while ((match = bcRegex.exec(text)) !== null) {
                    const yearValue = parseInt(match[1], 10);
                    if (yearValue >= 0 && yearValue <= 10000) {
                        allMatches.push({
                            text: match[0],
                            index: match.index,
                            type: 'year',
                            year: -yearValue, // Store as negative for BC years
                            isDecade: false,
                            isBCEra: true,
                            originalText: match[0]
                        });
                    }
                }
                
                // 4. Detect standard years (e.g., "1990", "2023")
                const standardYearRegex = /\b(-?[0-9]{1,5})\b/g;
                while ((match = standardYearRegex.exec(text)) !== null) {
                    const yearValue = parseInt(match[1], 10);
                    // Reasonable year range for historical context
                    if (yearValue >= -10000 && yearValue <= 2100) {
                        // Check if this match overlaps with any existing match to avoid duplicates
                        const overlaps = allMatches.some(existing => 
                            (match.index >= existing.index && match.index < existing.index + existing.text.length) ||
                            (existing.index >= match.index && existing.index < match.index + match[0].length)
                        );
                        
                        if (!overlaps) {
                            allMatches.push({
                                text: match[0],
                                index: match.index,
                                type: 'year',
                                year: yearValue,
                                isDecade: false,
                                isBCEra: yearValue < 0
                            });
                        }
                    }
                }
                
                // If no matches were found, return without changes
                if (allMatches.length === 0) return;
                
                // Sort matches by index to maintain order of text
                allMatches.sort((a, b) => a.index - b.index);
                
                // Create a document fragment to replace the text node
                const fragment = document.createDocumentFragment();
                let lastIndex = 0;
                
                // Process each match and create the appropriate spans
                allMatches.forEach(match => {
                    // Add text before this match
                    if (match.index > lastIndex) {
                        fragment.appendChild(document.createTextNode(text.substring(lastIndex, match.index)));
                    }
                    
                    // Create appropriate span based on match type
                    const span = document.createElement('span');
                    span.textContent = match.text;
                    
                    if (match.type === 'place') {
                        span.className = 'globstory-country';
                        span.dataset.place = match.text;
                        span.title = `Click or hover to locate ${match.text} on the map`;
                    } else if (match.type === 'year') {
                        span.className = 'globstory-year';
                        span.dataset.year = match.year;
                        span.title = `Click or hover to set map to year ${match.year}`;
                        
                        // Add special classes for decade and BC/BCE years
                        if (match.isDecade) {
                            span.classList.add('decade');
                            span.title = `Click or hover to set map to the ${match.text}`;
                        }
                        
                        if (match.isBCEra) {
                            span.classList.add('bc-era');
                            // Store original text for display purposes
                            if (match.originalText) {
                                span.dataset.originalText = match.originalText;
                            }
                        }
                    }
                    
                    fragment.appendChild(span);
                    lastIndex = match.index + match.text.length;
                });
                
                // Add any remaining text
                if (lastIndex < text.length) {
                    fragment.appendChild(document.createTextNode(text.substring(lastIndex)));
                }
                
                // Replace the original text node with our fragment
                if (node.parentNode) {
                    node.parentNode.replaceChild(fragment, node);
                }
            });
        }
        
        function updateMapLocation(placeName) {
            // Use MediaWiki API to fetch coordinates
            new mw.Api().get({
                action: 'query',
                prop: 'coordinates',
                titles: placeName,
                format: 'json'
            }).done(function(data) {
                var pages = data.query.pages;
                var pageId = Object.keys(pages)[0];
                var page = pages[pageId];
                
                if (page.coordinates) {
                    // Try to get current zoom from iframe first
                    updateCurrentMapStateFromIframe();
                    
                    // Now update with new coordinates
                    currentMapLat = page.coordinates[0].lat;
                    currentMapLon = page.coordinates[0].lon;
                    
                    // If we're explicitly navigating to a place, use a specific zoom level
                    currentMapZoom = "6";
                    
                    // Get current year from input
                    var currentYear = yearInput.value;
                    
                    // Update the map iframe with new state
                    updateMapWithCurrentState(currentYear);
                } else {
                    // If coordinates not found in Wiki API, try Nominatim as a fallback
                    searchNominatim(placeName);
                }
            }).fail(function() {
                console.error("Error fetching location coordinates for: " + placeName);
                // Try Nominatim as a fallback
                searchNominatim(placeName);
            });
        }
        
        // Fallback to Nominatim for locations not found in MediaWiki API
        function searchNominatim(placeName) {
            fetch(
                `https://nominatim.openstreetmap.org/search?` +
                `q=${encodeURIComponent(placeName)}&` +
                `format=json&limit=1&addressdetails=1`
            )
            .then(response => {
                if (!response.ok) throw new Error('Network response was not ok');
                return response.json();
            })
            .then(data => {
                if (data && data.length > 0) {
                    const location = data[0];
                    
                    // Update current map state
                    updateCurrentMapStateFromIframe();
                    
                    currentMapLat = location.lat;
                    currentMapLon = location.lon;
                    currentMapZoom = "6";
                    
                    // Get current year from input
                    var currentYear = yearInput.value;
                    
                    // Update the map iframe with new state
                    updateMapWithCurrentState(currentYear);
                } else {
                    console.error("Location not found in Nominatim:", placeName);
                }
            })
            .catch(error => {
                console.error("Error searching Nominatim:", error);
            });
        }

        // Listen for messages from the iframe
        window.addEventListener('message', function(event) {
            if (event.origin !== 'https://embed.openhistoricalmap.org') return;
            
            if (event.data.type === 'mapLoaded') {
                console.log('Map loaded successfully');
            }
        }, false);
        }; // End of initGlobStory function

        // Run the initialization
        initGlobStory();
    });
});