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 = [];