From b6d288f422846ea81a5702eab6eccdd217382284 Mon Sep 17 00:00:00 2001 From: Matt Mo Date: Wed, 11 Aug 2021 10:45:06 -0700 Subject: [PATCH] Added more docs. Router now has a data option that is passed with the event. Added route extension to help other templates react to route events. --- ignite-html-router.js | 67 +++++++++++++++++++++++++++++++++++++++---- 1 file changed, 62 insertions(+), 5 deletions(-) diff --git a/ignite-html-router.js b/ignite-html-router.js index fed362f..afe7c5f 100644 --- a/ignite-html-router.js +++ b/ignite-html-router.js @@ -1,5 +1,53 @@ import { IgniteElement } from "../ignite-html/ignite-element.js"; import { IgniteTemplate, slot, div, html } from "../ignite-html/ignite-template.js"; +import { IgniteCallback} from "../ignite-html/ignite-html.js"; + +/** + * Creates a route listener that runs when a route is switched. + * @param {String,String[]} routes A single or multiple set of routes that will invoke the callback if met. + * @param {Function} callback A callback function to invoke if the route is met, it will be passed the pushstate event. + * @param {Boolean} strict If true all routes must match before running the callback. + * @returns {IgniteTemplate} This ignite template. + */ +IgniteTemplate.prototype.route = function(routes, callback, strict = false) { + //If routes is not an array, wrap it. + if (!Array.isArray(routes)) { + routes = [routes]; + } + + //Create a managed callback + var managed = new IgniteCallback(event => { + var routeMatches = false; + + //Based on whether we are strict matching or not check if we have a match. + if (!strict) { + for (var i = 0; i < routes.length && !routeMatches; i++) { + routeMatches = Router.matches(routes[i]); + } + } else { + routeMatches = true; + for (var i = 0; i < routes.length && routeMatches; i++) { + routeMatches = Router.matches(routes[i]); + } + } + + //Invoke the callback if the route matched. + if (routeMatches) { + callback(event); + } + + }, () => { + window.removeEventListener("pushstate", managed.callback); + }); + + //Register our callback to the route event. + window.addEventListener("pushstate", managed.callback); + + //Add the managed callback to our template so that upon deconstruction our callback is destroyed correctly. + this._callbacks.push(managed); + + return this; +}; class RouterLink extends IgniteElement { constructor() { @@ -62,7 +110,7 @@ class RouterLink extends IgniteElement { onClick(event) { event.preventDefault(); - Router.navigate(this.target, false); + Router.navigate(this.target, null, false); } cleanup() { @@ -175,9 +223,10 @@ class Router { /** * Navigates to a given route and refreshes the page if requested. * @param {String} route The route to navigate to. + * @param {Any} data The data to pass along with this navigate, this only applies when not refreshing, default is null. * @param {Boolean} refresh Whether or not to refresh the page, default is false. */ - static navigate(route, refresh = false) { + static navigate(route, data = null, refresh = false) { if (refresh) { if (Router.hashMode) { window.location.hash = route; @@ -194,7 +243,10 @@ class Router { Router.states.push(route); } - window.dispatchEvent(new Event("pushstate")); + //Create a new pushstate event and fire it. + var event = new Event("pushstate"); + event.data = data; + window.dispatchEvent(event); } } @@ -206,16 +258,21 @@ class Router { static back(fallback = null, refresh = false) { if (Router.states && Router.states.length > 1) { Router.states.pop(); //Pop the current state. - Router.navigate(Router.states.pop(), refresh); //Navigate to the previous state. + Router.navigate(Router.states.pop(), null, refresh); //Navigate to the previous state. } else { if (fallback) { - Router.navigate(fallback, refresh); + Router.navigate(fallback, null, refresh); } else { window.history.back(); } } } + /** + * Returns whether or not the current location matches a given route. + * @param {String} route The route to check. + * @returns {Boolean} Returns whether or not the current browser location matches the route. + */ static matches(route) { //Get the path parts from the window var pathParts = [];