#wip: Routes sysmte started in GUI.
This commit is contained in:
		
							parent
							
								
									d6345aacdc
								
							
						
					
					
						commit
						8155e40a95
					
				@ -5,6 +5,8 @@ import {EventModel} from "../Models/EventModel.ecma.js";
 | 
			
		||||
import {BaseView} from "../Views/BaseView.ecma.js";
 | 
			
		||||
import {MenuView} from "../Views/MenuView.ecma.js";
 | 
			
		||||
import {MapView} from "../Views/MapView.ecma.js";
 | 
			
		||||
import {RoutesManager} from "../Managers/RoutesManager.ecma.js";
 | 
			
		||||
import {RandomKeysManager} from "../Managers/RandomKeysManager.ecma.js";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @callback routes_maker_ready_callback
 | 
			
		||||
@ -52,6 +54,10 @@ export const RoutesMaker = (function(){
 | 
			
		||||
        this.menu = new MenuView(self);
 | 
			
		||||
        /** @type {MapView} */
 | 
			
		||||
        this.map = new MapView(self);
 | 
			
		||||
        /** @type {RandomKeysManager} */
 | 
			
		||||
        this.random_keys = new RandomKeysManager();
 | 
			
		||||
        /** @type {RoutesManager} */
 | 
			
		||||
        this.routes = new RoutesManager(self);
 | 
			
		||||
 | 
			
		||||
        const constructor = () => {
 | 
			
		||||
            self.on_ready.add(callback);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										163
									
								
								Public/ecma/Drivers/LeafLetOSMDriver.ecma.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										163
									
								
								Public/ecma/Drivers/LeafLetOSMDriver.ecma.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,163 @@
 | 
			
		||||
"use strict";
 | 
			
		||||
 | 
			
		||||
import {MapDriverInterface} from "../Interfaces/MapDriverInterface.ecma.js";
 | 
			
		||||
import {EventModel} from "../Models/EventModel.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.<string, any|null>|Array.<any|null>)} [inputs = null] 
 | 
			
		||||
 * @returns {void}
 | 
			
		||||
 * @access public
 | 
			
		||||
 * @static
 | 
			
		||||
 */
 | 
			
		||||
export const LeafLetOSMDriver = (function(){
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @constructs LeafLetOSMDriver
 | 
			
		||||
     * @param {!RoutesMaker} routes_maker 
 | 
			
		||||
     * @param {?(Object.<string, any|null>|Array.<any|null>)} [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 : '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
 | 
			
		||||
            }).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);
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * @param {!DotModel} dot 
 | 
			
		||||
         * @returns {void}
 | 
			
		||||
         * @access public
 | 
			
		||||
         */
 | 
			
		||||
        this.add_dot = dot => {
 | 
			
		||||
 | 
			
		||||
            /** @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);
 | 
			
		||||
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * @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);
 | 
			
		||||
            previous && (dot.line = L.polyline([previous.get_point(), point])).addTo(self.map);
 | 
			
		||||
            next && (next.line = L.polyline([point, next.get_point()])).addTo(self.map);
 | 
			
		||||
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * @param {!DotModel} dot 
 | 
			
		||||
         * @returns {void}
 | 
			
		||||
         * @access public
 | 
			
		||||
         */
 | 
			
		||||
        this.remove_dot = dot => {
 | 
			
		||||
            self.remove_dot_lines(dot);
 | 
			
		||||
            self.map.removeLayer(dot.marker);
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        constructor();
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return LeafLetOSMDriver;
 | 
			
		||||
})();
 | 
			
		||||
							
								
								
									
										110
									
								
								Public/ecma/Interfaces/MapDriverInterface.ecma.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										110
									
								
								Public/ecma/Interfaces/MapDriverInterface.ecma.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,110 @@
 | 
			
		||||
"use strict";
 | 
			
		||||
 | 
			
		||||
import {EventModel} from "../Models/EventModel.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.<string, any|null>|Array.<any|null>)} [inputs = null] 
 | 
			
		||||
 * @returns {void}
 | 
			
		||||
 * @access public
 | 
			
		||||
 * @static
 | 
			
		||||
 */
 | 
			
		||||
export const MapDriverInterface = (function(){
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @constructs MapDriverInterface
 | 
			
		||||
     * @param {!RoutesMaker} routes_maker 
 | 
			
		||||
     * @param {?(Object.<string, any|null>|Array.<any|null>)} [inputs = null] 
 | 
			
		||||
     * @returns {void}
 | 
			
		||||
     * @access public
 | 
			
		||||
     * @static
 | 
			
		||||
     */
 | 
			
		||||
    const MapDriverInterface = function(routes_maker, inputs = null){
 | 
			
		||||
 | 
			
		||||
        this.map = null;
 | 
			
		||||
        /** @type {HTMLElement} */
 | 
			
		||||
        this.box = null;
 | 
			
		||||
 | 
			
		||||
        /** @type {EventModel} */
 | 
			
		||||
        this.on_click = new EventModel();
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * @param {!HTMLElement} box 
 | 
			
		||||
         * @returns {void}
 | 
			
		||||
         * @access public
 | 
			
		||||
         */
 | 
			
		||||
        this.build = box => {};
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * @param {!DotModel} dot 
 | 
			
		||||
         * @returns {void}
 | 
			
		||||
         * @access public
 | 
			
		||||
         */
 | 
			
		||||
        this.add_dot = dot => {};
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * @param {!DotModel} dot 
 | 
			
		||||
         * @returns {void}
 | 
			
		||||
         * @access public
 | 
			
		||||
         */
 | 
			
		||||
        this.remove_dot_line = dot => {};
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * @param {!DotModel} dot 
 | 
			
		||||
         * @returns {void}
 | 
			
		||||
         * @access public
 | 
			
		||||
         */
 | 
			
		||||
        this.remove_dot_lines = dot => {};
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * @param {!DotModel} dot 
 | 
			
		||||
         * @returns {void}
 | 
			
		||||
         * @access public
 | 
			
		||||
         */
 | 
			
		||||
        this.redraw_dot_lines = dot => {};
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * @param {!DotModel} dot 
 | 
			
		||||
         * @returns {void}
 | 
			
		||||
         * @access public
 | 
			
		||||
         */
 | 
			
		||||
        this.remove_dot = dot => {};
 | 
			
		||||
        
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param {?any} item 
 | 
			
		||||
     * @returns {boolean}
 | 
			
		||||
     * @access public
 | 
			
		||||
     * @static
 | 
			
		||||
     */
 | 
			
		||||
    MapDriverInterface.check = item => {
 | 
			
		||||
        
 | 
			
		||||
        /** @type {boolean} */
 | 
			
		||||
        let ok = !!item
 | 
			
		||||
        
 | 
			
		||||
        if(ok)
 | 
			
		||||
            [
 | 
			
		||||
                "map", "box", "on_click", "build", "add_dot", "remove_dot_line", 
 | 
			
		||||
                "remove_dot_lines", "redraw_dot_lines", "remove_dot"
 | 
			
		||||
            ].forEach(key => {
 | 
			
		||||
                if(item[key] === undefined){
 | 
			
		||||
                    console.error([item, key, "attribute_not_exists"]);
 | 
			
		||||
                    ok && (ok = false);
 | 
			
		||||
                };
 | 
			
		||||
            });
 | 
			
		||||
        else 
 | 
			
		||||
            console.error([item, null, "null_empty_undefined"]);
 | 
			
		||||
 | 
			
		||||
        return ok;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return MapDriverInterface;
 | 
			
		||||
})();
 | 
			
		||||
							
								
								
									
										93
									
								
								Public/ecma/Managers/RandomKeysManager.ecma.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										93
									
								
								Public/ecma/Managers/RandomKeysManager.ecma.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,93 @@
 | 
			
		||||
"use strict";
 | 
			
		||||
 | 
			
		||||
import {Utils} from "../Utils/Utils.ecma.js";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @class
 | 
			
		||||
 * @constructor
 | 
			
		||||
 * @param {?(Object.<string, any|null>|Array.<any|null>)} [inputs = null] 
 | 
			
		||||
 * @returns {void}
 | 
			
		||||
 * @access public
 | 
			
		||||
 * @static
 | 
			
		||||
 */
 | 
			
		||||
export const RandomKeysManager = (function(){
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @constructs RandomKeysManager
 | 
			
		||||
     * @param {?(Object.<string, any|null>|Array.<any|null>)} [inputs = null] 
 | 
			
		||||
     * @returns {void}
 | 
			
		||||
     * @access private
 | 
			
		||||
     * @static
 | 
			
		||||
     */
 | 
			
		||||
    const RandomKeysManager = function(inputs = null){
 | 
			
		||||
 | 
			
		||||
        /** @type {Array.<string>} */
 | 
			
		||||
        const keys = [], 
 | 
			
		||||
              /** @type {string|Array.<string>} */
 | 
			
		||||
              alphabet = Utils.get_value("alphabet", inputs, "qwertyuiopasdfghjklzxcvbnm1234567890QWERTYUIOPASDFGHJKLZXCVBNM"), 
 | 
			
		||||
              /** @type {number} */
 | 
			
		||||
              length = Utils.get_value("length", inputs, 11);
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * @returns {string}
 | 
			
		||||
         * @access public
 | 
			
		||||
         */
 | 
			
		||||
        this.get = () => {
 | 
			
		||||
 | 
			
		||||
            /** @type {string} */
 | 
			
		||||
            let key;
 | 
			
		||||
            /** @type {number} */
 | 
			
		||||
            const l = alphabet.length;
 | 
			
		||||
 | 
			
		||||
            do{
 | 
			
		||||
                key = "";
 | 
			
		||||
                while((key += alphabet[Math.random() * l >> 0]).length < length);
 | 
			
		||||
            }while(
 | 
			
		||||
                keys.includes(key) || 
 | 
			
		||||
                /^[^a-z_]/.test(key) || 
 | 
			
		||||
                document.querySelector("." + key + ",#" + key + ",[name=" + key + "]")
 | 
			
		||||
            );
 | 
			
		||||
            keys.includes(key);
 | 
			
		||||
 | 
			
		||||
            return key;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * @param {...string} set  
 | 
			
		||||
         * @returns {void}
 | 
			
		||||
         * @access public
 | 
			
		||||
         */
 | 
			
		||||
        this.remove = (...set) => {
 | 
			
		||||
            set.forEach(key => {
 | 
			
		||||
 | 
			
		||||
                /** @type {number} */
 | 
			
		||||
                const i = keys.indexOf(key);
 | 
			
		||||
 | 
			
		||||
                i != -1 && keys.splice(i, 1);
 | 
			
		||||
 | 
			
		||||
            });
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * @param  {...string} set 
 | 
			
		||||
         * @returns {void}
 | 
			
		||||
         * @access public
 | 
			
		||||
         */
 | 
			
		||||
        this.add = (...set) => {
 | 
			
		||||
            set.forEach(key => {
 | 
			
		||||
                keys.includes(key) || keys.push(key);
 | 
			
		||||
            });
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * @returns {void}
 | 
			
		||||
         * @access public
 | 
			
		||||
         */
 | 
			
		||||
        this.empty = () => {
 | 
			
		||||
            keys.splice(0, keys.length);
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return RandomKeysManager;
 | 
			
		||||
})();
 | 
			
		||||
							
								
								
									
										37
									
								
								Public/ecma/Managers/RoutesManager.ecma.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										37
									
								
								Public/ecma/Managers/RoutesManager.ecma.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,37 @@
 | 
			
		||||
"use strict";
 | 
			
		||||
 | 
			
		||||
import {RouteModel} from "../Models/RouteModel.ecma.js";
 | 
			
		||||
 | 
			
		||||
export const RoutesManager = (function(){
 | 
			
		||||
 | 
			
		||||
    const  RoutesManager = function(routes_maker){
 | 
			
		||||
 | 
			
		||||
        const routes = {};
 | 
			
		||||
 | 
			
		||||
        this.get = key => routes[key = RouteModel.to_key(key)] ? routes[key] : null;
 | 
			
		||||
 | 
			
		||||
        this.add = (name, key = null) => {
 | 
			
		||||
 | 
			
		||||
            let route = null;
 | 
			
		||||
 | 
			
		||||
            (key || (key = RouteModel.to_key(name))) && 
 | 
			
		||||
            !routes[key] && 
 | 
			
		||||
            (route = routes[key] = new RouteModel(routes_maker, name, key));
 | 
			
		||||
 | 
			
		||||
            return route;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        this.remove = key => {
 | 
			
		||||
            if(routes[key = RouteModel.to_key(key)])
 | 
			
		||||
                delete routes[key];
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        this.get_data = () => Object.keys(routes).reduce((dictionary, key) => {
 | 
			
		||||
            dictionary[key] = [routes[key].name, routes[key].dots.map(dot => [dot.longitude, dot.latitude])];
 | 
			
		||||
            return dictionary;
 | 
			
		||||
        }, {});
 | 
			
		||||
        
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return RoutesManager;
 | 
			
		||||
})();
 | 
			
		||||
@ -2,10 +2,14 @@
 | 
			
		||||
 | 
			
		||||
import {EventModel} from "./EventModel.ecma.js";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @typedef {import("./RouteModel.ecma.js").RouteModel} RouteModel
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @class
 | 
			
		||||
 * @constructor
 | 
			
		||||
 * @param {!L.Map} map 
 | 
			
		||||
 * @param {!RouteModel} route 
 | 
			
		||||
 * @param {!number} x 
 | 
			
		||||
 * @param {!number} y 
 | 
			
		||||
 * @param {!number} i 
 | 
			
		||||
@ -18,7 +22,7 @@ export const DotModel = (function(){
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @constructs DotModel
 | 
			
		||||
     * @param {!L.Map} map 
 | 
			
		||||
     * @param {!RouteModel} route 
 | 
			
		||||
     * @param {!number} x 
 | 
			
		||||
     * @param {!number} y 
 | 
			
		||||
     * @param {!number} i 
 | 
			
		||||
@ -27,134 +31,141 @@ export const DotModel = (function(){
 | 
			
		||||
     * @access private
 | 
			
		||||
     * @statix
 | 
			
		||||
     */
 | 
			
		||||
    const DotModel = function(map, x, y, i, dots){
 | 
			
		||||
    const DotModel = function(route, longitude, latitude, i){
 | 
			
		||||
 | 
			
		||||
        /** @type {DotModel} */
 | 
			
		||||
        const self = this;
 | 
			
		||||
 | 
			
		||||
        /** @type {Array.<L.Map>} */
 | 
			
		||||
        this.map = map;
 | 
			
		||||
        /** @type {RouteModel} */
 | 
			
		||||
        this.route = route;
 | 
			
		||||
        /** @type {number} */
 | 
			
		||||
        this.i = i;
 | 
			
		||||
        /** @type {number} */
 | 
			
		||||
        this.x = x;
 | 
			
		||||
        this.longitude = longitude;
 | 
			
		||||
        /** @type {number} */
 | 
			
		||||
        this.y = y;
 | 
			
		||||
        /** @type {L.Marker} */
 | 
			
		||||
        this.marker = L.marker([y, x], {draggable : true});
 | 
			
		||||
        /** @type {L.Pulyline|null} */
 | 
			
		||||
        this.latitude = latitude;
 | 
			
		||||
        /** @type {any|null} */
 | 
			
		||||
        this.marker = null;
 | 
			
		||||
        /** @type {any|null} */
 | 
			
		||||
        this.line = null;
 | 
			
		||||
        /** @type {Array.<DotModel>} */
 | 
			
		||||
        this.dots = dots;
 | 
			
		||||
        /** @type {number} */
 | 
			
		||||
        this.distance = 0;
 | 
			
		||||
 | 
			
		||||
        /** @type {EventModel} */
 | 
			
		||||
        this.on_change = new EventModel();
 | 
			
		||||
        /** @type {EventModel} */
 | 
			
		||||
        this.on_click = new EventModel();
 | 
			
		||||
        /** @type {EventModel} */
 | 
			
		||||
        this.on_drop = new EventModel();
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * @returns {void}
 | 
			
		||||
         * @access private
 | 
			
		||||
         */
 | 
			
		||||
        const constructor = () => {
 | 
			
		||||
            self.marker.addTo(map);
 | 
			
		||||
            dots.length && (self.line = L.polyline([dots[dots.length - 1].get_dot(), self.get_dot()]).addTo(self.map));
 | 
			
		||||
            self.marker.on("click", event => {
 | 
			
		||||
            route.routes_maker.map.driver.add_dot(self);
 | 
			
		||||
            self.on_click.add(() => {
 | 
			
		||||
                self.remove();
 | 
			
		||||
            });
 | 
			
		||||
            self.marker.on("dragend", event => {
 | 
			
		||||
                
 | 
			
		||||
                /** @type {L.LatLng} */
 | 
			
		||||
                const coordenates = event.target.getLatLng();
 | 
			
		||||
 | 
			
		||||
                self.x = coordenates.lng;
 | 
			
		||||
                self.y = coordenates.lat;
 | 
			
		||||
                
 | 
			
		||||
                self.remove_lines_linked();
 | 
			
		||||
                
 | 
			
		||||
                self.i < self.dots.length - 1 && (self.dots[self.i + 1].line = L.polyline([
 | 
			
		||||
                    self.dots[self.i + 1].get_dot(), 
 | 
			
		||||
                    self.get_dot()
 | 
			
		||||
                ])).addTo(self.map);
 | 
			
		||||
                self.i && (self.dots[self.i].line = L.polyline([
 | 
			
		||||
                    self.get_dot(), 
 | 
			
		||||
                    self.dots[self.i - 1].get_dot()
 | 
			
		||||
                ])).addTo(self.map);
 | 
			
		||||
 | 
			
		||||
            self.on_drop.add((_, longitude, latitude) => {
 | 
			
		||||
                self.longitude = longitude;
 | 
			
		||||
                self.latitude = latitude;
 | 
			
		||||
                self.route.routes_maker.map.driver.redraw_dot_lines(self);
 | 
			
		||||
                self.recalculate_distance();
 | 
			
		||||
            });
 | 
			
		||||
            self.recalculate_distance();
 | 
			
		||||
 | 
			
		||||
            });
 | 
			
		||||
            self.recalculate_distance();
 | 
			
		||||
            // self.marker.addTo(map);
 | 
			
		||||
            // dots.length && (self.line = L.polyline([dots[dots.length - 1].get_dot(), self.get_dot()]).addTo(self.map));
 | 
			
		||||
            // self.marker.on("click", event => {
 | 
			
		||||
            //     self.remove();
 | 
			
		||||
            // });
 | 
			
		||||
            // self.marker.on("dragend", event => {
 | 
			
		||||
                
 | 
			
		||||
            //     /** @type {L.LatLng} */
 | 
			
		||||
            //     const coordenates = event.target.getLatLng();
 | 
			
		||||
 | 
			
		||||
            //     self.longitude = coordenates.lng;
 | 
			
		||||
            //     self.latitude = coordenates.lat;
 | 
			
		||||
                
 | 
			
		||||
            //     self.remove_lines_linked();
 | 
			
		||||
                
 | 
			
		||||
            //     self.i < self.dots.length - 1 && (self.dots[self.i + 1].line = L.polyline([
 | 
			
		||||
            //         self.dots[self.i + 1].get_dot(), 
 | 
			
		||||
            //         self.get_dot()
 | 
			
		||||
            //     ])).addTo(self.map);
 | 
			
		||||
            //     self.i && (self.dots[self.i].line = L.polyline([
 | 
			
		||||
            //         self.get_dot(), 
 | 
			
		||||
            //         self.dots[self.i - 1].get_dot()
 | 
			
		||||
            //     ])).addTo(self.map);
 | 
			
		||||
 | 
			
		||||
            //     self.recalculate_distance();
 | 
			
		||||
 | 
			
		||||
            // });
 | 
			
		||||
            // self.recalculate_distance();
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * @returns {Object.<string, number>}
 | 
			
		||||
         * @returns {[number, number]}
 | 
			
		||||
         * @access public
 | 
			
		||||
         */
 | 
			
		||||
        this.get_leaflet_coordenates = () => ({
 | 
			
		||||
            lat : self.y, 
 | 
			
		||||
            lng : self.x
 | 
			
		||||
        });
 | 
			
		||||
        this.get_point = () => [self.latitude, self.longitude];
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * @returns {Object.<string, number>}
 | 
			
		||||
         * @access public
 | 
			
		||||
         */
 | 
			
		||||
        this.get_coordenates = () => ({
 | 
			
		||||
            latitude : self.y, 
 | 
			
		||||
            longitude : self.x
 | 
			
		||||
        });
 | 
			
		||||
        // /**
 | 
			
		||||
        //  * @returns {void}
 | 
			
		||||
        //  * @access public
 | 
			
		||||
        //  */
 | 
			
		||||
        // this.remove_line = () => {
 | 
			
		||||
        //     if(self.line){
 | 
			
		||||
        //         self.map.removeLayer(self.line);
 | 
			
		||||
        //         self.line = null;
 | 
			
		||||
        //     };
 | 
			
		||||
        // };
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * @returns {[string, number]}
 | 
			
		||||
         * @access public
 | 
			
		||||
         */
 | 
			
		||||
        this.get_dot = () => [self.y, self.x];
 | 
			
		||||
        // /**
 | 
			
		||||
        //  * @returns {void}
 | 
			
		||||
        //  * @access public
 | 
			
		||||
        //  */
 | 
			
		||||
        // self.remove_lines_linked = () => {
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * @returns {void}
 | 
			
		||||
         * @access public
 | 
			
		||||
         */
 | 
			
		||||
        this.remove_line = () => {
 | 
			
		||||
            if(self.line){
 | 
			
		||||
                self.map.removeLayer(self.line);
 | 
			
		||||
                self.line = null;
 | 
			
		||||
            };
 | 
			
		||||
        };
 | 
			
		||||
        //     /** @type {number} */
 | 
			
		||||
        //     const l = self.dots.length;
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * @returns {void}
 | 
			
		||||
         * @access public
 | 
			
		||||
         */
 | 
			
		||||
        self.remove_lines_linked = () => {
 | 
			
		||||
        //     [self.i, self.i + 1].forEach(i => {
 | 
			
		||||
        //         i && i < l && self.dots[i].remove_line();
 | 
			
		||||
        //     });
 | 
			
		||||
 | 
			
		||||
            /** @type {number} */
 | 
			
		||||
            const l = self.dots.length;
 | 
			
		||||
 | 
			
		||||
            [self.i, self.i + 1].forEach(i => {
 | 
			
		||||
                i && i < l && self.dots[i].remove_line();
 | 
			
		||||
            });
 | 
			
		||||
 | 
			
		||||
        };
 | 
			
		||||
        // };
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * @returns {void}
 | 
			
		||||
         * @access public
 | 
			
		||||
         */
 | 
			
		||||
        this.remove = () => {
 | 
			
		||||
            self.remove_lines_linked();
 | 
			
		||||
            self.i && self.i < self.dots.length - 1 && (self.dots[self.i + 1].line = L.polyline([
 | 
			
		||||
                self.dots[self.i + 1].get_dot(), 
 | 
			
		||||
                self.dots[self.i - 1].get_dot()
 | 
			
		||||
            ])).addTo(self.map);
 | 
			
		||||
            self.dots.splice(self.i, 1);
 | 
			
		||||
            console.log(["A", self.distance]);
 | 
			
		||||
            self.dots[self.i + 1].recalculate_distance();
 | 
			
		||||
            console.log(["B", self.distance]);
 | 
			
		||||
            self.map.removeLayer(self.marker);
 | 
			
		||||
            self.dots.slice(self.i).forEach(dot => {
 | 
			
		||||
 | 
			
		||||
            const not_unique = self.i && self.i + 1 < route.dots.length;
 | 
			
		||||
 | 
			
		||||
            route.routes_maker.map.driver.remove_dot(self);
 | 
			
		||||
            route.dots.splice(self.i, 1);
 | 
			
		||||
            route.dots.slice(self.i).forEach(dot => {
 | 
			
		||||
                dot.i --;
 | 
			
		||||
            });
 | 
			
		||||
            not_unique && route.routes_maker.map.driver.redraw_dot_lines(route.dots[self.i]);
 | 
			
		||||
            not_unique && route.dots[self.i].recalculate_distance();
 | 
			
		||||
 | 
			
		||||
            // self.remove_lines_linked();
 | 
			
		||||
            // self.i && self.i < self.dots.length - 1 && (self.dots[self.i + 1].line = L.polyline([
 | 
			
		||||
            //     self.dots[self.i + 1].get_dot(), 
 | 
			
		||||
            //     self.dots[self.i - 1].get_dot()
 | 
			
		||||
            // ])).addTo(self.map);
 | 
			
		||||
            // self.dots.splice(self.i, 1);
 | 
			
		||||
            // console.log(["A", self.distance]);
 | 
			
		||||
            // self.dots[self.i + 1].recalculate_distance();
 | 
			
		||||
            // console.log(["B", self.distance]);
 | 
			
		||||
            // self.map.removeLayer(self.marker);
 | 
			
		||||
            // self.dots.slice(self.i).forEach(dot => {
 | 
			
		||||
            //     dot.i --;
 | 
			
		||||
            // });
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
@ -169,14 +180,14 @@ export const DotModel = (function(){
 | 
			
		||||
            if(self.i){
 | 
			
		||||
 | 
			
		||||
                /** @type {DotModel} */
 | 
			
		||||
                const previous = self.dots[self.i - 1], 
 | 
			
		||||
                const previous = route.dots[self.i - 1], 
 | 
			
		||||
                      /** @type {number} */
 | 
			
		||||
                      pi_radians = Math.PI / 180, 
 | 
			
		||||
                      /** @type {number} */
 | 
			
		||||
                      angle = (
 | 
			
		||||
                          Math.sin((self.y - previous.y) * pi_radians / 2) ** 2 + 
 | 
			
		||||
                          Math.cos(self.y * pi_radians) * Math.cos(previous.y * pi_radians) * 
 | 
			
		||||
                          Math.sin((self.x - previous.x) * pi_radians / 2) ** 2
 | 
			
		||||
                          Math.sin((self.latitude - previous.latitude) * pi_radians / 2) ** 2 + 
 | 
			
		||||
                          Math.cos(self.latitude * pi_radians) * Math.cos(previous.latitude * pi_radians) * 
 | 
			
		||||
                          Math.sin((self.longitude - previous.longitude) * pi_radians / 2) ** 2
 | 
			
		||||
                      );
 | 
			
		||||
 | 
			
		||||
                self.distance = DotModel.EARTH_RADIUS * 2 * Math.atan2(angle ** .5, (1 - angle) ** .5);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										71
									
								
								Public/ecma/Models/RouteModel.ecma.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										71
									
								
								Public/ecma/Models/RouteModel.ecma.js
									
									
									
									
									
										Normal file
									
								
							@ -0,0 +1,71 @@
 | 
			
		||||
"use strict";
 | 
			
		||||
 | 
			
		||||
import {DotModel} from "./DotModel.ecma.js";
 | 
			
		||||
import {Check} from "../Utils/Check.ecma.js";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @typedef {import("../Application/RoutesMaker.ecma.js").RoutesMaker} RoutesMaker 
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @class
 | 
			
		||||
 * @constructor
 | 
			
		||||
 * @param {!RoutesMaker} routes_maker 
 | 
			
		||||
 * @param {!string} name 
 | 
			
		||||
 * @param {!string} key 
 | 
			
		||||
 * @returns {void}
 | 
			
		||||
 * @access public
 | 
			
		||||
 * @static
 | 
			
		||||
 */
 | 
			
		||||
export const RouteModel = (function(){
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @constructs RouteModel
 | 
			
		||||
     * @param {!RoutesMaker} routes_maker 
 | 
			
		||||
     * @param {!string} name 
 | 
			
		||||
     * @param {!string} key 
 | 
			
		||||
     * @returns {void}
 | 
			
		||||
     * @access public
 | 
			
		||||
     * @static
 | 
			
		||||
     */
 | 
			
		||||
    const RouteModel = function(routes_maker, name, key){
 | 
			
		||||
 | 
			
		||||
        /** @type {RouteModel} */
 | 
			
		||||
        const self = this;
 | 
			
		||||
 | 
			
		||||
        /** @type {RoutesMaker} */
 | 
			
		||||
        this.routes_maker = routes_maker;
 | 
			
		||||
        /** @type {Array.<DotModel>} */
 | 
			
		||||
        this.dots = [];
 | 
			
		||||
        /** @type {string} */
 | 
			
		||||
        this.name = name;
 | 
			
		||||
        /** @type {string} */
 | 
			
		||||
        this.key = key;
 | 
			
		||||
        /** @type {number} */
 | 
			
		||||
        this.from = 0;
 | 
			
		||||
 | 
			
		||||
        this.add_dot = (longitude, latitude) => {
 | 
			
		||||
 | 
			
		||||
            const dot = new DotModel(self, longitude, latitude, self.dots.length);
 | 
			
		||||
 | 
			
		||||
            self.dots.push(dot);
 | 
			
		||||
 | 
			
		||||
            return dot;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        this.get_distance = (...slice) => (
 | 
			
		||||
            slice.length ? self.dots.slice(...slice) : self.dots
 | 
			
		||||
        ).reduce((distance, dot) => distance + dot.distance);
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param {!string} name 
 | 
			
		||||
     * @returns {string}
 | 
			
		||||
     * @access public
 | 
			
		||||
     * @static
 | 
			
		||||
     */
 | 
			
		||||
    RouteModel.to_key = name => Check.is_string(name) && (name = name.trim()) ? name.replace(/_/g, "-").toLowerCase() : null;
 | 
			
		||||
 | 
			
		||||
    return RouteModel;
 | 
			
		||||
})();
 | 
			
		||||
@ -81,5 +81,15 @@ export const Check = (function(){
 | 
			
		||||
     */
 | 
			
		||||
    Check.is_array = item => item instanceof Array;
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param {?any} item 
 | 
			
		||||
     * @returns {boolean}
 | 
			
		||||
     * @access public
 | 
			
		||||
     * @static
 | 
			
		||||
     */
 | 
			
		||||
    Check.is_key = item => item && Check.is_string(item) && /^[a-z0-9_]+$/i.test(item);
 | 
			
		||||
 | 
			
		||||
    Check.is_dictionary = item => item && item.constructor == Object;
 | 
			
		||||
 | 
			
		||||
    return Check;
 | 
			
		||||
})();
 | 
			
		||||
@ -141,5 +141,98 @@ export const Utils = (function(){
 | 
			
		||||
        });
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    Utils.get_keys = keys => (
 | 
			
		||||
        Check.is_array(keys) ? keys.reduce((keys, key) => keys.concat(Utils.get_keys(key)), []) : 
 | 
			
		||||
        Check.is_key(keys) ? [keys] : 
 | 
			
		||||
    []);
 | 
			
		||||
 | 
			
		||||
    Utils.get_dictionary = (dictionaries, overwrite = false) => (
 | 
			
		||||
        Check.is_array(dictionaries) ? dictionaries.reduce((dictionary, item) => (overwrite ? {
 | 
			
		||||
            ...dictionary, 
 | 
			
		||||
            ...Utils.get_dictionary(item)
 | 
			
		||||
        } : {
 | 
			
		||||
            ...Utils.get_dictionary(item), 
 | 
			
		||||
            ...dictionary
 | 
			
		||||
        }), {}) : 
 | 
			
		||||
        Check.is_dictionary(dictionaries) ? dictionaries : 
 | 
			
		||||
    {});
 | 
			
		||||
 | 
			
		||||
    Utils.get_value = (keys, inputs, _default = null) => {
 | 
			
		||||
 | 
			
		||||
        const l = (keys = Utils.get_keys(keys)).length;
 | 
			
		||||
 | 
			
		||||
        if(l && Object.keys(inputs = Utils.get_dictionary(inputs)).length)
 | 
			
		||||
            for(let i = 0; i < l; i ++)
 | 
			
		||||
                if(inputs[keys[i]] !== undefined)
 | 
			
		||||
                    return inputs[keys[i]];
 | 
			
		||||
        return _default;
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    Utils.download = (data, mime = "application/octet-stream") => {
 | 
			
		||||
        console.log(data);
 | 
			
		||||
 | 
			
		||||
        const anchor = document.createElement("a"), 
 | 
			
		||||
                date = new Date();
 | 
			
		||||
 | 
			
		||||
        Utils.set_attributes(anchor, {
 | 
			
		||||
            download : "RoutesMaker." + (
 | 
			
		||||
                ("0000" + date.getFullYear()).slice(4) + 
 | 
			
		||||
                ("00" + (date.getMonth() + 1)).slice(2) + 
 | 
			
		||||
                ("00" + (date.getDate() + 1)).slice(2) + 
 | 
			
		||||
                ("00" + (date.getHours() + 1)).slice(2) + 
 | 
			
		||||
                ("00" + (date.getMinutes() + 1)).slice(2) + 
 | 
			
		||||
                ("00" + (date.getSeconds() + 1)).slice(2)
 | 
			
		||||
            ) + ".json", 
 | 
			
		||||
            href : "data:" + mime + ";base64," + btoa(Check.is_string(data) ? data : JSON.stringify(data)), 
 | 
			
		||||
            target : "_blank"
 | 
			
		||||
        });
 | 
			
		||||
        anchor.click();
 | 
			
		||||
        anchor.remove();
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    Utils.upload = callback => {
 | 
			
		||||
 | 
			
		||||
        const input = document.createElement("input");
 | 
			
		||||
 | 
			
		||||
        Utils.set_attributes(input, {
 | 
			
		||||
            type : "file", 
 | 
			
		||||
            multiple : false, 
 | 
			
		||||
            on_change : (item, event) => {
 | 
			
		||||
 | 
			
		||||
                let loaded = 0;
 | 
			
		||||
                const data = [], 
 | 
			
		||||
                      l = event.target.files.length, 
 | 
			
		||||
                      end = (i, file, string) => {
 | 
			
		||||
                          data[i] = {
 | 
			
		||||
                              name : file.name, 
 | 
			
		||||
                              last_modified_date : file.lastModified, 
 | 
			
		||||
                              size : file.size, 
 | 
			
		||||
                              mime : file.type, 
 | 
			
		||||
                              content : string
 | 
			
		||||
                          };
 | 
			
		||||
                          if(++ loaded == l){
 | 
			
		||||
                              input.remove();
 | 
			
		||||
                              Utils.execute(callback, ...data);
 | 
			
		||||
                          };
 | 
			
		||||
                      };
 | 
			
		||||
 | 
			
		||||
                [...event.target.files].forEach((file, i) => {
 | 
			
		||||
 | 
			
		||||
                    const reader = new FileReader();
 | 
			
		||||
 | 
			
		||||
                    reader.onload = () => {
 | 
			
		||||
                        end(i, file, reader.result);
 | 
			
		||||
                    };
 | 
			
		||||
                    reader.readAsText(file);
 | 
			
		||||
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
            }
 | 
			
		||||
        });
 | 
			
		||||
        input.click();
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return Utils;
 | 
			
		||||
})();
 | 
			
		||||
@ -1,18 +1,42 @@
 | 
			
		||||
"use strict";
 | 
			
		||||
 | 
			
		||||
import {Utils} from "../Utils/Utils.ecma.js";
 | 
			
		||||
import {EventModel} from "../Models/EventModel.ecma.js";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @typedef {import("../Application/RoutesMaker.ecma.js").RoutesMaker} RoutesMaker
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @class
 | 
			
		||||
 * @constructor
 | 
			
		||||
 * @param {!RoutesMaker} routes_maker 
 | 
			
		||||
 * @returns {void}
 | 
			
		||||
 * @access public
 | 
			
		||||
 * @static
 | 
			
		||||
 */
 | 
			
		||||
export const BaseView = (function(){
 | 
			
		||||
 | 
			
		||||
    const BaseView = function(routes_marker){
 | 
			
		||||
    /**
 | 
			
		||||
     * @constructs BaseView
 | 
			
		||||
     * @param {!RoutesMaker} routes_maker 
 | 
			
		||||
     * @returns {void}
 | 
			
		||||
     * @access public
 | 
			
		||||
     * @static
 | 
			
		||||
     */
 | 
			
		||||
    const BaseView = function(routes_maker){
 | 
			
		||||
 | 
			
		||||
        /** @type {BaseView} */
 | 
			
		||||
        const self = this;
 | 
			
		||||
 | 
			
		||||
        const constructor = () => {};
 | 
			
		||||
        /** @type {HTMLElement|null} */
 | 
			
		||||
        this.item = null;
 | 
			
		||||
        /** @type {EventModel|null} */
 | 
			
		||||
        this.on_change = null;
 | 
			
		||||
 | 
			
		||||
        this.build = position => {
 | 
			
		||||
            routes_marker.item_self || 
 | 
			
		||||
            (routes_marker.item_self = Utils.set_html(position, [
 | 
			
		||||
            self.item || 
 | 
			
		||||
            (self.on_change = new EventModel(self.item = Utils.set_html(position, [
 | 
			
		||||
                ["div", {
 | 
			
		||||
                    id : "routes-maker", 
 | 
			
		||||
                    class : "routes-maker", 
 | 
			
		||||
@ -21,11 +45,9 @@ export const BaseView = (function(){
 | 
			
		||||
                    data_url : "https://routesmaker.k3y.pw/", 
 | 
			
		||||
                    data_author : "KyMAN"
 | 
			
		||||
                }]
 | 
			
		||||
            ])[0]);
 | 
			
		||||
            ])[0]));
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        constructor();
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    return BaseView;
 | 
			
		||||
 | 
			
		||||
@ -2,64 +2,103 @@
 | 
			
		||||
 | 
			
		||||
import {Utils} from "../Utils/Utils.ecma.js";
 | 
			
		||||
import {EventModel} from "../Models/EventModel.ecma.js";
 | 
			
		||||
import {DotModel} from "../Models/DotModel.ecma.js";
 | 
			
		||||
import {ScreenModel} from "../Models/ScreenModel.ecma.js";
 | 
			
		||||
import {LeafLetOSMDriver} from "../Drivers/LeafLetOSMDriver.ecma.js";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @typedef {import("../Application/RoutesMaker.ecma.js").RoutesMaker} RoutesMaker
 | 
			
		||||
 * @typedef {import("../Interfaces/MapDriverInterface.ecma.js").MapDriverInterface} MapDriverInterface
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @class
 | 
			
		||||
 * @constructor
 | 
			
		||||
 * @param {!RoutesMaker} routes_maker
 | 
			
		||||
 * @returns {void}
 | 
			
		||||
 * @access public
 | 
			
		||||
 * @static
 | 
			
		||||
 */
 | 
			
		||||
export const MapView = (function(){
 | 
			
		||||
 | 
			
		||||
    const MapView = function(routes_marker){
 | 
			
		||||
    /**
 | 
			
		||||
     * @constructs MapView
 | 
			
		||||
     * @param {!RoutesMaker} routes_maker
 | 
			
		||||
     * @returns {void}
 | 
			
		||||
     * @access private
 | 
			
		||||
     * @static
 | 
			
		||||
     */
 | 
			
		||||
    const MapView = function(routes_maker){
 | 
			
		||||
 | 
			
		||||
        /** @type {MapView} */
 | 
			
		||||
        const self = this;
 | 
			
		||||
        /** @type {boolean} */
 | 
			
		||||
        let built = false, 
 | 
			
		||||
            /** @type {Array.<[number, number]>} */
 | 
			
		||||
            dots = [];
 | 
			
		||||
 | 
			
		||||
        /** @type {ScreenModel|null} */
 | 
			
		||||
        this.screen = null;
 | 
			
		||||
        /** @type {EventModel} */
 | 
			
		||||
        this.on_dots_change = new EventModel();
 | 
			
		||||
 | 
			
		||||
        /** @type {HTMLElement|null} */
 | 
			
		||||
        this.box = null;
 | 
			
		||||
        /** @type {L.Map|null} */
 | 
			
		||||
        this.map = null;
 | 
			
		||||
        /** @type {MapDriverInterface} */
 | 
			
		||||
        this.driver = null;
 | 
			
		||||
 | 
			
		||||
        const constructor = () => {};
 | 
			
		||||
 | 
			
		||||
        this.set_point = (longitude, latitude) => {
 | 
			
		||||
 | 
			
		||||
            const route_key = routes_maker.menu.get_route_selected();
 | 
			
		||||
 | 
			
		||||
            if(route_key){
 | 
			
		||||
                routes_maker.routes.get(route_key).add_dot(longitude, latitude).on_change.add((..._) => {
 | 
			
		||||
                    recalculate_total_distance();
 | 
			
		||||
                });
 | 
			
		||||
                recalculate_total_distance();
 | 
			
		||||
            };
 | 
			
		||||
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        this.build = () => {
 | 
			
		||||
            if(!built && routes_marker.item_self){
 | 
			
		||||
            if(!built && routes_maker.base.item){
 | 
			
		||||
                built = true;
 | 
			
		||||
                self.box = Utils.set_html(routes_marker.item_self, [
 | 
			
		||||
                (self.driver = new LeafLetOSMDriver(routes_maker)).build(self.box = Utils.set_html(routes_maker.base.item, [
 | 
			
		||||
                    ["div", {
 | 
			
		||||
                        id : "routes-maker-map", 
 | 
			
		||||
                        class : "map", 
 | 
			
		||||
                        data_show_markers : true, 
 | 
			
		||||
                        data_show_routes : true
 | 
			
		||||
                    }]
 | 
			
		||||
                ])[0];
 | 
			
		||||
                L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {
 | 
			
		||||
                    maxZoom : 19,
 | 
			
		||||
                    attribution : '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
 | 
			
		||||
                }).addTo(self.map = L.map("routes-maker-map").setView(routes_marker.get_user_coordenates(), 13));
 | 
			
		||||
                (self.screen = new ScreenModel(self.box)).on_change.add((i, x, y, box) => {
 | 
			
		||||
                    self.map.invalidateSize(true);
 | 
			
		||||
                });
 | 
			
		||||
                self.map.on("click", event => {
 | 
			
		||||
 | 
			
		||||
                    const dot = new DotModel(self.map, event.latlng.lng, event.latlng.lat, dots.length, dots);
 | 
			
		||||
 | 
			
		||||
                    dots.push(dot);
 | 
			
		||||
                    recalculate_total_distance();
 | 
			
		||||
                    dot.on_change.add(() => {
 | 
			
		||||
                        recalculate_total_distance();
 | 
			
		||||
                ])[0]);
 | 
			
		||||
                self.driver.on_click.add((_, longitude, latitude) => {
 | 
			
		||||
                    self.set_point(longitude, latitude);
 | 
			
		||||
                });
 | 
			
		||||
 | 
			
		||||
                });
 | 
			
		||||
                // L.tileLayer("https://tile.openstreetmap.org/{z}/{x}/{y}.png", {
 | 
			
		||||
                //     maxZoom : 19,
 | 
			
		||||
                //     attribution : '© <a href="http://www.openstreetmap.org/copyright">OpenStreetMap</a>'
 | 
			
		||||
                // }).addTo(self.map = L.map("routes-maker-map").setView(routes_maker.get_user_coordenates(), 13));
 | 
			
		||||
                // (self.screen = new ScreenModel(self.box)).on_change.add((i, x, y, box) => {
 | 
			
		||||
                //     self.map.invalidateSize(true);
 | 
			
		||||
                // });
 | 
			
		||||
                // self.map.on("click", event => {
 | 
			
		||||
 | 
			
		||||
                //     const dot = new DotModel(self.map, event.latlng.lng, event.latlng.lat, dots.length, dots);
 | 
			
		||||
 | 
			
		||||
                //     dots.push(dot);
 | 
			
		||||
                //     recalculate_total_distance();
 | 
			
		||||
                //     dot.on_change.add(() => {
 | 
			
		||||
                //         recalculate_total_distance();
 | 
			
		||||
                //     });
 | 
			
		||||
 | 
			
		||||
                // });
 | 
			
		||||
            };
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        const recalculate_total_distance = () => {
 | 
			
		||||
            routes_marker.item_self.querySelector(".map-menu [name=distance]").value = dots.reduce((distance, dot) => distance + dot.distance, 0) >> 0;
 | 
			
		||||
 | 
			
		||||
            const route_key = routes_maker.menu.get_route_selected();
 | 
			
		||||
 | 
			
		||||
            route_key && 
 | 
			
		||||
            (routes_maker.base.item.querySelector(".map-menu [name=distance]").value = routes_maker.routes.get(route_key).get_distance() >> 0);
 | 
			
		||||
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        constructor();
 | 
			
		||||
 | 
			
		||||
@ -2,19 +2,109 @@
 | 
			
		||||
 | 
			
		||||
import {Utils} from "../Utils/Utils.ecma.js";
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @callback menu_view_event_callback
 | 
			
		||||
 * @param {!HTMLElement} item 
 | 
			
		||||
 * @param {!Event} event 
 | 
			
		||||
 * @returns {void}
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
export const MenuView = (function(){
 | 
			
		||||
 | 
			
		||||
    const MenuView = function(routes_marker){
 | 
			
		||||
    const MenuView = function(routes_maker){
 | 
			
		||||
 | 
			
		||||
        const self = this;
 | 
			
		||||
        let built = false;
 | 
			
		||||
 | 
			
		||||
        const constructor = () => {};
 | 
			
		||||
 | 
			
		||||
        const load_database = (item, event) => {
 | 
			
		||||
            Utils.upload((...data) => {
 | 
			
		||||
                try{
 | 
			
		||||
 | 
			
		||||
                    const [layers, routes, menu] = JSON.parse(data[0].content);
 | 
			
		||||
 | 
			
		||||
                    menu.forEach(([type, key]) => {
 | 
			
		||||
                        if(routes[key]){
 | 
			
		||||
 | 
			
		||||
                            const [name, dots] = routes[key];
 | 
			
		||||
 | 
			
		||||
                            routes_maker.routes.add(name, key);
 | 
			
		||||
                            add_new_item(routes_maker[type].get(key), type);
 | 
			
		||||
                            dots.forEach(([longitude, latitude]) => {
 | 
			
		||||
                                routes_maker.map.set_point(longitude, latitude);
 | 
			
		||||
                            });
 | 
			
		||||
 | 
			
		||||
                        };
 | 
			
		||||
                    });
 | 
			
		||||
 | 
			
		||||
                }catch(exception){
 | 
			
		||||
                    console.error(exception);
 | 
			
		||||
                };
 | 
			
		||||
            });
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        const save_database = (item, event) => {
 | 
			
		||||
            Utils.download([
 | 
			
		||||
                [], 
 | 
			
		||||
                routes_maker.routes.get_data(), 
 | 
			
		||||
                [...routes_maker.base.item.querySelectorAll(".map-menu [data-field=items] li")].map(item => [
 | 
			
		||||
                    item.getAttribute("data-type"), 
 | 
			
		||||
                    item.getAttribute("data-key")
 | 
			
		||||
                ])
 | 
			
		||||
            ], "application/json");
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        const add_new_item = (object, type) => {
 | 
			
		||||
            object && select_item(Utils.set_html(".map-menu [data-field=items] ul", [
 | 
			
		||||
                ["li", {
 | 
			
		||||
                    data_type : type, 
 | 
			
		||||
                    data_name : object.name, 
 | 
			
		||||
                    data_key : object.key, 
 | 
			
		||||
                    data_selected : true, 
 | 
			
		||||
                    title : object.name
 | 
			
		||||
                }, [
 | 
			
		||||
                    ["span", {
 | 
			
		||||
                        class : "name", 
 | 
			
		||||
                        on_click : (item, event) => {
 | 
			
		||||
                            select_item(item.parentNode);
 | 
			
		||||
                        }
 | 
			
		||||
                    }, object.name]
 | 
			
		||||
                ]]
 | 
			
		||||
            ], routes_maker.base.item)[0]);
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        const add_new_route = (item, event) => {
 | 
			
		||||
            add_new_item(routes_maker.routes.add(item.parentNode.querySelector("[type=text]").value.trim()), "routes");
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        const add_new_layer = (item, event) => {
 | 
			
		||||
            add_new_item(null, "layers");
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        const select_item = item => {
 | 
			
		||||
            routes_maker.base.item.querySelectorAll(".map-menu [data-field=items] ul>[data-selected=true]").forEach(item => {
 | 
			
		||||
                item.setAttribute("data-selected", false);
 | 
			
		||||
            });
 | 
			
		||||
            item.setAttribute("data-selected", true);
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        const clear_item_name = (item, event) => {
 | 
			
		||||
            item.parentNode.querySelector("[type=text]").value = "";
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        const show_markers = (item, event) => {
 | 
			
		||||
            Utils.set_attributes(".map", {data_show_markers : item.checked}, routes_maker.base.item);
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        const show_routes = (item, event) => {
 | 
			
		||||
            Utils.set_attributes(".map", {data_show_routes : item.checked}, routes_maker.base.item);
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        this.build = () => {
 | 
			
		||||
            if(!built && routes_marker.item_self){
 | 
			
		||||
            if(!built && routes_maker.base.item){
 | 
			
		||||
                built = true;
 | 
			
		||||
                Utils.set_html(routes_marker.item_self, [
 | 
			
		||||
                Utils.set_html(routes_maker.base.item, [
 | 
			
		||||
                    ["form", {
 | 
			
		||||
                        class : "map-menu", 
 | 
			
		||||
                        method : "GET", 
 | 
			
		||||
@ -25,64 +115,42 @@ export const MenuView = (function(){
 | 
			
		||||
                            ["legend", {data_i18n : "menu"}, "Menu"], 
 | 
			
		||||
                            ["nav", null, [
 | 
			
		||||
                                ["ul", null, [
 | 
			
		||||
                                    ["li", {
 | 
			
		||||
                                        data_i : 0, 
 | 
			
		||||
                                        data_field : "distance", 
 | 
			
		||||
                                        data_i18n : "distance", 
 | 
			
		||||
                                        data_i18n_without : true, 
 | 
			
		||||
                                        title : "Distance"
 | 
			
		||||
                                    }, [
 | 
			
		||||
                                        ["label", {for : "distance"}, [
 | 
			
		||||
                                            ["span", {data_i18n : "distance"}, "Distance"], 
 | 
			
		||||
                                    MenuView.create_button("load_database", load_database, "Load database"), 
 | 
			
		||||
                                    MenuView.create_button("save_database", save_database, "Save database"), 
 | 
			
		||||
                                    MenuView.create_item("item_name", [
 | 
			
		||||
                                        ["label", {for : "item_name"}, [
 | 
			
		||||
                                            ["span", {data_i18n : "item_name"}, "Item name"], 
 | 
			
		||||
                                            ["input", {
 | 
			
		||||
                                                type : "text", 
 | 
			
		||||
                                                name : "item_name", 
 | 
			
		||||
                                                id : "item_name", 
 | 
			
		||||
                                                data_i18n : "item_name", 
 | 
			
		||||
                                                data_i18n_without : true, 
 | 
			
		||||
                                                placeholder : "Item name...", 
 | 
			
		||||
                                                value : ""
 | 
			
		||||
                                            }]
 | 
			
		||||
                                        ]], 
 | 
			
		||||
                                        MenuView.button("add_route", add_new_route, "Add route"), 
 | 
			
		||||
                                        MenuView.button("add_layer", add_new_layer, "Add layer"), 
 | 
			
		||||
                                        MenuView.button("clear", clear_item_name, "Clear")
 | 
			
		||||
                                    ], "Item name"), 
 | 
			
		||||
                                    MenuView.create_item("items", [["nav", null, [["ul", null]]]], "Items"), 
 | 
			
		||||
                                    MenuView.create_item("distance", [["label", {for : "distance"}, [
 | 
			
		||||
                                        ["span", {data_i18n : "distance"}, "Distance"], 
 | 
			
		||||
                                        ["input", {
 | 
			
		||||
                                            type : "number", 
 | 
			
		||||
                                            name : "distance", 
 | 
			
		||||
                                            readonly : true, 
 | 
			
		||||
                                                id : "distance"
 | 
			
		||||
                                            id : "distance", 
 | 
			
		||||
                                            data_i18n : "distance", 
 | 
			
		||||
                                            data_i18n_without : true, 
 | 
			
		||||
                                            placeholder : "Distance...", 
 | 
			
		||||
                                            value : 0
 | 
			
		||||
                                        }], 
 | 
			
		||||
                                        ["span", {data_i18n : "meters_symbol"}, "m"]
 | 
			
		||||
                                        ]]
 | 
			
		||||
                                    ]], 
 | 
			
		||||
                                    ["li", {
 | 
			
		||||
                                        data_i : 1, 
 | 
			
		||||
                                        data_field : "show-markers", 
 | 
			
		||||
                                        data_i18n : "show_markers", 
 | 
			
		||||
                                        data_i18n_without : true, 
 | 
			
		||||
                                        title : "Show markers"
 | 
			
		||||
                                    }, [
 | 
			
		||||
                                        ["label", {for : "show-markers"}, [
 | 
			
		||||
                                            ["input", {
 | 
			
		||||
                                                type : "checkbox", 
 | 
			
		||||
                                                name : "show_markers", 
 | 
			
		||||
                                                id : "show-markers", 
 | 
			
		||||
                                                checked : true, 
 | 
			
		||||
                                                on_change : (item, event) => {
 | 
			
		||||
                                                    Utils.set_attributes(".map", {data_show_markers : item.checked}, routes_marker.item_self);
 | 
			
		||||
                                                }
 | 
			
		||||
                                            }], 
 | 
			
		||||
                                            ["span", {data_i18n : "show_markers"}, "Show markers"]
 | 
			
		||||
                                        ]]
 | 
			
		||||
                                    ]], 
 | 
			
		||||
                                    ["li", {
 | 
			
		||||
                                        data_i : 2, 
 | 
			
		||||
                                        data_field : "show-routes", 
 | 
			
		||||
                                        data_i18n : "show_routes", 
 | 
			
		||||
                                        data_i18n_without : true, 
 | 
			
		||||
                                        title : "Show routes"
 | 
			
		||||
                                    }, [
 | 
			
		||||
                                        ["label", {for : "show-routes"}, [
 | 
			
		||||
                                            ["input", {
 | 
			
		||||
                                                type : "checkbox", 
 | 
			
		||||
                                                name : "show_routes", 
 | 
			
		||||
                                                id : "show-routes", 
 | 
			
		||||
                                                checked : true, 
 | 
			
		||||
                                                on_change : (item, event) => {
 | 
			
		||||
                                                    Utils.set_attributes(".map", {data_show_routes : item.checked}, routes_marker.item_self);
 | 
			
		||||
                                                }
 | 
			
		||||
                                            }], 
 | 
			
		||||
                                            ["span", {data_i18n : "show_routes"}, "Show routes"]
 | 
			
		||||
                                        ]]
 | 
			
		||||
                                    ]]
 | 
			
		||||
                                    ]]], "Distance"), 
 | 
			
		||||
                                    MenuView.create_checkbox("show_markers", true, show_markers, "Show markers"), 
 | 
			
		||||
                                    MenuView.create_checkbox("show_routes", true, show_routes, "Show routes")
 | 
			
		||||
                                ]]
 | 
			
		||||
                            ]]
 | 
			
		||||
                        ]]
 | 
			
		||||
@ -91,9 +159,108 @@ export const MenuView = (function(){
 | 
			
		||||
            };
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        /**
 | 
			
		||||
         * @returns {string|null}
 | 
			
		||||
         * @access public
 | 
			
		||||
         */
 | 
			
		||||
        this.get_route_selected = () => {
 | 
			
		||||
 | 
			
		||||
            /** @type {HTMLLIElement|null} */
 | 
			
		||||
            const item_selected = routes_maker.base.item.querySelector(".map-menu [data-field=items] [data-selected=true]");
 | 
			
		||||
 | 
			
		||||
            return item_selected ? item_selected.getAttribute("data-key") : null;
 | 
			
		||||
        };
 | 
			
		||||
 | 
			
		||||
        constructor();
 | 
			
		||||
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param {!string} name 
 | 
			
		||||
     * @returns {string}
 | 
			
		||||
     * @access public
 | 
			
		||||
     * @static
 | 
			
		||||
     */
 | 
			
		||||
    MenuView.get_id = name => name.replace(/_/g, "-").toLowerCase();
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param {!string} name 
 | 
			
		||||
     * @param {!Array.<Array.<any|null>>} item 
 | 
			
		||||
     * @param {!string} text 
 | 
			
		||||
     * @returns {[string, Object.<string, any>, Array.<any>]}
 | 
			
		||||
     * @access public
 | 
			
		||||
     * @static
 | 
			
		||||
     */
 | 
			
		||||
    MenuView.create_item = (name, item, text) => ["li", {
 | 
			
		||||
        data_field : name, 
 | 
			
		||||
        data_i18n : name, 
 | 
			
		||||
        data_i18n_without : true, 
 | 
			
		||||
        title : text
 | 
			
		||||
    }, item];
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param {!string} name 
 | 
			
		||||
     * @param {!boolean} checked 
 | 
			
		||||
     * @param {!menu_view_event_callback} action 
 | 
			
		||||
     * @param {!string} text 
 | 
			
		||||
     * @returns {[string, Object.<string, any>, Array.<any>]}
 | 
			
		||||
     * @access public
 | 
			
		||||
     * @static
 | 
			
		||||
     */
 | 
			
		||||
    MenuView.create_checkbox = (name, checked, action, text) => {
 | 
			
		||||
        
 | 
			
		||||
        /** @type {string} */
 | 
			
		||||
        const id = MenuView.get_id(name);
 | 
			
		||||
        
 | 
			
		||||
        return MenuView.create_item(name, [["label", {for : id}, [
 | 
			
		||||
            ["input", {
 | 
			
		||||
                type : "checkbox", 
 | 
			
		||||
                name : name, 
 | 
			
		||||
                id : id, 
 | 
			
		||||
                checked : checked, 
 | 
			
		||||
                on_change : action
 | 
			
		||||
            }], 
 | 
			
		||||
            ["span", {data_i18n : name}, text]
 | 
			
		||||
        ]]], text);
 | 
			
		||||
    };
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param {!string} name 
 | 
			
		||||
     * @param {!menu_view_event_callback} action 
 | 
			
		||||
     * @param {!string} text 
 | 
			
		||||
     * @returns {[string, Object.<string, any>, Array.<any>]}
 | 
			
		||||
     * @access public
 | 
			
		||||
     * @static
 | 
			
		||||
     */
 | 
			
		||||
    MenuView.button = (name, action, text) => ["button", {
 | 
			
		||||
        type : "button", 
 | 
			
		||||
        data_i18n : name, 
 | 
			
		||||
        data_i18n_without : true, 
 | 
			
		||||
        title : text, 
 | 
			
		||||
        on_click : action
 | 
			
		||||
    }, [
 | 
			
		||||
        ["span", {data_icon : name}], 
 | 
			
		||||
        ["span", {data_i18n : name}, text]
 | 
			
		||||
    ]];
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * @param {!string} name 
 | 
			
		||||
     * @param {!menu_view_event_callback} action 
 | 
			
		||||
     * @param {!string} text 
 | 
			
		||||
     * @returns {[string, Object.<string, any>, Array.<any>]}
 | 
			
		||||
     * @access public
 | 
			
		||||
     * @static
 | 
			
		||||
     */
 | 
			
		||||
    MenuView.create_button = (name, action, text) => MenuView.create_item(name, [["button", {
 | 
			
		||||
        type : "button", 
 | 
			
		||||
        data_i18n : name, 
 | 
			
		||||
        data_i18n_without : true, 
 | 
			
		||||
        title : text, 
 | 
			
		||||
        on_click : action
 | 
			
		||||
    }, [
 | 
			
		||||
        ["span", {data_icon : name}], 
 | 
			
		||||
        ["span", {data_i18n : name}, text]
 | 
			
		||||
    ]]], text)
 | 
			
		||||
 | 
			
		||||
    return MenuView;
 | 
			
		||||
})();
 | 
			
		||||
@ -27,7 +27,7 @@
 | 
			
		||||
 | 
			
		||||
            try{
 | 
			
		||||
                const routes_maker = new RoutesMaker("body", routes_maker => {
 | 
			
		||||
                    console.log("PASA");
 | 
			
		||||
                    // console.log("PASA");
 | 
			
		||||
                });
 | 
			
		||||
            }catch(exception){
 | 
			
		||||
                console.error(exception);
 | 
			
		||||
 | 
			
		||||
							
								
								
									
										20
									
								
								README.md
									
									
									
									
									
								
							
							
						
						
									
										20
									
								
								README.md
									
									
									
									
									
								
							@ -1,3 +1,21 @@
 | 
			
		||||
# RoutesMaker
 | 
			
		||||
 | 
			
		||||
Routes generator from set ordered points into Leaflet Map.
 | 
			
		||||
RoutesMaker es un pequeño proyecto para gestionar mapas sobre rutas y emplazamientos sobre un entorno vectorial interactuable al ser desarrollado sobre elementos XML/SVG integrados sobre el HTML. La idea es hacer un proyecto que perdure con escalabilidad y aislado del entorno generalista y comunitario a nivel de datos, siendo su propósito principalmente sobre el entorno cliente pese a haber una comunicación remota con las librerías de consumo para la gestión, visualización, interactuación y generación de mapas.
 | 
			
		||||
 | 
			
		||||
## Escalabilidad
 | 
			
		||||
 | 
			
		||||
Para poder llevar a cabo la escalabilidad haremos uso de "Drivers", un elemento que básicamente será un entorno de comunicación intermedio entre el entorno de la aplicación y el entorno de mapas. Dicho Driver ha de tener una serie de propiedades que han de cumplirse siempre:
 | 
			
		||||
 | 
			
		||||
* **box**: Éste será el elemento HTML donde se integre el mapa gráficamente. Normalmente suele ser una capa DIV.
 | 
			
		||||
* **map**: Éste será el objeto de Mapa o de gestión del mismo, como puede ser un objeto L.Map cara LeafLet.
 | 
			
		||||
* **build**: Éste será un método que construya el mapa gráficamente y lo instale internamente dentro del Driver.
 | 
			
		||||
* **on_click**: Éste será un gestor de eventos que salta cuando se haga Click dentro del mapa. Éste devolverá la longitud y la latitud en dicho orden sobre el o los Callbacks.
 | 
			
		||||
* **add_dot**: Éste será un método para añadir un punto al mapa.
 | 
			
		||||
* **remove_dot**: Éste será un método para eliminar un punto al mapa.
 | 
			
		||||
* **move_dot**: Éste será un método para mover un punto concreto en el mapa.
 | 
			
		||||
 | 
			
		||||
Como podemos ver, el Driver depende de que los objetos que genere el Objeto Mapa sean llamables, por lo que los puntos de gestión del mismo han de tener un elemento público que represente dicho objeto. Por lo tanto, y para prevalecer en un estándar, a dicho elemento lo llamaremos, dentro del Modelo de los Dots, **marker**. Cuando hacemos una llamada a cualquiera de las instrucciones del Driver y requiere del envío de puntos, éstos ya tiene Embedido el ObjectMap para que puedan interactuar.
 | 
			
		||||
 | 
			
		||||
Otro elemento que ha de llevar el Modelo de los Dots es el **line**, el cual será nulo en el caso del Dot 0, y el resto une sobre su previo.
 | 
			
		||||
 | 
			
		||||
Este método permite cambiar el Driver siempre que haga falta de una forma relativamente sencilla. La idea es controlar un mapa lógico con datos manejables por los intereses de la aplicación y éstos ser adaptados mediante métodos sobre un Driver.
 | 
			
		||||
		Loading…
	
		Reference in New Issue
	
	Block a user