Created
September 10, 2019 06:05
-
-
Save fczbkk/0bbca7851dc05f166fe7485152a3c12e to your computer and use it in GitHub Desktop.
Robustný spôsob, ako dynamicky vložiť mapu z api.mapy.cz do stránky. Použité knižnice "gatedQueue" a "loadExternalScript" sú znovupoužiteľné.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
/** | |
* @typedef {Object} gatedQueueInterface | |
* @property {Function} openGate - Executes all functions currently in the queue. Functions added to the queue will be executed immediately, until the gate is closed again. | |
* @property {Function} closeGate - Closes the gate. Functions added to the queue will be executed only once the gate is opened again. | |
* @property {function(): boolean} isGateOpen - Checks whether the gate is currently open. | |
* @property {Function} addToQueue - Adds function(s) to the queue. Accepts single function or an array of functions. | |
* @property {Function} clearQueue - Removes all functions from the queue. | |
* @property {Function} processQueue - Calls all functions in the queue. Even if the gate is currently closed. | |
* @property {Function} getQueue - Returns copy of current queue. | |
*/ | |
/** | |
* Creates queue object filled with functions to be called once gate has been opened. | |
* This was primarily developed for mechanisms of asynchronously loading external dependencies while giving the ability to call these dependencies' methods before they have been loaded. | |
* @param {Object} [config] | |
* @param {Array.<Function>} [config.queue = []] | |
* @param {boolean} [isOpen = false] | |
* @return {{openGate: openGate, addToQueue: addToQueue, closeGate: closeGate, getQueue: (function(): *[]), clearQueue: clearQueue, processQueue: processQueue, isGateOpen: (function(): boolean)}} | |
*/ | |
export function createGatedQueue ({ | |
queue = [], | |
isOpen = false | |
} = {}) { | |
const openGate = () => { | |
processQueue() | |
isOpen = true | |
} | |
const closeGate = () => { | |
isOpen = false | |
} | |
const clearQueue = () => { | |
queue = [] | |
} | |
const addToQueue = (newItems) => { | |
queue = [].concat(queue, newItems) | |
if (isOpen) { | |
processQueue() | |
} | |
} | |
const processQueue = () => { | |
queue.forEach((fn) => fn()) | |
clearQueue() | |
} | |
const isGateOpen = () => isOpen | |
const getQueue = () => [].concat(queue) | |
if (isOpen) { | |
processQueue() | |
} | |
return { | |
openGate, | |
closeGate, | |
isGateOpen, | |
clearQueue, | |
addToQueue, | |
processQueue, | |
getQueue | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { createGatedQueue } from './gatedQueue.js' | |
const NOOP = () => {} | |
const IS_LOADED = '1' | |
const IS_NOT_LOADED = '0' | |
const SCRIPT_LOAD_QUEUES = {} | |
/** | |
* @typedef {Object} load_external_script_options | |
* @property {boolean} [async = true] - If set to `true`, the SCRIPT element will be created with "async" attribute. | |
*/ | |
/** | |
* Loads external script into the page. Makes sure the script is only inserted once. | |
* @param {string} url | |
* @param {load_external_script_options} [options] | |
* @return {Promise} - Called when script is inserted and loaded. | |
*/ | |
export function loadExternalScript (url, options = {}) { | |
return new Promise((resolve) => { | |
const existingScriptElement = findScriptElement(url) | |
if (existingScriptElement) { | |
if (existingScriptElement.dataset.loaded === IS_LOADED) { | |
resolve() | |
} else { | |
addToScriptLoadQueue(url, resolve) | |
} | |
} else { | |
createScriptElement(url, options, resolve) | |
} | |
}) | |
} | |
/** | |
* Finds SCRIPT element with given `url` as a "src" attribute. | |
* @param {string} url | |
* @return {Element | null} | |
*/ | |
export function findScriptElement (url) { | |
return document.head.querySelector(`script[src="${url}"]`) | |
} | |
/** | |
* Creates SCRIPT element. | |
* @param {string} url | |
* @param {load_external_script_options} [options] | |
* @param {Function} [onload] - Function to be called when script is inserted and loaded. | |
* @return {HTMLElement} - Inserted SCRIPT element. | |
*/ | |
export function createScriptElement (url, options = {}, onload = NOOP) { | |
const { async = true } = options | |
const scriptElement = document.createElement('script') | |
addToScriptLoadQueue(url, onload) | |
if (async) { | |
scriptElement.setAttribute('async', 'true') | |
} | |
scriptElement.dataset.loaded = IS_NOT_LOADED | |
scriptElement.onload = () => { | |
scriptElement.dataset.loaded = IS_LOADED | |
SCRIPT_LOAD_QUEUES[url].openGate() | |
} | |
document.head.appendChild(scriptElement) | |
// Set the "src" attribute as a last thing, otherwise eager browsers (e.g. IE) will start loading it too soon and miss the "onload" event. | |
scriptElement.setAttribute('src', url) | |
return scriptElement | |
} | |
function addToScriptLoadQueue (id, fn) { | |
if (typeof SCRIPT_LOAD_QUEUES[id] === 'undefined') { | |
SCRIPT_LOAD_QUEUES[id] = createGatedQueue({ queue: [fn] }) | |
} else { | |
SCRIPT_LOAD_QUEUES[id].addToQueue(fn) | |
} | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { loadExternalScript } from '../utils/loadExternalScript' | |
const LOADER_URL = 'https://api.mapy.cz/loader.js' | |
const LOADER_QUEUE = createGatedQueue() | |
const DEFAULT_LONGITUDE = 14.41790 | |
const DEFAULT_LATITUDE = 50.12655 | |
const DEFAULT_ZOOM = 7 | |
export function init () { | |
return new Promise((resolve) => { | |
LOADER_QUEUE.addToQueue(resolve) | |
loadExternalScript(LOADER_URL, { async: true }) | |
.then(() => { | |
// Seznam's loader object | |
const { Loader } = window | |
Loader.lang = 'cs' | |
Loader.async = true | |
Loader.load(null, { suggest: true }, () => { | |
createMapObject() | |
LOADER_QUEUE.openGate() | |
}) | |
}) | |
}) | |
} | |
function createMapObject ({ | |
longitude = DEFAULT_LONGITUDE, | |
latitude = DEFAULT_LATITUDE, | |
zoom = DEFAULT_ZOOM | |
} = {}) { | |
// TODO: dohladanie spravneho elementu, do ktoreho sa ma mapa vlozit | |
const mapElement = document.getElementById('mapWrapper') | |
const center = window.SMap.Coords.fromWGS84(longitude, latitude) | |
const map = new window.SMap(getMapElement(), center, zoom) | |
// TODO: tu sa nastavuje konfiguracia mapy | |
return map | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment