mirror of
https://github.com/esiur/iui.git
synced 2025-12-17 03:50:24 +00:00
Add router base option and navigate to origin after on init
This commit is contained in:
@@ -1,338 +1,322 @@
|
||||
import IUIElement from "../Core/IUIElement.js";
|
||||
import Route from "./Route.js"
|
||||
import Route from "./Route.js";
|
||||
import Target from "./Target.js";
|
||||
import { IUI } from "../Core/IUI.js";
|
||||
|
||||
export default IUI.module(
|
||||
class Router extends Target {
|
||||
constructor() {
|
||||
super({
|
||||
routes: [],
|
||||
_states: new Map(),
|
||||
active: null,
|
||||
cssClass: "router",
|
||||
});
|
||||
|
||||
export default IUI.module(class Router extends Target
|
||||
{
|
||||
|
||||
constructor()
|
||||
{
|
||||
super({routes: [], _states: new Map(), active: null, cssClass: "router"});
|
||||
this._history = [];
|
||||
|
||||
this._history = [];
|
||||
|
||||
|
||||
//IUI._router = this;
|
||||
|
||||
//Object.defineProperty(window, "router", {
|
||||
// get() {
|
||||
// if (!IUI._router.isConnected)
|
||||
// IUI._router = document.getElementsByTagName("i-router")[0];
|
||||
// return IUI._router;
|
||||
// }
|
||||
//});
|
||||
//IUI._router = this;
|
||||
|
||||
//Object.defineProperty(window, "router", {
|
||||
// get() {
|
||||
// if (!IUI._router.isConnected)
|
||||
// IUI._router = document.getElementsByTagName("i-router")[0];
|
||||
// return IUI._router;
|
||||
// }
|
||||
//});
|
||||
}
|
||||
|
||||
_getRouteParent(route) {
|
||||
let e = null;
|
||||
let e = null;
|
||||
|
||||
while (e = route.parentElement) {
|
||||
if (e instanceof Route || e instanceof Router)
|
||||
return e;
|
||||
}
|
||||
while ((e = route.parentElement)) {
|
||||
if (e instanceof Route || e instanceof Router) return e;
|
||||
}
|
||||
|
||||
return null;
|
||||
return null;
|
||||
}
|
||||
|
||||
add(route, parent = null) {
|
||||
if (parent == null) {
|
||||
this.routes.push(route);
|
||||
}
|
||||
else {
|
||||
route.parent = parent;
|
||||
this.appendChild(route);
|
||||
//parent.routes.push(route);
|
||||
}
|
||||
if (parent == null) {
|
||||
this.routes.push(route);
|
||||
} else {
|
||||
route.parent = parent;
|
||||
this.appendChild(route);
|
||||
//parent.routes.push(route);
|
||||
}
|
||||
}
|
||||
|
||||
_routeInPath(name, routes)
|
||||
{
|
||||
for (var i = 0; i < routes.length; i++)
|
||||
if (routes[i].name == name)
|
||||
return routes[i];
|
||||
return null;
|
||||
_routeInPath(name, routes) {
|
||||
for (var i = 0; i < routes.length; i++)
|
||||
if (routes[i].name == name) return routes[i];
|
||||
return null;
|
||||
}
|
||||
|
||||
getRoute(url, data) {
|
||||
let p = url.split("/");
|
||||
/**
|
||||
* @type {String[]}
|
||||
*/
|
||||
let p = url.split("/");
|
||||
|
||||
let searchRoutes = this.routes;
|
||||
let searchRoutes = this.routes;
|
||||
|
||||
for (var i = 0; i < p.length; i++) {
|
||||
var route = this._routeInPath(p[i], searchRoutes);
|
||||
if (p[0] == this.base) {
|
||||
p.shift();
|
||||
}
|
||||
|
||||
if (route == null)
|
||||
return [null, null];
|
||||
for (var i = 0; i < p.length; i++) {
|
||||
var route = this._routeInPath(p[i], searchRoutes);
|
||||
|
||||
if (i == p.length - 1) {
|
||||
// return [destination state route (link, icon,..etc) , actual route to view]
|
||||
if (route.dst == null)
|
||||
return [route, route];
|
||||
else {
|
||||
if (route == null) return [null, null];
|
||||
|
||||
let dst = route.dst instanceof Function ? route.dst(data) : route.dst;
|
||||
let url = dst.replace(/^[/]*(.*?)[/]*$/g, '$1').trim();
|
||||
return [route, this.getRoute(url)[1]];
|
||||
}
|
||||
}
|
||||
|
||||
searchRoutes = route.routes;
|
||||
if (i == p.length - 1) {
|
||||
// return [destination state route (link, icon,..etc) , actual route to view]
|
||||
if (route.dst == null) return [route, route];
|
||||
else {
|
||||
let dst =
|
||||
route.dst instanceof Function ? route.dst(data) : route.dst;
|
||||
let url = dst.replace(/^[/]*(.*?)[/]*$/g, "$1").trim();
|
||||
return [route, this.getRoute(url)[1]];
|
||||
}
|
||||
}
|
||||
|
||||
searchRoutes = route.routes;
|
||||
}
|
||||
}
|
||||
|
||||
back() {
|
||||
//if (this._history.length > 1) {
|
||||
// let last = this._history[this._history.length - 2];
|
||||
// this.navigate(last.url, last.data, last.target);
|
||||
//}
|
||||
//if (this._history.length > 1) {
|
||||
// let last = this._history[this._history.length - 2];
|
||||
// this.navigate(last.url, last.data, last.target);
|
||||
//}
|
||||
|
||||
window.history.back();
|
||||
}
|
||||
window.history.back();
|
||||
}
|
||||
|
||||
_toQuery(o) {
|
||||
let rt = [];
|
||||
for (let i in o)
|
||||
if (o[i] == undefined)
|
||||
rt.push(i);
|
||||
else
|
||||
rt.push(i + "=" + encodeURI(o[i].toString().replace("&", "&&")));///encodeURIComponent(o[i]));
|
||||
return rt.join("&");
|
||||
let rt = [];
|
||||
for (let i in o)
|
||||
if (o[i] == undefined) rt.push(i);
|
||||
else rt.push(i + "=" + encodeURI(o[i].toString().replace("&", "&&"))); ///encodeURIComponent(o[i]));
|
||||
return rt.join("&");
|
||||
}
|
||||
|
||||
_fromQuery(q) {
|
||||
let kv = q.replace("&&", "\0").split('&');
|
||||
let rt = {};
|
||||
for (let i = 0; i < kv.length; i++) {
|
||||
let d = kv[i].replace("\0", "&").split('=', 2);
|
||||
let v = decodeURI(d[1] || ''); //decodeURIComponent(d[1] || '');
|
||||
if (v != null && v.trim() != '' && !isNaN(v))
|
||||
v = new Number(v);
|
||||
rt[d[0]] = v;
|
||||
}
|
||||
return JSON.parse(JSON.stringify(rt));
|
||||
let kv = q.replace("&&", "\0").split("&");
|
||||
let rt = {};
|
||||
for (let i = 0; i < kv.length; i++) {
|
||||
let d = kv[i].replace("\0", "&").split("=", 2);
|
||||
let v = decodeURI(d[1] || ""); //decodeURIComponent(d[1] || '');
|
||||
if (v != null && v.trim() != "" && !isNaN(v)) v = new Number(v);
|
||||
rt[d[0]] = v;
|
||||
}
|
||||
return JSON.parse(JSON.stringify(rt));
|
||||
}
|
||||
|
||||
async navigate(url, data, target, state, dataToQuery = true)
|
||||
{
|
||||
let q = url.match(/^\/*(.*?)\?(.*)$|^\/*(.*)$/);
|
||||
async navigate(url, data, target, state, dataToQuery = true) {
|
||||
let q = url.match(/^\/*(.*?)\?(.*)$|^\/*(.*)$/);
|
||||
|
||||
//debugger;
|
||||
//debugger;
|
||||
|
||||
var path;
|
||||
var path;
|
||||
|
||||
// do we have a query string ?
|
||||
if (q[2] !== undefined) {
|
||||
path = q[1];
|
||||
data = this._fromQuery(q[2]);
|
||||
url = path + "?" + q[2];
|
||||
}
|
||||
// do we have data ?
|
||||
else if (data !== undefined) {
|
||||
path = q[3];
|
||||
url = dataToQuery ? path + "?" + this._toQuery(data) : path;
|
||||
}
|
||||
else {
|
||||
path = q[3];
|
||||
url = path;
|
||||
}
|
||||
|
||||
// do we have a query string ?
|
||||
if (q[2] !== undefined) {
|
||||
path = q[1];
|
||||
data = this._fromQuery(q[2]);
|
||||
url = path + "?" + q[2];
|
||||
}
|
||||
// do we have data ?
|
||||
else if (data !== undefined) {
|
||||
path = q[3];
|
||||
url = dataToQuery ? path + "?" + this._toQuery(data) : path;
|
||||
} else {
|
||||
path = q[3];
|
||||
url = path;
|
||||
}
|
||||
|
||||
let [stateRoute, viewRoute] = this.getRoute(path, data);
|
||||
let [stateRoute, viewRoute] = this.getRoute(path, data);
|
||||
|
||||
if (stateRoute == null)
|
||||
{
|
||||
console.warn("State not found ", path);
|
||||
return;
|
||||
}
|
||||
if (stateRoute == null) {
|
||||
console.warn("State not found ", path);
|
||||
return;
|
||||
}
|
||||
|
||||
let ok = this._emit("navigate", { url, stateRoute, viewRoute, base: path, data, cancelable: true });
|
||||
let ok = this._emit("navigate", {
|
||||
url,
|
||||
stateRoute,
|
||||
viewRoute,
|
||||
base: path,
|
||||
data,
|
||||
cancelable: true,
|
||||
});
|
||||
|
||||
if (!ok)
|
||||
{
|
||||
console.warn("Route not allowed", path);
|
||||
return;
|
||||
}
|
||||
if (!ok) {
|
||||
console.warn("Route not allowed", path);
|
||||
return;
|
||||
}
|
||||
|
||||
// destination view not found
|
||||
if (viewRoute == null) {
|
||||
console.log(`Destination route not found ${stateRoute.dst}`);
|
||||
viewRoute = stateRoute;
|
||||
}
|
||||
|
||||
// destination view not found
|
||||
if (viewRoute == null) {
|
||||
console.log(`Destination route not found ${stateRoute.dst}`);
|
||||
viewRoute = stateRoute;
|
||||
}
|
||||
|
||||
//let state = null;
|
||||
//let state = null;
|
||||
|
||||
//if (data !== undefined) {
|
||||
// for (let [k, v] of this._states)
|
||||
// if (v == data) {
|
||||
// state = k;
|
||||
// break;
|
||||
// }
|
||||
//if (data !== undefined) {
|
||||
// for (let [k, v] of this._states)
|
||||
// if (v == data) {
|
||||
// state = k;
|
||||
// break;
|
||||
// }
|
||||
|
||||
// if (state == null) {
|
||||
// state = Math.random().toString(36).substr(2, 10);
|
||||
// this._states.set(state, data);
|
||||
// }
|
||||
//}
|
||||
// if (state == null) {
|
||||
// state = Math.random().toString(36).substr(2, 10);
|
||||
// this._states.set(state, data);
|
||||
// }
|
||||
//}
|
||||
|
||||
if (!(target instanceof Target))
|
||||
target = this;
|
||||
if (!(target instanceof Target)) target = this;
|
||||
|
||||
if (state == null) {
|
||||
let id = Math.random().toString(36).substr(2, 10);
|
||||
state = { id, url, data, target, stateRoute, viewRoute };
|
||||
this._states.set(id, state);
|
||||
history.pushState(id, stateRoute.caption, this._hash ? "#" + url : "/" + url);
|
||||
}
|
||||
if (state == null) {
|
||||
let id = Math.random().toString(36).substr(2, 10);
|
||||
state = { id, url, data, target, stateRoute, viewRoute };
|
||||
this._states.set(id, state);
|
||||
history.pushState(
|
||||
id,
|
||||
stateRoute.caption,
|
||||
this._hash ? "#" + url : "/" + url
|
||||
);
|
||||
}
|
||||
|
||||
this._history.push(state.id);// { url, data, target, stateRoute, viewRoute });
|
||||
this._history.push(state.id); // { url, data, target, stateRoute, viewRoute });
|
||||
|
||||
target.show(viewRoute, this.active);
|
||||
viewRoute.set(true);
|
||||
target.show(viewRoute, this.active);
|
||||
viewRoute.set(true);
|
||||
|
||||
this.active = viewRoute;
|
||||
|
||||
this.active = viewRoute;
|
||||
//{ url: "/", data: null, target: null };
|
||||
this._emit("route", { route: stateRoute });
|
||||
|
||||
viewRoute.query = data || {};
|
||||
stateRoute.query = viewRoute.query;
|
||||
|
||||
//{ url: "/", data: null, target: null };
|
||||
this._emit("route", { route: stateRoute });
|
||||
target.setLoading(true);
|
||||
|
||||
viewRoute.query = data || {};
|
||||
stateRoute.query = viewRoute.query;
|
||||
if (stateRoute.dataMap != null) {
|
||||
// if map function failed to call setData, we will render without it
|
||||
if (!(await stateRoute.dataMap.render(data || {})))
|
||||
await stateRoute.render();
|
||||
|
||||
if (viewRoute != stateRoute) await viewRoute.setData(stateRoute.data);
|
||||
} //if (data !== undefined)
|
||||
else await viewRoute.setData(data);
|
||||
|
||||
target.setLoading(true);
|
||||
|
||||
if (stateRoute.dataMap != null) {
|
||||
// if map function failed to call setData, we will render without it
|
||||
if (!(await stateRoute.dataMap.render(data || {})))
|
||||
await stateRoute.render();
|
||||
|
||||
if (viewRoute != stateRoute)
|
||||
await viewRoute.setData(stateRoute.data);
|
||||
}
|
||||
else //if (data !== undefined)
|
||||
await viewRoute.setData(data);
|
||||
|
||||
target.setLoading(false);
|
||||
|
||||
target.setLoading(false);
|
||||
}
|
||||
|
||||
hide() {
|
||||
// do nothing, we're not here to hide.
|
||||
// do nothing, we're not here to hide.
|
||||
}
|
||||
|
||||
refresh() {
|
||||
let state = this.current;
|
||||
this.navigate(state.url, state.data, state.target, state);
|
||||
|
||||
let state = this.current;
|
||||
this.navigate(state.url, state.data, state.target, state);
|
||||
|
||||
//this.current.render();
|
||||
//this.current.data = this.current.data;
|
||||
//if (updateAttributes)
|
||||
// this.current.updateAttributes(true);
|
||||
//this.current.render();
|
||||
//this.current.data = this.current.data;
|
||||
//if (updateAttributes)
|
||||
// this.current.updateAttributes(true);
|
||||
}
|
||||
|
||||
show(route, active) {
|
||||
super.show(route, active);
|
||||
|
||||
|
||||
super.show(route, active);
|
||||
}
|
||||
|
||||
get current() {
|
||||
return this._states.get(history.state);//.viewRoute;
|
||||
//return this._history[this._history.length - 1].viewRoute;
|
||||
return this._states.get(history.state); //.viewRoute;
|
||||
//return this._history[this._history.length - 1].viewRoute;
|
||||
}
|
||||
|
||||
get previous() {
|
||||
|
||||
if (this._history.length > 2)
|
||||
return this._states.get(this._history[this._history.length - 2]);//.viewRoute;
|
||||
else
|
||||
return null;
|
||||
if (this._history.length > 2)
|
||||
return this._states.get(this._history[this._history.length - 2]);
|
||||
//.viewRoute;
|
||||
else return null;
|
||||
}
|
||||
|
||||
create() {
|
||||
|
||||
// save origin
|
||||
this.origin = window.location.pathname + window.location.search;
|
||||
// save origin
|
||||
this.origin = window.location.pathname + window.location.search;
|
||||
this.base = this.getAttribute("base") || "";
|
||||
}
|
||||
|
||||
destroy() {
|
||||
console.log("Destroyed", this);
|
||||
console.log("Destroyed", this);
|
||||
}
|
||||
|
||||
created()
|
||||
{
|
||||
created() {
|
||||
if (
|
||||
this.hasAttribute("type") &&
|
||||
this.getAttribute("type").toLowerCase() == "hash"
|
||||
)
|
||||
this._hash = true;
|
||||
|
||||
if (this.hasAttribute("type") && this.getAttribute("type").toLowerCase() == "hash")
|
||||
this._hash = true;
|
||||
|
||||
|
||||
/// find all children
|
||||
for (var i = 0; i < this.children.length; i++) {
|
||||
let e = this.children[i];
|
||||
if (e instanceof Route) {
|
||||
this.add(e);
|
||||
if (e.visible)
|
||||
this.navigate(e.name);
|
||||
}
|
||||
/// find all children
|
||||
for (var i = 0; i < this.children.length; i++) {
|
||||
let e = this.children[i];
|
||||
if (e instanceof Route) {
|
||||
this.add(e);
|
||||
if (e.visible) this.navigate(e.name);
|
||||
}
|
||||
}
|
||||
|
||||
this._emit("created");
|
||||
|
||||
//console.log("Router created", this);
|
||||
this._emit("created");
|
||||
this.navigate(this.origin);
|
||||
//console.log("Router created", this);
|
||||
}
|
||||
|
||||
connectedCallback() {
|
||||
//console.log("New router", this);
|
||||
//console.log("New router", this);
|
||||
|
||||
window.router = this;
|
||||
window.router = this;
|
||||
|
||||
let self = this;
|
||||
let self = this;
|
||||
|
||||
window.addEventListener("popstate", function (event) {
|
||||
window.addEventListener("popstate", function (event) {
|
||||
//console.log(event);
|
||||
let stateId = event.state;
|
||||
let path;
|
||||
|
||||
//console.log(event);
|
||||
let stateId = event.state;
|
||||
let path;
|
||||
if (self._hash) {
|
||||
path = window.location.hash;
|
||||
|
||||
if (self._hash) {
|
||||
path = window.location.hash;
|
||||
if (path.length > 0) path = path.substr(1);
|
||||
} else {
|
||||
path = window.location.pathname;
|
||||
}
|
||||
|
||||
if (path.length > 0)
|
||||
path = path.substr(1);
|
||||
}
|
||||
else {
|
||||
path = window.location.pathname;
|
||||
}
|
||||
if (stateId != null) {
|
||||
if (stateId != self._history[self._history.length - 1]) {
|
||||
//this._lastStateId = stateId;
|
||||
let state = self._states.get(stateId);
|
||||
self.navigate(path, state.data, state.target, state);
|
||||
} else {
|
||||
console.log("SAME");
|
||||
}
|
||||
} else {
|
||||
this._lastState = null;
|
||||
self.navigate(path, undefined, undefined, {});
|
||||
}
|
||||
//alert("location: " + document.location + ", state: " + JSON.stringify(event.state));
|
||||
console.log(document.location.hash, event.state);
|
||||
});
|
||||
|
||||
if (stateId != null) {
|
||||
|
||||
if (stateId != self._history[self._history.length -1]) {
|
||||
//this._lastStateId = stateId;
|
||||
let state = self._states.get(stateId);
|
||||
self.navigate(path, state.data, state.target, state);
|
||||
}
|
||||
else {
|
||||
console.log("SAME");
|
||||
}
|
||||
}
|
||||
else {
|
||||
this._lastState = null;
|
||||
self.navigate(path, undefined, undefined, {});
|
||||
}
|
||||
//alert("location: " + document.location + ", state: " + JSON.stringify(event.state));
|
||||
console.log(document.location.hash, event.state);
|
||||
});
|
||||
|
||||
this._register("navigate");
|
||||
this._register("route");
|
||||
this._register("created");
|
||||
this._register("navigate");
|
||||
this._register("route");
|
||||
this._register("created");
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
);
|
||||
|
||||
Reference in New Issue
Block a user