Content is user-generated and unverified.
// ============================================================================= // iframe-bridge-client.ts — Script embarqué dans chaque iframe carte // ============================================================================= // Ce fichier est inclus dans les pages HTML des iframes (map-osm.html, etc.) // Il gère : // 1. L'annonce de readiness au parent // 2. La réception des actions et sync de state // 3. La remontée d'événements (clics, survols, etc.) vers le parent // ============================================================================= interface IframeBridgeMessage { source: 'map-parent' | 'map-iframe'; iframeId: string; type: 'ACTION' | 'READY' | 'EVENT' | 'STATE_SYNC'; payload: unknown; } interface MapBridgeClient { iframeId: string; state: any; onStateSync: (state: any) => void; onAction: (action: { type: string; payload?: unknown }) => void; emitEvent: (name: string, data: unknown) => void; signalReady: () => void; } /** * Crée le client bridge côté iframe. * * Usage dans map-osm.html : * * const bridge = createMapBridge('map-osm'); * * bridge.onStateSync = (state) => { * console.log('Received full state:', state); * renderMarkers(state.objects); * }; * * bridge.onAction = (action) => { * if (action.type === 'FIT_BOUNDS') fitBounds(action.payload.bounds); * if (action.type === 'HIGHLIGHT') highlight(action.payload.id); * }; * * // Quand la carte est initialisée : * map.on('load', () => bridge.signalReady()); * * // Remonter les événements : * map.on('click', (e) => { * bridge.emitEvent('object-clicked', { id: e.feature.id }); * }); */ function createMapBridge(iframeId: string): MapBridgeClient { const client: MapBridgeClient = { iframeId, state: null, // Callbacks à surcharger par le consommateur onStateSync: () => {}, onAction: () => {}, /** Envoie un événement au parent */ emitEvent(name: string, data: unknown): void { const msg: IframeBridgeMessage = { source: 'map-iframe', iframeId: this.iframeId, type: 'EVENT', payload: { name, data }, }; window.parent.postMessage(msg, '*'); }, /** Signale au parent que l'iframe est prête */ signalReady(): void { const msg: IframeBridgeMessage = { source: 'map-iframe', iframeId: this.iframeId, type: 'READY', payload: null, }; window.parent.postMessage(msg, '*'); console.log(`[MapBridge] iframe "${iframeId}" signaled READY`); }, }; // Écoute les messages du parent window.addEventListener('message', (event: MessageEvent<IframeBridgeMessage>) => { const msg = event.data; if (!msg || msg.source !== 'map-parent') return; if (msg.iframeId !== iframeId) return; // Ignore les messages destinés à d'autres iframes switch (msg.type) { case 'STATE_SYNC': client.state = msg.payload; client.onStateSync(msg.payload); break; case 'ACTION': client.onAction(msg.payload as { type: string; payload?: unknown }); break; default: console.log(`[MapBridge] unhandled message type: ${msg.type}`); } }); return client; } // Exporte pour usage dans un contexte module, ou attache au window pour usage script if (typeof window !== 'undefined') { (window as any).createMapBridge = createMapBridge; } export { createMapBridge, MapBridgeClient, IframeBridgeMessage };
Content is user-generated and unverified.
    iframe-bridge-client.ts: Cross-iframe Communication Guide | Claude