「Widget:Custom multiple map」の版間の差分
ナビゲーションに移動
検索に移動
ページの作成:「<includeonly> <!-- Required CSS (静的リソース - 一度だけ読み込み) --> <script> if (!document.querySelector('link[href*="leaflet.css"]')) { document.head.insertAdjacentHTML('beforeend', '<link rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css"/>'); document.head.insertAdjacentHTML('beforeend', '<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/leaflet.draw/1.0.4/leaflet.draw.css"/>'); document.head.ins…」 |
編集の要約なし |
||
| 11行目: | 11行目: | ||
} | } | ||
</script> | </script> | ||
<!-- Required JS Libraries (静的リソース - 一度だけ読み込み) --> | <!-- Required JS Libraries (静的リソース - 一度だけ読み込み) --> | ||
<script> | <script> | ||
| 33行目: | 32行目: | ||
} | } | ||
</script> | </script> | ||
<!-- Global Configuration (初期化 - 一度だけ実行) --> | <!-- Global Configuration (初期化 - 一度だけ実行) --> | ||
<script> | <script> | ||
| 56行目: | 54行目: | ||
return this.instances[instanceId]; | return this.instances[instanceId]; | ||
} | } | ||
// 設定の深いコピーを作成して分離を確実にする | |||
const instanceConfig = config ? JSON.parse(JSON.stringify(config)) : {}; | |||
const instance = { | const instance = { | ||
id: instanceId, | id: instanceId, | ||
config: | config: instanceConfig, | ||
api: {}, | api: {}, | ||
map: null, | map: null, | ||
| 79行目: | 80行目: | ||
window.WidgetMap = instance; | window.WidgetMap = instance; | ||
} | } | ||
console.log('[WidgetMapManager] Created instance:', instanceId, 'with config:', instanceConfig); | |||
return instance; | return instance; | ||
| 96行目: | 99行目: | ||
}; | }; | ||
} | } | ||
// Initialize API base URL | // Initialize API base URL | ||
if (!window.API_BASE_URL) { | if (!window.API_BASE_URL) { | ||
| 104行目: | 106行目: | ||
console.log('API_BASE_URL initialized:', baseUrl); | console.log('API_BASE_URL initialized:', baseUrl); | ||
} | } | ||
// 保留中の設定を保存するための配列 | |||
if (!window.WidgetMapPendingConfigs) { | |||
window.WidgetMapPendingConfigs = []; | |||
} | |||
// グローバル初期化完了フラグ | // グローバル初期化完了フラグ | ||
window.WidgetMapGlobalInitialized = true; | window.WidgetMapGlobalInitialized = true; | ||
| 110行目: | 117行目: | ||
})(); | })(); | ||
</script> | </script> | ||
<!-- WidgetMapコアモジュールの読み込み (一度だけ) --> | <!-- WidgetMapコアモジュールの読み込み (一度だけ) --> | ||
<script> | <script> | ||
| 143行目: | 149行目: | ||
}); | }); | ||
} | } | ||
// コアモジュールの順次読み込み | // コアモジュールの順次読み込み | ||
Promise.resolve() | Promise.resolve() | ||
| 153行目: | 158行目: | ||
window.WidgetMapCoreLoaded = true; | window.WidgetMapCoreLoaded = true; | ||
console.log('[WidgetMap] All core modules loaded successfully'); | console.log('[WidgetMap] All core modules loaded successfully'); | ||
// 保留中の設定を処理 | |||
if (window.WidgetMapPendingConfigs) { | |||
window.WidgetMapPendingConfigs.forEach(pendingConfig => { | |||
try { | |||
pendingConfig.initFunction(); | |||
} catch (error) { | |||
console.error('[WidgetMap] Pending config initialization failed:', error); | |||
} | |||
}); | |||
window.WidgetMapPendingConfigs = []; | |||
} | |||
// 読み込み完了を待機している初期化関数を実行 | // 読み込み完了を待機している初期化関数を実行 | ||
| 174行目: | 191行目: | ||
})(); | })(); | ||
</script> | </script> | ||
<!-- 個別マップインスタンス用の設定と初期化 --> | <!-- 個別マップインスタンス用の設定と初期化 --> | ||
<script> | <script> | ||
| 180行目: | 196行目: | ||
'use strict'; | 'use strict'; | ||
// | // このWidget呼び出し専用の設定を即座に作成・固定化 | ||
const | const widgetInstanceConfig = Object.freeze({ | ||
imageUrl: '<!--{$img}-->', | imageUrl: '<!--{$img}-->', | ||
imageWidth: <!--{$imgwidth}-->, | imageWidth: <!--{$imgwidth}-->, | ||
| 188行目: | 204行目: | ||
maxZoom: <!--{$maxzoom}-->, | maxZoom: <!--{$maxzoom}-->, | ||
geoJsonPage: '<!--{$geojson}-->', | geoJsonPage: '<!--{$geojson}-->', | ||
iconUrls: { | iconUrls: Object.freeze({ | ||
icon1: '<!--{$icon1|default:"https://dq.h1g.jp/img/marker-icon-img/marker-icon-blue.png"}-->', | icon1: '<!--{$icon1|default:"https://dq.h1g.jp/img/marker-icon-img/marker-icon-blue.png"}-->', | ||
icon2: '<!--{$icon2|default:"https://dq.h1g.jp/img/marker-icon-img/marker-icon-red.png"}-->', | icon2: '<!--{$icon2|default:"https://dq.h1g.jp/img/marker-icon-img/marker-icon-red.png"}-->', | ||
| 209行目: | 225行目: | ||
icon19: '<!--{$icon19|default:"https://dq.h1g.jp/img/marker-icon-img/marker-icon-grey.png"}-->', | icon19: '<!--{$icon19|default:"https://dq.h1g.jp/img/marker-icon-img/marker-icon-grey.png"}-->', | ||
icon20: '<!--{$icon20|default:"https://dq.h1g.jp/img/marker-icon-img/marker-icon-grey.png"}-->' | icon20: '<!--{$icon20|default:"https://dq.h1g.jp/img/marker-icon-img/marker-icon-grey.png"}-->' | ||
}, | }), | ||
filters: { | filters: Object.freeze({ | ||
filter1: '<!--{$filter1|default:""}-->', | filter1: '<!--{$filter1|default:""}-->', | ||
filter2: '<!--{$filter2|default:""}-->', | filter2: '<!--{$filter2|default:""}-->', | ||
| 231行目: | 247行目: | ||
filter19: '<!--{$filter19|default:""}-->', | filter19: '<!--{$filter19|default:""}-->', | ||
filter20: '<!--{$filter20|default:""}-->' | filter20: '<!--{$filter20|default:""}-->' | ||
} | }), | ||
}; | // 一意識別子 | ||
instanceCreatedAt: Date.now(), | |||
uniqueId: Math.random().toString(36).substr(2, 9) | |||
}); | |||
// 設定のログ出力(デバッグ用) | |||
console.log('[Widget Map] Created config for GeoJSON page:', widgetInstanceConfig.geoJsonPage, 'ID:', widgetInstanceConfig.uniqueId); | |||
// | // マップIDの決定ロジック(大幅に改善) | ||
function findTargetMapElement() { | function findTargetMapElement() { | ||
const currentScript = document.currentScript; | const currentScript = document.currentScript; | ||
| 240行目: | 262行目: | ||
// 1. mapidパラメータが指定されている場合 | // 1. mapidパラメータが指定されている場合 | ||
const specifiedMapId = '<!--{$mapid|default:""}-->'; | const specifiedMapId = '<!--{$mapid|default:""}-->'; | ||
if (specifiedMapId) { | if (specifiedMapId && specifiedMapId.trim() !== '') { | ||
const specifiedElement = document.getElementById(specifiedMapId); | const specifiedElement = document.getElementById(specifiedMapId); | ||
if (specifiedElement) { | if (specifiedElement) { | ||
console.log('[WidgetMap] Using specified map element:', specifiedMapId); | |||
return specifiedElement; | return specifiedElement; | ||
} else { | } else { | ||
| 251行目: | 274行目: | ||
// 2. 現在のスクリプトより前にある最新のmap要素を探す | // 2. 現在のスクリプトより前にある最新のmap要素を探す | ||
if (currentScript) { | if (currentScript) { | ||
let | // 前の兄弟要素を遡って検索 | ||
let element = currentScript.previousElementSibling; | |||
while (element) { | |||
while ( | if (element.id && element.id.match(/^map\d*$/i)) { | ||
// まだ初期化されていない要素を優先 | |||
if ( | if (!element.hasAttribute('data-widgetmap-initialized')) { | ||
console.log('[WidgetMap] Found uninitialized map element:', element.id); | |||
return element; | |||
} | |||
} | } | ||
element = element.previousElementSibling; | |||
} | } | ||
// | // 同じ親要素内のmap要素をすべて検索 | ||
const parent = currentScript.parentElement; | const parent = currentScript.parentElement; | ||
if (parent) { | if (parent) { | ||
const mapElements = parent.querySelectorAll('[id^ | const mapElements = parent.querySelectorAll('[id^="map"]'); | ||
// 配列を逆順にして最新のものから探す | |||
for (let i = mapElements.length - 1; i >= 0; i--) { | |||
const mapElement = mapElements[i]; | |||
if (!mapElement.hasAttribute('data-widgetmap-initialized')) { | |||
console.log('[WidgetMap] Found uninitialized map element in parent:', mapElement.id); | |||
return mapElement; | |||
} | |||
} | } | ||
} | } | ||
} | } | ||
// 3. | // 3. ドキュメント全体で未初期化のmap要素を探す(フォールバック) | ||
const allMapElements = document.querySelectorAll('[id^ | const allMapElements = document.querySelectorAll('[id^="map"]'); | ||
for (let element of allMapElements) { | |||
if (!element.hasAttribute('data-widgetmap-initialized')) { | |||
console.log('[WidgetMap] Found uninitialized map element (fallback):', element.id); | |||
return element; | |||
} | } | ||
} | } | ||
console.error('[WidgetMap] No suitable map element found'); | |||
return null; | return null; | ||
} | } | ||
// | // このWidget呼び出し専用の初期化関数 | ||
function | function initializeThisWidgetMap() { | ||
try { | try { | ||
const mapElement = findTargetMapElement(); | const mapElement = findTargetMapElement(); | ||
| 300行目: | 322行目: | ||
if (!mapElement) { | if (!mapElement) { | ||
throw new Error('Map element not found. Please ensure a div element with id starting with "map" exists before the Widget call.'); | throw new Error('Map element not found. Please ensure a div element with id starting with "map" exists before the Widget call.'); | ||
} | |||
if (!mapElement.id) { | |||
throw new Error('Map element found but has no ID'); | |||
} | } | ||
const mapId = mapElement.id; | const mapId = mapElement.id; | ||
console.log('[WidgetMap] Initializing map:', mapId); | console.log('[WidgetMap] Initializing map:', mapId, 'with GeoJSON page:', widgetInstanceConfig.geoJsonPage); | ||
// 既に初期化済みかチェック | // 既に初期化済みかチェック | ||
| 313行目: | 339行目: | ||
// 初期化済みマークを追加 | // 初期化済みマークを追加 | ||
mapElement.setAttribute('data-widgetmap-initialized', 'true'); | mapElement.setAttribute('data-widgetmap-initialized', 'true'); | ||
mapElement.setAttribute('data-widgetmap-geojson', widgetInstanceConfig.geoJsonPage); | |||
// マップインスタンスの初期化(固定化された設定を使用) | |||
const instance = initializeMapInstance(mapId, widgetInstanceConfig); | |||
// | // データの読み込みを確実に実行 | ||
if (instance && instance.api && instance.api.loadPinsFromWikiPage) { | |||
console.log('[WidgetMap] Loading pins for instance:', instance.id, 'from page:', instance.config.geoJsonPage); | |||
// 少し遅延させてマップ初期化完了を待つ | |||
setTimeout(() => { | |||
try { | |||
instance.api.loadPinsFromWikiPage(); | |||
} catch (error) { | |||
console.error('[WidgetMap] Error loading pins:', error); | |||
} | |||
}, 100); | |||
} else { | |||
console.error('[WidgetMap] API not available for loading pins - instance:', instance ? 'exists' : 'null', 'api:', instance ? (instance.api ? 'exists' : 'null') : 'N/A'); | |||
} | |||
} catch (error) { | } catch (error) { | ||
| 342行目: | 384行目: | ||
} | } | ||
function initializeMapInstance(elementId, | function initializeMapInstance(elementId, configToUse) { | ||
if (!window.WidgetMapManager || !window.WidgetMapManager.initializeMap) { | if (!window.WidgetMapManager || !window.WidgetMapManager.initializeMap) { | ||
throw new Error('WidgetMapManager not initialized'); | throw new Error('WidgetMapManager not initialized'); | ||
} | } | ||
const instance = window.WidgetMapManager.initializeMap(elementId, | console.log('[WidgetMap] Creating instance for element:', elementId, 'with config GeoJSON page:', configToUse.geoJsonPage); | ||
// 設定の深いコピーを確実に作成 | |||
const isolatedConfig = JSON.parse(JSON.stringify(configToUse)); | |||
const instance = window.WidgetMapManager.initializeMap(elementId, isolatedConfig); | |||
if (!instance) { | if (!instance) { | ||
throw new Error('Failed to create map instance'); | throw new Error('Failed to create map instance'); | ||
} | } | ||
console.log('[WidgetMap] Instance created with ID:', instance.id, 'GeoJSON page:', instance.config.geoJsonPage); | |||
console.log('[WidgetMap] Map instance created successfully:', elementId); | console.log('[WidgetMap] Map instance created successfully:', elementId); | ||
| 367行目: | 409行目: | ||
// DOMが読み込まれるまで待機 | // DOMが読み込まれるまで待機 | ||
if (document.readyState === 'loading') { | if (document.readyState === 'loading') { | ||
document.addEventListener('DOMContentLoaded', | document.addEventListener('DOMContentLoaded', function() { | ||
setTimeout(initializeThisWidgetMap, 50); | |||
}); | |||
} else { | } else { | ||
// 少し遅延させて確実にDOM要素が配置されるのを待つ | // 少し遅延させて確実にDOM要素が配置されるのを待つ | ||
setTimeout( | setTimeout(initializeThisWidgetMap, 50); | ||
} | } | ||
} | } | ||
| 378行目: | 422行目: | ||
executeInitialization(); | executeInitialization(); | ||
} else { | } else { | ||
// コアモジュールの読み込み待ち | // コアモジュールの読み込み待ち - このWidget専用の設定を保存 | ||
if (!window.WidgetMapPendingConfigs) { | |||
window.WidgetMapPendingConfigs = []; | |||
} | |||
window.WidgetMapPendingConfigs.push({ | |||
config: widgetInstanceConfig, | |||
initFunction: executeInitialization | |||
}); | |||
// 従来の初期化も保持(互換性のため) | |||
if (!window.WidgetMapPendingInitializations) { | if (!window.WidgetMapPendingInitializations) { | ||
window.WidgetMapPendingInitializations = []; | window.WidgetMapPendingInitializations = []; | ||
| 390行目: | 443行目: | ||
})(); | })(); | ||
</script> | </script> | ||
</includeonly> | </includeonly> | ||