feat: Functional base done.
This commit is contained in:
parent
cdb5857149
commit
d6345aacdc
4
.gitignore
vendored
Normal file
4
.gitignore
vendored
Normal file
@ -0,0 +1,4 @@
|
||||
/Data
|
||||
/Public/data
|
||||
.sass-cache
|
||||
*.[Ss]ecrets.*
|
98
Public/ecma/Application/RoutesMaker.ecma.js
Normal file
98
Public/ecma/Application/RoutesMaker.ecma.js
Normal file
@ -0,0 +1,98 @@
|
||||
"use strict";
|
||||
|
||||
import {Utils} from "../Utils/Utils.ecma.js";
|
||||
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";
|
||||
|
||||
/**
|
||||
* @callback routes_maker_ready_callback
|
||||
* @param {!RoutesMaker} routes_maker
|
||||
* @returns {void}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @class
|
||||
* @constructor
|
||||
* @param {!(string|HTMLElement)} [position = "body"]
|
||||
* @param {?routes_maker_ready_callback} [callback = null]
|
||||
* @returns {void}
|
||||
* @access public
|
||||
* @static
|
||||
*/
|
||||
export const RoutesMaker = (function(){
|
||||
|
||||
/**
|
||||
* @constructs RoutesMaker
|
||||
* @param {!(string|HTMLElement)} [position = "body"]
|
||||
* @param {?routes_maker_ready_callback} [callback = null]
|
||||
* @returns {void}
|
||||
* @access private
|
||||
* @static
|
||||
*/
|
||||
const RoutesMaker = function(position = "body", callback = null){
|
||||
|
||||
/** @type {RoutesMaker} */
|
||||
const self = this;
|
||||
/** @type {number} */
|
||||
let latitude = 0,
|
||||
/** @type {number} */
|
||||
longitude = 0;
|
||||
|
||||
/** @type {HTMLElement|null} */
|
||||
this.item_self = null;
|
||||
|
||||
/** @type {EventModel} */
|
||||
this.on_ready = new EventModel();
|
||||
|
||||
/** @type {BaseView} */
|
||||
this.base = new BaseView(self);
|
||||
/** @type {MenuView} */
|
||||
this.menu = new MenuView(self);
|
||||
/** @type {MapView} */
|
||||
this.map = new MapView(self);
|
||||
|
||||
const constructor = () => {
|
||||
self.on_ready.add(callback);
|
||||
navigator.geolocation.getCurrentPosition(location => {
|
||||
longitude = location.coords.longitude;
|
||||
latitude = location.coords.latitude;
|
||||
build();
|
||||
}, () => {
|
||||
build();
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {void}
|
||||
* @access private
|
||||
*/
|
||||
const build = () => {
|
||||
Utils.preload(position, (position, asynchronous, ok) => {
|
||||
if(ok){
|
||||
try{
|
||||
self.base.build(position);
|
||||
self.map.build();
|
||||
self.menu.build();
|
||||
self.on_ready.autoexecute = true;
|
||||
self.on_ready.execute(self);
|
||||
}catch(exception){
|
||||
console.error(exception);
|
||||
};
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {[number, number]}
|
||||
* @access public
|
||||
*/
|
||||
this.get_user_coordenates = () => [latitude, longitude];
|
||||
|
||||
constructor();
|
||||
|
||||
};
|
||||
|
||||
return RoutesMaker;
|
||||
})();
|
199
Public/ecma/Models/DotModel.ecma.js
Normal file
199
Public/ecma/Models/DotModel.ecma.js
Normal file
@ -0,0 +1,199 @@
|
||||
"use strict";
|
||||
|
||||
import {EventModel} from "./EventModel.ecma.js";
|
||||
|
||||
/**
|
||||
* @class
|
||||
* @constructor
|
||||
* @param {!L.Map} map
|
||||
* @param {!number} x
|
||||
* @param {!number} y
|
||||
* @param {!number} i
|
||||
* @param {!Array.<DotModel>} dots
|
||||
* @returns {void}
|
||||
* @access public
|
||||
* @statix
|
||||
*/
|
||||
export const DotModel = (function(){
|
||||
|
||||
/**
|
||||
* @constructs DotModel
|
||||
* @param {!L.Map} map
|
||||
* @param {!number} x
|
||||
* @param {!number} y
|
||||
* @param {!number} i
|
||||
* @param {!Array.<DotModel>} dots
|
||||
* @returns {void}
|
||||
* @access private
|
||||
* @statix
|
||||
*/
|
||||
const DotModel = function(map, x, y, i, dots){
|
||||
|
||||
/** @type {DotModel} */
|
||||
const self = this;
|
||||
|
||||
/** @type {Array.<L.Map>} */
|
||||
this.map = map;
|
||||
/** @type {number} */
|
||||
this.i = i;
|
||||
/** @type {number} */
|
||||
this.x = x;
|
||||
/** @type {number} */
|
||||
this.y = y;
|
||||
/** @type {L.Marker} */
|
||||
this.marker = L.marker([y, x], {draggable : true});
|
||||
/** @type {L.Pulyline|null} */
|
||||
this.line = null;
|
||||
/** @type {Array.<DotModel>} */
|
||||
this.dots = dots;
|
||||
/** @type {number} */
|
||||
this.distance = 0;
|
||||
|
||||
/** @type {EventModel} */
|
||||
this.on_change = 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 => {
|
||||
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.recalculate_distance();
|
||||
|
||||
});
|
||||
self.recalculate_distance();
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {Object.<string, number>}
|
||||
* @access public
|
||||
*/
|
||||
this.get_leaflet_coordenates = () => ({
|
||||
lat : self.y,
|
||||
lng : self.x
|
||||
});
|
||||
|
||||
/**
|
||||
* @returns {Object.<string, number>}
|
||||
* @access public
|
||||
*/
|
||||
this.get_coordenates = () => ({
|
||||
latitude : self.y,
|
||||
longitude : self.x
|
||||
});
|
||||
|
||||
/**
|
||||
* @returns {[string, number]}
|
||||
* @access public
|
||||
*/
|
||||
this.get_dot = () => [self.y, self.x];
|
||||
|
||||
/**
|
||||
* @returns {void}
|
||||
* @access public
|
||||
*/
|
||||
this.remove_line = () => {
|
||||
if(self.line){
|
||||
self.map.removeLayer(self.line);
|
||||
self.line = null;
|
||||
};
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {void}
|
||||
* @access public
|
||||
*/
|
||||
self.remove_lines_linked = () => {
|
||||
|
||||
/** @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 => {
|
||||
dot.i --;
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @returns {void}
|
||||
* @access public
|
||||
*/
|
||||
this.recalculate_distance = () => {
|
||||
|
||||
/** @type {number} */
|
||||
const origin = self.distance || 0;
|
||||
|
||||
if(self.i){
|
||||
|
||||
/** @type {DotModel} */
|
||||
const previous = self.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
|
||||
);
|
||||
|
||||
self.distance = DotModel.EARTH_RADIUS * 2 * Math.atan2(angle ** .5, (1 - angle) ** .5);
|
||||
|
||||
}else
|
||||
self.distance = 0;
|
||||
|
||||
origin != self.distance && self.on_change.execute(self);
|
||||
|
||||
};
|
||||
|
||||
constructor();
|
||||
|
||||
};
|
||||
|
||||
/** @type {number} */
|
||||
DotModel.EARTH_RADIUS = 6371000;
|
||||
|
||||
return DotModel;
|
||||
})();
|
87
Public/ecma/Models/EventModel.ecma.js
Normal file
87
Public/ecma/Models/EventModel.ecma.js
Normal file
@ -0,0 +1,87 @@
|
||||
"use strict";
|
||||
|
||||
import {Check} from "../Utils/Check.ecma.js";
|
||||
import {Utils} from "../Utils/Utils.ecma.js";
|
||||
|
||||
/**
|
||||
* @callback event_model_callback
|
||||
* @param {!number} i
|
||||
* @param {...any} [parameters]
|
||||
* @returns {Array.<any|null>}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @class
|
||||
* @constructor
|
||||
* @returns {void}
|
||||
* @access public
|
||||
* @static
|
||||
*/
|
||||
export const EventModel = (function(){
|
||||
|
||||
/**
|
||||
* @constructs EventModel
|
||||
* @returns {void}
|
||||
* @access private
|
||||
* @static
|
||||
*/
|
||||
const EventModel = function(){
|
||||
|
||||
/** @type {EventModel} */
|
||||
const self = this,
|
||||
/** @type {Array.<event_model_callback>} */
|
||||
events = [];
|
||||
|
||||
/** @type {boolean} */
|
||||
this.autoexecute = false;
|
||||
|
||||
/**
|
||||
* @param {...any} [parameters]
|
||||
* @returns {Array.<any|null>}
|
||||
* @access public
|
||||
*/
|
||||
this.execute = (...parameters) => events.map((event, i) => event ? event(i, ...parameters) : null);
|
||||
|
||||
/**
|
||||
* @param {!event_model_callback} callback
|
||||
* @returns {number|null}
|
||||
* @access public
|
||||
*/
|
||||
this.add = callback => {
|
||||
|
||||
/** @type {number|null} */
|
||||
let i = null;
|
||||
|
||||
if(Check.is_function(callback)){
|
||||
if(self.autoexecute)
|
||||
Utils.execute(callback);
|
||||
else{
|
||||
|
||||
/** @type {number} */
|
||||
const l = events.length;
|
||||
|
||||
for(i = 0; i < l; i ++)
|
||||
if(!events[i])
|
||||
break;
|
||||
|
||||
events[i] = callback;
|
||||
|
||||
};
|
||||
};
|
||||
|
||||
return i;
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {!number} i
|
||||
* @returns {void}
|
||||
* @access public
|
||||
*/
|
||||
this.remove = i => {
|
||||
Check.is_index(i) && i < events.length && events[i] && (events[i] = null);
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
return EventModel;
|
||||
})();
|
65
Public/ecma/Models/ScreenModel.ecma.js
Normal file
65
Public/ecma/Models/ScreenModel.ecma.js
Normal file
@ -0,0 +1,65 @@
|
||||
"use strict";
|
||||
|
||||
import {EventModel} from "./EventModel.ecma.js";
|
||||
import {Utils} from "../Utils/Utils.ecma.js";
|
||||
|
||||
/**
|
||||
* @class
|
||||
* @constructor
|
||||
* @param {!(string|HTMLElement)} selector
|
||||
* @returns {void}
|
||||
* @access public
|
||||
* @static
|
||||
*/
|
||||
export const ScreenModel = (function(){
|
||||
|
||||
/**
|
||||
* @constructs ScreenModel
|
||||
* @param {!(string|HTMLElement)} selector
|
||||
* @returns {void}
|
||||
* @access private
|
||||
* @static
|
||||
*/
|
||||
const ScreenModel = function(selector){
|
||||
|
||||
/** @type {ScreenModel} */
|
||||
const self = this;
|
||||
|
||||
/** @type {number|null} */
|
||||
let interval = null;
|
||||
|
||||
/** @type {number} */
|
||||
this.x = 0;
|
||||
/** @type {number} */
|
||||
this.y = 0;
|
||||
/** @type {HTMLElement|null} */
|
||||
this.item = null;
|
||||
|
||||
/** @type {EventModel} */
|
||||
this.on_change = new EventModel();
|
||||
|
||||
/**
|
||||
* @returns {void}
|
||||
* @access private
|
||||
*/
|
||||
const constructor = () => {
|
||||
Utils.preload(selector, (item, asynchronous, ok) => {
|
||||
if(ok){
|
||||
self.item = item;
|
||||
interval = setInterval(() => {
|
||||
if(self.x != self.item.offsetWidth || self.y != self.item.offsetHeight){
|
||||
self.x = self.item.offsetWidth;
|
||||
self.y = self.item.offsetHeight;
|
||||
this.on_change.execute(self.x, self.y, self.item);
|
||||
};
|
||||
}, 100);
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
constructor();
|
||||
|
||||
};
|
||||
|
||||
return ScreenModel;
|
||||
})();
|
85
Public/ecma/Utils/Check.ecma.js
Normal file
85
Public/ecma/Utils/Check.ecma.js
Normal file
@ -0,0 +1,85 @@
|
||||
"use strict";
|
||||
|
||||
/**
|
||||
* @class
|
||||
* @constructor
|
||||
* @returns {void}
|
||||
* @access public
|
||||
* @static
|
||||
*/
|
||||
export const Check = (function(){
|
||||
|
||||
/**
|
||||
* @constructs Check
|
||||
* @returns {void}
|
||||
* @access private
|
||||
* @static
|
||||
*/
|
||||
const Check = function(){};
|
||||
|
||||
/**
|
||||
* @param {?any} item
|
||||
* @returns {boolean}
|
||||
* @access public
|
||||
* @static
|
||||
*/
|
||||
Check.is_function = item => typeof item == "function";
|
||||
|
||||
/**
|
||||
* @param {?any} item
|
||||
* @returns {boolean}
|
||||
* @access public
|
||||
* @static
|
||||
*/
|
||||
Check.is_number = item => typeof item == "number";
|
||||
|
||||
/**
|
||||
* @param {?any} item
|
||||
* @returns {boolean}
|
||||
* @access public
|
||||
* @static
|
||||
*/
|
||||
Check.is_integer = item => Check.is_number(item) && item == item >> 0;
|
||||
|
||||
/**
|
||||
* @param {?any} item
|
||||
* @returns {boolean}
|
||||
* @access public
|
||||
* @static
|
||||
*/
|
||||
Check.is_index = item => Check.is_integer(item) && item >= 0;
|
||||
|
||||
/**
|
||||
* @param {?any} item
|
||||
* @returns {boolean}
|
||||
* @access public
|
||||
* @static
|
||||
*/
|
||||
Check.is_html_object = item => item && item.constructor == Object;
|
||||
|
||||
/**
|
||||
* @param {?any} item
|
||||
* @returns {boolean}
|
||||
* @access public
|
||||
* @static
|
||||
*/
|
||||
Check.is_string = item => typeof item == "string";
|
||||
|
||||
/**
|
||||
* @param {?any} item
|
||||
* @returns {boolean}
|
||||
* @access public
|
||||
* @static
|
||||
*/
|
||||
Check.is_null_or_undefined = item => item === undefined || item === null;
|
||||
|
||||
/**
|
||||
* @param {?any} item
|
||||
* @returns {boolean}
|
||||
* @access public
|
||||
* @static
|
||||
*/
|
||||
Check.is_array = item => item instanceof Array;
|
||||
|
||||
return Check;
|
||||
})();
|
145
Public/ecma/Utils/Utils.ecma.js
Normal file
145
Public/ecma/Utils/Utils.ecma.js
Normal file
@ -0,0 +1,145 @@
|
||||
"use strict";
|
||||
|
||||
import {Check} from "./Check.ecma.js";
|
||||
|
||||
/**
|
||||
* @callback utils_preload_callback
|
||||
* @param {?HTMLElement} item
|
||||
* @param {!boolean} asynchronous
|
||||
* @param {!boolean} ok
|
||||
* @returns {void}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @callback utils_execute_callback
|
||||
* @param {...any} [paramenters]
|
||||
* @returns {any|null}
|
||||
*/
|
||||
|
||||
/**
|
||||
* @class
|
||||
* @constructor
|
||||
* @returns {void}
|
||||
* @access public
|
||||
* @static
|
||||
*/
|
||||
export const Utils = (function(){
|
||||
|
||||
/**
|
||||
* @constructs Utils
|
||||
* @returns {void}
|
||||
* @access private
|
||||
* @static
|
||||
*/
|
||||
const Utils = function(){};
|
||||
|
||||
/**
|
||||
* @param {!(string|HTMLElement)} selector
|
||||
* @param {!utils_preload_callback} callback
|
||||
* @param {!(Document|HTMLElement)} [root = document]
|
||||
* @param {!number} [timeout = 2000]
|
||||
* @returns {void}
|
||||
* @access public
|
||||
* @static
|
||||
*/
|
||||
Utils.preload = (selector, callback, root = document, timeout = 2000) => {
|
||||
if(!selector)
|
||||
callback(null, false, false);
|
||||
else if(Check.is_html_object(selector))
|
||||
callback(selector, false, true);
|
||||
else if(Check.is_string(selector) && (selector = selector.trim())){
|
||||
|
||||
/** @type {HTMLElement|null} */
|
||||
let item = null;
|
||||
|
||||
try{
|
||||
if(item = root.querySelector(selector)){
|
||||
callback(item, false, true);
|
||||
return;
|
||||
};
|
||||
}catch(exception){
|
||||
callback(null, false, false);
|
||||
return;
|
||||
};
|
||||
|
||||
/** @type {number} */
|
||||
const date = Date.now();
|
||||
/** @type {number} */
|
||||
let interval = setInterval(() => {
|
||||
if(item = root.querySelector(selector)){
|
||||
clearInterval(interval);
|
||||
callback(item, true, true);
|
||||
}else if(Date.now() - date > timeout){
|
||||
clearInterval(interval);
|
||||
callback(null, false, true);
|
||||
};
|
||||
}, 100);
|
||||
|
||||
}else
|
||||
callback(null, false, false);
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {!utils_execute_callback} callback
|
||||
* @param {...any} [parameters]
|
||||
* @returns {any|null}
|
||||
* @access public
|
||||
* @static
|
||||
*/
|
||||
Utils.execute = (callback, ...parameters) => Check.is_function(callback) ? callback(...parameters) : null;
|
||||
|
||||
/**
|
||||
* @param {!(string|HTMLElement)} selector
|
||||
* @param {!Object.<string, any|null>} attributes
|
||||
* @param {!(HTMLElement|Document)} [position = document]
|
||||
* @returns {void}
|
||||
* @access public
|
||||
* @static
|
||||
*/
|
||||
Utils.set_attributes = (selector, attributes, position = document) => {
|
||||
(Check.is_string(selector) ? position.querySelectorAll(selector) : [selector]).forEach(item => {
|
||||
for(const key in attributes){
|
||||
if(/^on_?/i.test(key))
|
||||
item.addEventListener(
|
||||
key.substring(2).replace(/[^a-z]+/g, "").toLowerCase(),
|
||||
event => Utils.execute(attributes[key], item, event)
|
||||
);
|
||||
else
|
||||
item.setAttribute(key.replace(/_|([A-Z])/g, (_, character) => {
|
||||
return character ? "-" + character.toLowerCase() : "-";
|
||||
}), attributes[key]);
|
||||
};
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
* @param {!(string|HTMLElement|Document)} selector
|
||||
* @param {!Array.<[string, Object.<string, any|null>|null, Array.<any>|null]} items
|
||||
* @param {!(HTMLElement|Document)} [position = document]
|
||||
* @returns {Array.<HTMLElement>}
|
||||
* @access public
|
||||
* @static
|
||||
*/
|
||||
Utils.set_html = (selector, items, position = document) => {
|
||||
|
||||
Check.is_string(selector) && (selector = position.querySelector(selector));
|
||||
|
||||
return items.map(([tag, attributes, childs]) => {
|
||||
|
||||
/** @type {HTMLElement} */
|
||||
const item = selector.appendChild(document.createElement(tag));
|
||||
|
||||
attributes && Utils.set_attributes(item, attributes);
|
||||
if(!Check.is_null_or_undefined(childs)){
|
||||
if(Check.is_string(childs))
|
||||
item.innerHTML = childs;
|
||||
else if(Check.is_array(childs))
|
||||
Utils.set_html(item, childs);
|
||||
};
|
||||
|
||||
return item;
|
||||
});
|
||||
};
|
||||
|
||||
return Utils;
|
||||
})();
|
32
Public/ecma/Views/BaseView.ecma.js
Normal file
32
Public/ecma/Views/BaseView.ecma.js
Normal file
@ -0,0 +1,32 @@
|
||||
"use strict";
|
||||
|
||||
import {Utils} from "../Utils/Utils.ecma.js";
|
||||
|
||||
export const BaseView = (function(){
|
||||
|
||||
const BaseView = function(routes_marker){
|
||||
|
||||
const self = this;
|
||||
|
||||
const constructor = () => {};
|
||||
|
||||
this.build = position => {
|
||||
routes_marker.item_self ||
|
||||
(routes_marker.item_self = Utils.set_html(position, [
|
||||
["div", {
|
||||
id : "routes-maker",
|
||||
class : "routes-maker",
|
||||
data_application : "RoutesMaker",
|
||||
data_git : "https://git.k3y.pw/KyMAN/RoutesMaker",
|
||||
data_url : "https://routesmaker.k3y.pw/",
|
||||
data_author : "KyMAN"
|
||||
}]
|
||||
])[0]);
|
||||
};
|
||||
|
||||
constructor();
|
||||
|
||||
};
|
||||
|
||||
return BaseView;
|
||||
})();
|
70
Public/ecma/Views/MapView.ecma.js
Normal file
70
Public/ecma/Views/MapView.ecma.js
Normal file
@ -0,0 +1,70 @@
|
||||
"use strict";
|
||||
|
||||
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";
|
||||
|
||||
export const MapView = (function(){
|
||||
|
||||
const MapView = function(routes_marker){
|
||||
|
||||
const self = this;
|
||||
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;
|
||||
|
||||
const constructor = () => {};
|
||||
|
||||
this.build = () => {
|
||||
if(!built && routes_marker.item_self){
|
||||
built = true;
|
||||
self.box = Utils.set_html(routes_marker.item_self, [
|
||||
["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();
|
||||
});
|
||||
|
||||
});
|
||||
};
|
||||
};
|
||||
|
||||
const recalculate_total_distance = () => {
|
||||
routes_marker.item_self.querySelector(".map-menu [name=distance]").value = dots.reduce((distance, dot) => distance + dot.distance, 0) >> 0;
|
||||
};
|
||||
|
||||
constructor();
|
||||
|
||||
};
|
||||
|
||||
return MapView;
|
||||
})();
|
99
Public/ecma/Views/MenuView.ecma.js
Normal file
99
Public/ecma/Views/MenuView.ecma.js
Normal file
@ -0,0 +1,99 @@
|
||||
"use strict";
|
||||
|
||||
import {Utils} from "../Utils/Utils.ecma.js";
|
||||
|
||||
export const MenuView = (function(){
|
||||
|
||||
const MenuView = function(routes_marker){
|
||||
|
||||
const self = this;
|
||||
let built = false;
|
||||
|
||||
const constructor = () => {};
|
||||
|
||||
this.build = () => {
|
||||
if(!built && routes_marker.item_self){
|
||||
built = true;
|
||||
Utils.set_html(routes_marker.item_self, [
|
||||
["form", {
|
||||
class : "map-menu",
|
||||
method : "GET",
|
||||
action : "#",
|
||||
on_submit : (form, event) => false
|
||||
}, [
|
||||
["fieldset", null, [
|
||||
["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"],
|
||||
["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"]
|
||||
]]
|
||||
]]
|
||||
]]
|
||||
]]
|
||||
]]
|
||||
]]
|
||||
]);
|
||||
};
|
||||
};
|
||||
|
||||
constructor();
|
||||
|
||||
};
|
||||
|
||||
return MenuView;
|
||||
})();
|
40
Public/index.html
Normal file
40
Public/index.html
Normal file
@ -0,0 +1,40 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<title>RoutesMaker</title>
|
||||
<meta http-equiv="content-type" content="text/html;charset=utf-8" />
|
||||
<meta charset="utf-8" />
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0" />
|
||||
|
||||
<link type="text/css;charset=utf-8" data-language="CSS3" rel="stylesheet" href="https://unpkg.com/leaflet@1.9.4/dist/leaflet.css" data-crossorigin="anonymous" charset="utf-8" />
|
||||
<link type="text/css;charset=utf-8" data-language="SASS/CSS3" rel="stylesheet" href="/scss/RoutesMaker.css" data-scss="/scss/RoutesMaker.scss" data-css-map="/scss/RoutesMaker.css.map" data-crossorigin="anonymous" charset="utf-8" />
|
||||
|
||||
<style data-type="text/css;charset=utf-8" data-language="CSS3" charset="utf-8">
|
||||
|
||||
html,body{
|
||||
height : 100%;
|
||||
margin : 0em;
|
||||
}
|
||||
|
||||
</style>
|
||||
|
||||
<script src="https://unpkg.com/leaflet@1.9.4/dist/leaflet.js"></script>
|
||||
|
||||
<script type="module" data-type="text/javascript;charset=utf-8" data-language="ECMAScript 2015" charset="utf-8">
|
||||
"use strict";
|
||||
|
||||
import {RoutesMaker} from "./ecma/Application/RoutesMaker.ecma.js";
|
||||
|
||||
try{
|
||||
const routes_maker = new RoutesMaker("body", routes_maker => {
|
||||
console.log("PASA");
|
||||
});
|
||||
}catch(exception){
|
||||
console.error(exception);
|
||||
};
|
||||
|
||||
</script>
|
||||
|
||||
</head>
|
||||
<body></body>
|
||||
</html>
|
23
Public/scss/RoutesMaker.css
Normal file
23
Public/scss/RoutesMaker.css
Normal file
@ -0,0 +1,23 @@
|
||||
.routes-maker {
|
||||
position: relative; }
|
||||
.routes-maker > .map {
|
||||
position: absolute; }
|
||||
.routes-maker, .routes-maker > .map {
|
||||
top: 0em;
|
||||
left: 0em;
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
overflow: hidden;
|
||||
z-index: 10; }
|
||||
.routes-maker > .map-menu {
|
||||
position: absolute;
|
||||
top: 5em;
|
||||
left: 1em;
|
||||
width: 20em;
|
||||
z-index: 20; }
|
||||
.routes-maker [data-show-markers=false] .leaflet-marker-pane, .routes-maker [data-show-markers=false] .leaflet-shadow-pane {
|
||||
display: none; }
|
||||
.routes-maker [data-show-routes=false] .leaflet-overlay-pane {
|
||||
display: none; }
|
||||
|
||||
/*# sourceMappingURL=RoutesMaker.css.map */
|
7
Public/scss/RoutesMaker.css.map
Normal file
7
Public/scss/RoutesMaker.css.map
Normal file
@ -0,0 +1,7 @@
|
||||
{
|
||||
"version": 3,
|
||||
"mappings": "AAAA,aAAa;EAET,QAAQ,EAAG,QAAQ;EACnB,oBAAM;IAAC,QAAQ,EAAG,QAAQ;EAC1B,mCAAQ;IACJ,GAAG,EAAG,GAAG;IACT,IAAI,EAAG,GAAG;IACV,KAAK,EAAG,IAAI;IACZ,MAAM,EAAG,IAAI;IACb,QAAQ,EAAG,MAAM;IACjB,OAAO,EAAG,EAAE;EAGhB,yBAAW;IACP,QAAQ,EAAG,QAAQ;IACnB,GAAG,EAAG,GAAG;IACT,IAAI,EAAG,GAAG;IACV,KAAK,EAAG,IAAI;IACZ,OAAO,EAAG,EAAE;EAGU,0HAAyC;IAAC,OAAO,EAAG,IAAI;EAClF,4DAA8C;IAAC,OAAO,EAAG,IAAI",
|
||||
"sources": ["RoutesMaker.scss"],
|
||||
"names": [],
|
||||
"file": "RoutesMaker.css"
|
||||
}
|
25
Public/scss/RoutesMaker.scss
Normal file
25
Public/scss/RoutesMaker.scss
Normal file
@ -0,0 +1,25 @@
|
||||
.routes-maker{
|
||||
|
||||
position : relative;
|
||||
&>.map{position : absolute;}
|
||||
&,&>.map{
|
||||
top : 0em;
|
||||
left : 0em;
|
||||
width : 100%;
|
||||
height : 100%;
|
||||
overflow : hidden;
|
||||
z-index : 10;
|
||||
}
|
||||
|
||||
&>.map-menu{
|
||||
position : absolute;
|
||||
top : 5em;
|
||||
left : 1em;
|
||||
width : 20em;
|
||||
z-index : 20;
|
||||
}
|
||||
|
||||
[data-show-markers=false]{.leaflet-marker-pane,.leaflet-shadow-pane{display : none;}}
|
||||
[data-show-routes=false] .leaflet-overlay-pane{display : none;}
|
||||
|
||||
}
|
3
Tools/sass.sh
Executable file
3
Tools/sass.sh
Executable file
@ -0,0 +1,3 @@
|
||||
#!/bin/bash
|
||||
directory=`dirname $(readlink -f "$0")`
|
||||
sass $directory/../Public/scss/RoutesMaker.scss ../Public/scss/RoutesMaker.css;
|
Loading…
Reference in New Issue
Block a user