"use strict"; import {MapDriverInterface} from "../Interfaces/MapDriverInterface.ecma.js"; import {EventModel} from "../Models/EventModel.ecma.js"; import {Utils} from "../Utils/Utils.ecma.js"; /** * @typedef {import("../Application/RoutesMaker.ecma.js").RoutesMaker} RoutesMaker * @typedef {import("../Models/DotModel.ecma.js").DotModel} DotModel */ /** * @class * @constructor * @param {!RoutesMaker} routes_maker * @param {?(Object.|Array.)} [inputs = null] * @returns {void} * @access public * @static */ export const LeafLetOSMDriver = (function(){ /** * @constructs LeafLetOSMDriver * @param {!RoutesMaker} routes_maker * @param {?(Object.|Array.)} [inputs = null] * @returns {void} * @access public * @static */ const LeafLetOSMDriver = function(routes_maker, inputs = null){ /** @type {LeafLetOSMDriver} */ const self = this; /** @type {L.Map} */ this.map = null; /** @type {HTMLElement} */ this.box = null; /** @type {EventModel} */ this.on_click = new EventModel(); /** * @returns {void} * @access private */ const constructor = () => { MapDriverInterface.check(self); }; /** * @param {!HTMLElement} box * @returns {void} * @access public */ this.build = box => { /** @type {string} */ let id; if(box.hasAttribute("id")) id = box.getAttribute("id"); else box.setAttribute("id", id = routes_maker.random_keys.get()); L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", { maxZoom : 19, attribution : '© OpenStreetMap' }).addTo(self.map = L.map(id).setView(routes_maker.get_user_coordenates(), 13)); routes_maker.base.on_change.add(_ => { self.map.invalidateSize(true); }); self.map.on("click", event => { self.on_click.execute(event.latlng.lng, event.latlng.lat); }); }; const set_value = (object, dom, name, value) => { object[dom] && object[dom].setAttribute(name, value); }; const update_object_attributes = (item, object) => { for(const key in item.attributes){ /** @type {string} */ const name = "data-" + Utils.to_kebab(key); ["_path", "_icon", "_shadow"].forEach(dom => { set_value(object, dom, name, item.attributes[key]); }); }; } const set_attributes = (item, object) => { object.on("add", () => { update_object_attributes(item, object); }); update_object_attributes(item, object); }; this.update_attributes = item => { ["marker", "line"].forEach(key => { item[key] && update_object_attributes(item, item[key]); }); }; /** * @param {!DotModel} dot * @returns {void} * @access public */ this.add_dot = (dot, attributes = {}) => { /** @type {[number, number]} */ const point = dot.get_point(); (dot.marker = L.marker(point, {draggable : true})).addTo(self.map); self.redraw_dot_lines(dot); dot.marker.on("click", event => { dot.on_click.execute(); }); dot.marker.on("dragend", event => { /** @type {L.LatLng} */ const coordenates = event.target.getLatLng(); dot.on_drop.execute(coordenates.lng, coordenates.lat); }); set_attributes(dot, dot.marker); }; /** * @param {!DotModel} dot * @returns {void} * @access public */ this.remove_dot_line = dot => { if(dot.line){ self.map.removeLayer(dot.line); dot.line = null; }; }; /** * @param {!DotModel} dot * @returns {void} * @access public */ this.remove_dot_lines = dot => { dot.i && self.remove_dot_line(dot); dot.i + 1 < dot.route.dots.length && self.remove_dot_line(dot.route.dots[dot.i + 1]); }; /** * @param {!DotModel} dot * @returns {void} * @access public */ this.redraw_dot_lines = dot => { /** @type {[number, number]} */ const point = dot.get_point(), /** @type {DotModel|null} */ previous = dot.i ? dot.route.dots[dot.i - 1] : null, /** @type {DotModel|null} */ next = dot.i + 1 < dot.route.dots.length ? dot.route.dots[dot.i + 1] : null; self.remove_dot_lines(dot); if(previous){ (dot.line = L.polyline([previous.get_point(), point])).addTo(self.map); set_attributes(dot, dot.line); }; if(next){ (next.line = L.polyline([point, next.get_point()])).addTo(self.map); set_attributes(dot, next.line); }; }; /** * @param {!DotModel} dot * @returns {void} * @access public */ this.remove_dot = dot => { self.remove_dot_lines(dot); self.map.removeLayer(dot.marker); }; this.create_overlay = overlay => { const item = document.createElementNS("http://www.w3.org/2000/svg", "svg"); item.innerHTML = overlay.data.replace(/<\/?svg([^>]*)>/gi, (_, data) => { data.matchAll(/ ([^= ]+)="([^"]*)"/g).forEach(([_, key, value]) => { item.setAttribute(key, value); }); return ""; }).replace(/(<([^ >]+) [^\/>]+) \/>/g, "$1>"); (overlay.item = L.svgOverlay(item, L.latLngBounds(overlay.position.get_point(), overlay.size.get_point()))).addTo(self.map); (overlay.from = L.marker(overlay.position.get_point(), {draggable : true})).addTo(self.map); (overlay.to = L.marker(overlay.size.get_point(), {draggable : true})).addTo(self.map); overlay.from.on("dragend", event => { /** @type {L.LatLng} */ const coordenates = event.target.getLatLng(); overlay.on_change_position.execute(coordenates.lng, coordenates.lat); }); overlay.to.on("dragend", event => { /** @type {L.LatLng} */ const coordenates = event.target.getLatLng(); overlay.on_change_size.execute(coordenates.lng, coordenates.lat); }); }; this.update_overalay = overlay => { overlay.item.setBounds(L.latLngBounds(overlay.position.get_point(), overlay.size.get_point())); }; constructor(); }; return LeafLetOSMDriver; })();