#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.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);
|
||||
])[0]);
|
||||
self.driver.on_click.add((_, longitude, latitude) => {
|
||||
self.set_point(longitude, latitude);
|
||||
});
|
||||
self.map.on("click", event => {
|
||||
|
||||
const dot = new DotModel(self.map, event.latlng.lng, event.latlng.lat, dots.length, dots);
|
||||
// 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 => {
|
||||
|
||||
dots.push(dot);
|
||||
recalculate_total_distance();
|
||||
dot.on_change.add(() => {
|
||||
recalculate_total_distance();
|
||||
});
|
||||
// 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 : "distance",
|
||||
readonly : true,
|
||||
id : "distance"
|
||||
}],
|
||||
["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"]
|
||||
]]
|
||||
]]
|
||||
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",
|
||||
data_i18n : "distance",
|
||||
data_i18n_without : true,
|
||||
placeholder : "Distance...",
|
||||
value : 0
|
||||
}],
|
||||
["span", {data_i18n : "meters_symbol"}, "m"]
|
||||
]]], "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