T.ME/BIBIL_0DAY
CasperSecurity


Server : Apache/2
System : Linux server-15-235-50-60 5.15.0-164-generic #174-Ubuntu SMP Fri Nov 14 20:25:16 UTC 2025 x86_64
User : gositeme ( 1004)
PHP Version : 8.2.29
Disable Function : exec,system,passthru,shell_exec,proc_close,proc_open,dl,popen,show_source,posix_kill,posix_mkfifo,posix_getpwuid,posix_setpgid,posix_setsid,posix_setuid,posix_setgid,posix_seteuid,posix_setegid,posix_uname
Directory :  /home/gositeme/.cursor-server/data/User/History/6b963d87/

Upload File :
current_dir [ Writeable ] document_root [ Writeable ]

 

Current File : /home/gositeme/.cursor-server/data/User/History/6b963d87/XBBH.js
/**
 * Simple Interactive Map - Clean Implementation
 * Shows cities and villages on a Quebec map
 */

(function() {
    'use strict';

    const CONFIG = {
        quebecBounds: {
            minLat: 45.0,
            maxLat: 51.0,
            minLng: -80.0,
            maxLng: -66.0
        },
        zoom: {
            min: 0.5,
            max: 5,
            default: 1.2,
            step: 1.2
        }
    };

    let state = {
        cities: [],
        villages: [],
        zoom: CONFIG.zoom.default,
        panX: 0,
        panY: 0,
        isDragging: false,
        dragStart: { x: 0, y: 0 }
    };

    let canvas, ctx, container;
    const lang = document.documentElement.lang || 'en';

    function init() {
        container = document.getElementById('homepageInteractiveMap');
        if (!container) return;

        canvas = document.getElementById('homepageMapCanvas');
        if (!canvas) return;

        ctx = canvas.getContext('2d');
        if (!ctx) return;

        setupUI();
        setupEvents();
        resize();
        loadData();
        animate();
    }

    function setupUI() {
        const zoomIn = document.getElementById('mapZoomIn');
        const zoomOut = document.getElementById('mapZoomOut');
        const resetView = document.getElementById('resetMapView');

        if (zoomIn) zoomIn.addEventListener('click', () => zoom(1));
        if (zoomOut) zoomOut.addEventListener('click', () => zoom(-1));
        if (resetView) resetView.addEventListener('click', resetMapView);
    }

    function setupEvents() {
        canvas.addEventListener('mousedown', handleMouseDown);
        canvas.addEventListener('mousemove', handleMouseMove);
        canvas.addEventListener('mouseup', handleMouseUp);
        canvas.addEventListener('wheel', handleWheel, { passive: false });
        window.addEventListener('resize', resize);
    }

    async function loadData() {
        // Load cities from fallback data
        if (window.quebecMunicipalities) {
            const bounds = CONFIG.quebecBounds;
            state.cities = Object.keys(window.quebecMunicipalities).map(name => {
                const data = window.quebecMunicipalities[name];
                if (!data || !data.lat || !data.lng) return null;
                return {
                    name: name,
                    lat: parseFloat(data.lat),
                    lng: parseFloat(data.lng),
                    region: data.region || '',
                    population: parseInt(data.population) || 0
                };
            }).filter(c => 
                c !== null &&
                c.lat >= bounds.minLat && c.lat <= bounds.maxLat &&
                c.lng >= bounds.minLng && c.lng <= bounds.maxLng
            );
        }

        // Try to load villages from API
        try {
            const response = await fetch('/api/endpoints/map-villages.php');
            if (response.ok) {
                const data = await response.json();
                if (data.success && data.villages) {
                    const bounds = CONFIG.quebecBounds;
                    state.villages = data.villages.filter(v => {
                        if (!v.lat || !v.lng) return false;
                        const lat = parseFloat(v.lat);
                        const lng = parseFloat(v.lng);
                        return lat >= bounds.minLat && lat <= bounds.maxLat &&
                               lng >= bounds.minLng && lng <= bounds.maxLng;
                    }).map(v => ({
                        ...v,
                        lat: parseFloat(v.lat),
                        lng: parseFloat(v.lng)
                    }));
                }
            }
        } catch (e) {
            // Continue without villages
        }

        updatePositions();
    }

    function resize() {
        if (!canvas || !container) return;
        const rect = container.getBoundingClientRect();
        canvas.width = rect.width;
        canvas.height = rect.height;
        
        if (state.panX === 0 && state.panY === 0) {
            state.panX = canvas.width / 2;
            state.panY = canvas.height / 2;
        }
        
        updatePositions();
    }

    function updatePositions() {
        if (!canvas || canvas.width === 0 || canvas.height === 0) return;

        const bounds = CONFIG.quebecBounds;
        const width = canvas.width;
        const height = canvas.height;

        state.cities.forEach(city => {
            city.x = ((city.lng - bounds.minLng) / (bounds.maxLng - bounds.minLng)) * width * state.zoom + (state.panX - (width * state.zoom) / 2);
            city.y = ((bounds.maxLat - city.lat) / (bounds.maxLat - bounds.minLat)) * height * state.zoom + (state.panY - (height * state.zoom) / 2);
        });

        state.villages.forEach(village => {
            village.x = ((village.lng - bounds.minLng) / (bounds.maxLng - bounds.minLng)) * width * state.zoom + (state.panX - (width * state.zoom) / 2);
            village.y = ((bounds.maxLat - village.lat) / (bounds.maxLat - bounds.minLat)) * height * state.zoom + (state.panY - (height * state.zoom) / 2);
        });
    }

    function zoom(direction) {
        state.zoom = Math.max(CONFIG.zoom.min, Math.min(CONFIG.zoom.max, 
            state.zoom * (direction > 0 ? CONFIG.zoom.step : 1 / CONFIG.zoom.step)));
        updatePositions();
    }

    function resetMapView() {
        state.zoom = CONFIG.zoom.default;
        state.panX = canvas.width / 2;
        state.panY = canvas.height / 2;
        updatePositions();
    }

    function handleMouseDown(e) {
        state.isDragging = true;
        const rect = canvas.getBoundingClientRect();
        state.dragStart.x = e.clientX - rect.left;
        state.dragStart.y = e.clientY - rect.top;
        canvas.style.cursor = 'grabbing';
    }

    function handleMouseMove(e) {
        if (state.isDragging) {
            const rect = canvas.getBoundingClientRect();
            const x = e.clientX - rect.left;
            const y = e.clientY - rect.top;
            state.panX += x - state.dragStart.x;
            state.panY += y - state.dragStart.y;
            state.dragStart.x = x;
            state.dragStart.y = y;
            updatePositions();
        }
    }

    function handleMouseUp() {
        state.isDragging = false;
        canvas.style.cursor = 'grab';
    }

    function handleWheel(e) {
        e.preventDefault();
        const rect = canvas.getBoundingClientRect();
        const x = e.clientX - rect.left;
        const y = e.clientY - rect.top;
        
        const oldZoom = state.zoom;
        const zoomFactor = e.deltaY > 0 ? 1 / CONFIG.zoom.step : CONFIG.zoom.step;
        state.zoom = Math.max(CONFIG.zoom.min, Math.min(CONFIG.zoom.max, state.zoom * zoomFactor));
        
        const zoomChange = state.zoom / oldZoom;
        state.panX = x - (x - state.panX) * zoomChange;
        state.panY = y - (y - state.panY) * zoomChange;
        updatePositions();
    }

    function draw() {
        if (!ctx || !canvas) return;

        // Clear canvas
        ctx.clearRect(0, 0, canvas.width, canvas.height);

        // Background
        const bgColor = getComputedStyle(document.documentElement).getPropertyValue('--color-bg-light').trim() || '#1a1a1a';
        ctx.fillStyle = bgColor;
        ctx.fillRect(0, 0, canvas.width, canvas.height);

        // Grid
        ctx.strokeStyle = 'rgba(212, 165, 116, 0.1)';
        ctx.lineWidth = 1;
        const gridSize = 50;
        for (let x = 0; x < canvas.width; x += gridSize) {
            ctx.beginPath();
            ctx.moveTo(x, 0);
            ctx.lineTo(x, canvas.height);
            ctx.stroke();
        }
        for (let y = 0; y < canvas.height; y += gridSize) {
            ctx.beginPath();
            ctx.moveTo(0, y);
            ctx.lineTo(canvas.width, y);
            ctx.stroke();
        }

        // Draw cities
        state.cities.forEach(city => {
            if (city.x === undefined || city.y === undefined || isNaN(city.x) || isNaN(city.y)) return;
            
            const radius = city.population > 100000 ? 8 : city.population > 50000 ? 5 : 3;
            const color = city.population > 100000 ? '212, 165, 116' : city.population > 50000 ? '139, 195, 74' : '100, 150, 200';
            
            // Draw city point
            ctx.fillStyle = `rgba(${color}, 0.8)`;
            ctx.beginPath();
            ctx.arc(city.x, city.y, radius, 0, Math.PI * 2);
            ctx.fill();
            
            // Draw border
            ctx.strokeStyle = `rgba(${color}, 1)`;
            ctx.lineWidth = 2;
            ctx.stroke();
            
            // Draw label for major cities
            if (city.population > 50000 && state.zoom > 1.5) {
                const textColor = getComputedStyle(document.documentElement).getPropertyValue('--color-text').trim() || '#f5f5f5';
                ctx.fillStyle = textColor;
                ctx.font = '12px sans-serif';
                ctx.textAlign = 'center';
                ctx.textBaseline = 'top';
                ctx.fillText(city.name, city.x, city.y + radius + 5);
            }
        });

        // Draw villages
        if (state.zoom > 2.0) {
            state.villages.forEach(village => {
                if (village.x === undefined || village.y === undefined || isNaN(village.x) || isNaN(village.y)) return;
                
                const isActive = village.status === 'active';
                const radius = isActive ? 10 : 6;
                const color = isActive ? '255, 215, 0' : '139, 195, 74';
                
                // Draw village point
                ctx.fillStyle = `rgba(${color}, 0.9)`;
                ctx.beginPath();
                ctx.arc(village.x, village.y, radius, 0, Math.PI * 2);
                ctx.fill();
                
                // Draw border
                ctx.strokeStyle = `rgba(${color}, 1)`;
                ctx.lineWidth = isActive ? 3 : 2;
                ctx.stroke();
                
                // Draw label
                const name = (lang === 'fr' && village.name_fr) ? village.name_fr : village.name;
                const textColor = getComputedStyle(document.documentElement).getPropertyValue('--color-text').trim() || '#f5f5f5';
                ctx.fillStyle = textColor;
                ctx.font = isActive ? 'bold 13px sans-serif' : '12px sans-serif';
                ctx.textAlign = 'center';
                ctx.textBaseline = 'top';
                ctx.fillText(name, village.x, village.y + radius + 5);
            });
        } else {
            // Show only active villages when zoomed out
            state.villages.filter(v => v.status === 'active').forEach(village => {
                if (village.x === undefined || village.y === undefined || isNaN(village.x) || isNaN(village.y)) return;
                
                const radius = 10;
                const color = '255, 215, 0';
                
                ctx.fillStyle = `rgba(${color}, 0.9)`;
                ctx.beginPath();
                ctx.arc(village.x, village.y, radius, 0, Math.PI * 2);
                ctx.fill();
                
                ctx.strokeStyle = `rgba(${color}, 1)`;
                ctx.lineWidth = 3;
                ctx.stroke();
            });
        }

        requestAnimationFrame(animate);
    }

    function animate() {
        draw();
    }

    if (document.readyState === 'loading') {
        document.addEventListener('DOMContentLoaded', init);
    } else {
        setTimeout(init, 100);
    }
})();

CasperSecurity Mini