| "use strict"; |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| |
| (function () { |
| const DB_NAME = "mobis-tiles", STORE = "tiles"; |
| let dbp = null; |
|
|
| function db() { |
| if (dbp) return dbp; |
| dbp = new Promise((resolve, reject) => { |
| let req; |
| try { req = indexedDB.open(DB_NAME, 1); } catch (e) { return reject(e); } |
| req.onupgradeneeded = () => req.result.createObjectStore(STORE); |
| req.onsuccess = () => resolve(req.result); |
| req.onerror = () => reject(req.error); |
| }).catch(() => null); |
| return dbp; |
| } |
|
|
| async function idbGet(key) { |
| const d = await db(); |
| if (!d) return null; |
| return new Promise((res) => { |
| try { |
| const r = d.transaction(STORE, "readonly").objectStore(STORE).get(key); |
| r.onsuccess = () => res(r.result || null); |
| r.onerror = () => res(null); |
| } catch (e) { res(null); } |
| }); |
| } |
|
|
| async function idbPut(key, blob) { |
| const d = await db(); |
| if (!d) return; |
| try { d.transaction(STORE, "readwrite").objectStore(STORE).put(blob, key); } catch (e) {} |
| } |
|
|
| if (!window.L || !L.TileLayer) return; |
|
|
| const CachedTileLayer = L.TileLayer.extend({ |
| createTile(coords, done) { |
| const tile = document.createElement("img"); |
| tile.setAttribute("role", "presentation"); |
| tile.alt = ""; |
| const url = this.getTileUrl(coords); |
|
|
| let settled = false; |
| const finish = () => { if (!settled) { settled = true; done(null, tile); } }; |
| tile.addEventListener("load", finish); |
| tile.addEventListener("error", finish); |
|
|
| const useBlob = (blob) => { |
| const obj = URL.createObjectURL(blob); |
| tile.addEventListener("load", () => { try { URL.revokeObjectURL(obj); } catch (e) {} }, { once: true }); |
| tile.src = obj; |
| }; |
|
|
| idbGet(url).then((blob) => { |
| if (blob) { useBlob(blob); return; } |
| if (!navigator.onLine) { finish(); return; } |
| fetch(url, { mode: "cors" }) |
| .then((r) => (r && r.ok) ? r.blob() : Promise.reject()) |
| .then((b) => { idbPut(url, b); useBlob(b); }) |
| .catch(() => { tile.src = url; }); |
| }).catch(() => { tile.src = url; }); |
|
|
| return tile; |
| }, |
| }); |
|
|
| |
| |
| window.makeTileLayer = function (template, opts) { |
| if (!("indexedDB" in window)) return L.tileLayer(template, opts); |
| return new CachedTileLayer(template, opts); |
| }; |
| })(); |
|
|