269 lines
7.0 KiB
JavaScript
269 lines
7.0 KiB
JavaScript
"use strict";
|
|
|
|
import {Common} from "../Utils/Common.ecma.js";
|
|
import {RouteModel} from "../Models/RouteModel.ecma.js";
|
|
import {Check} from "../Utils/Checks.ecma.js";
|
|
import {RE} from "../Utils/Patterns.ecma.js";
|
|
|
|
/**
|
|
* @typedef {import("../AnP.ecma.js").AnP} AnP
|
|
*/
|
|
|
|
/**
|
|
* @class RoutesManager
|
|
* @constructor
|
|
* @param {!AnP} anp
|
|
* @return {void}
|
|
* @access public
|
|
* @static
|
|
*/
|
|
export const RoutesManager = (function(){
|
|
|
|
/**
|
|
* @callback continue_callback
|
|
* @param {!boolean} ok
|
|
* @return {boolean}
|
|
*/
|
|
|
|
/**
|
|
* @callback default_callback
|
|
* @return {void}
|
|
*/
|
|
|
|
/**
|
|
* @constructs RoutesManager
|
|
* @param {!AnP} anp
|
|
* @return {void}
|
|
* @access private
|
|
* @static
|
|
*/
|
|
const RoutesManager = function(anp){
|
|
|
|
/** @type {RoutesManager} */
|
|
const self = this,
|
|
/** @type {Array.<RouteModel>} */
|
|
routes = [];
|
|
/** @type {boolean} */
|
|
let started = false,
|
|
/** @type {string} */
|
|
last_url = "",
|
|
/** @type {number|null} */
|
|
thread = null;
|
|
|
|
/**
|
|
* @returns {void}
|
|
* @access private
|
|
*/
|
|
const constructor = () => {
|
|
|
|
thread = anp.threads.add(thread_method, {
|
|
bucle : true,
|
|
autoplay : true
|
|
});
|
|
|
|
};
|
|
|
|
/**
|
|
* @returns {void}
|
|
* @access private
|
|
*/
|
|
const thread_method = () => {
|
|
|
|
/** @type {string} */
|
|
const current_url = window.location.hash.substring(1);
|
|
|
|
if(last_url != current_url){
|
|
last_url = current_url;
|
|
self.refresh();
|
|
};
|
|
|
|
};
|
|
|
|
/**
|
|
* @returns {void}
|
|
* @access public
|
|
*/
|
|
this.refresh = () => {
|
|
self.go(last_url);
|
|
};
|
|
|
|
/**
|
|
* @param {?continue_callback} callback
|
|
* @returns {boolean}
|
|
* @access public
|
|
*/
|
|
this.update = (callback = null) => {
|
|
Common.execute_array(["default_routes_files", "routes_files", "default_routes", "routes"], (key, next) => {
|
|
self.add(anp.settings.get(key), true, next);
|
|
}, callback, true);
|
|
};
|
|
|
|
/**
|
|
* @param {?continue_callback} callback
|
|
* @returns {boolean}
|
|
* @access public
|
|
*/
|
|
this.reset = (callback = null) => {
|
|
|
|
routes.splice(0, routes.length);
|
|
|
|
self.update(callback);
|
|
|
|
};
|
|
|
|
/**
|
|
* @param {?continue_callback} callback
|
|
* @returns {boolean}
|
|
* @access public
|
|
*/
|
|
this.start = (callback = null) => {
|
|
|
|
/** @type {continue_callback} */
|
|
const end = ok => Common.execute(callback, ok);
|
|
|
|
if(started){
|
|
end(false);
|
|
return false;
|
|
};
|
|
started = true;
|
|
|
|
self.update(() => end(true));
|
|
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* @param {?continue_callback} callback
|
|
* @returns {boolean}
|
|
* @access public
|
|
*/
|
|
this.close = (callback = null) => {
|
|
|
|
/** @type {continue_callback} */
|
|
const end = ok => Common.execute(callback, ok);
|
|
|
|
if(!started){
|
|
end(false);
|
|
return false;
|
|
};
|
|
started = false;
|
|
|
|
end(true);
|
|
|
|
return true;
|
|
};
|
|
|
|
/**
|
|
* @param {!(string|RegExp)} route_path
|
|
* @param {!string} view
|
|
* @param {!boolean} overwrite
|
|
* @returns {boolean}
|
|
* @access private
|
|
*/
|
|
const set_new = (route_path, view, permissions, overwrite) => {
|
|
|
|
/** @type {RouteModel} */
|
|
const route = new RouteModel(route_path, view, permissions);
|
|
let i = null;
|
|
|
|
if(!routes.some((exists, j) => {
|
|
if(exists.route.source == route.route.source){
|
|
i = j;
|
|
return true;
|
|
};
|
|
return false;
|
|
})){
|
|
if(i === null)
|
|
routes.push(route);
|
|
else if(overwrite)
|
|
routes[i] = route;
|
|
return true;
|
|
};
|
|
return false;
|
|
};
|
|
|
|
/**
|
|
* @param {?any} inputs
|
|
* @param {!boolean} [overwrite = false]
|
|
* @param {?default_callback} [callback = null]
|
|
* @returns {void}
|
|
* @access public
|
|
*/
|
|
this.add = (inputs, overwrite = false, callback = null) => {
|
|
if(Check.is_string(inputs)){
|
|
|
|
/** @type {RegExpMatchArray} */
|
|
const matches = (inputs = inputs.trim()).match(RE.ROUTES);
|
|
|
|
if(matches){
|
|
set_new(matches[1], matches[2], matches[3] ? matches[3].split(",") : [], overwrite);
|
|
Common.execute(callback);
|
|
}else if(Check.is_json(inputs))
|
|
self.add(JSON.parse(inputs), overwrite, callback);
|
|
else
|
|
anp.files.load_json(inputs, data => {
|
|
self.add(data, overwrite, callback);
|
|
});
|
|
|
|
}else if(Check.is_array(inputs)){
|
|
if(inputs.length >= 2 && inputs.length <= 3 && (
|
|
Check.is_string(inputs[0]) && inputs[0] == inputs[0].trim() &&
|
|
Check.is_key(inputs[1]) &&
|
|
!inputs[2] || (Check.is_array(inputs[2]) && inputs[2].every(Check.is_key))
|
|
)){
|
|
set_new(inputs[0], inputs[1], inputs[3], overwrite);
|
|
Common.execute(callback);
|
|
return;
|
|
};
|
|
|
|
/** @type {number} */
|
|
let i = 0;
|
|
/** @type {number} */
|
|
const l = inputs.length,
|
|
/** @type {default_callback} */
|
|
end = () => ++ i == l && Common.execute(callback);
|
|
|
|
inputs.forEach(subinputs => {
|
|
self.add(subinputs, overwrite, end);
|
|
});
|
|
|
|
}else if(Check.is_dictionary(inputs)){
|
|
set_new(inputs.route, inputs.view, inputs.permissions || [], overwrite);
|
|
Common.execute(callback);
|
|
}else
|
|
Common.execute(callback);
|
|
};
|
|
|
|
/**
|
|
* @param {!string} path
|
|
* @returns {void}
|
|
* @access public
|
|
*/
|
|
this.go = path => {
|
|
|
|
const main = anp.item_self.querySelector("main");
|
|
|
|
if(!main)
|
|
return;
|
|
|
|
main.innerHTML = "";
|
|
|
|
for(const route of routes){
|
|
|
|
/** @type {[boolean, Object.<string, string>]} */
|
|
const [ok, variables] = route.check(path);
|
|
|
|
if(ok){
|
|
Common.HTML("main", anp.views.get(route.view, variables))
|
|
break;
|
|
};
|
|
|
|
};
|
|
|
|
};
|
|
|
|
constructor();
|
|
};
|
|
|
|
return RoutesManager;
|
|
})(); |