StructureJS
0.15.2A class based utility library for building modular and scalable web platform applications. Features opt-in classes and utilities which provide a solid foundation and toolset to build your next project.
/** * The **Route** class is a model that keeps track of a specific route for the {{#crossLink "Router"}}{{/crossLink}} class. * * @class Route * @module StructureJS * @submodule model * @param routePattern {string} The string pattern you want to have match, which can be any of the following combinations {}, ::, *, '' * @param callback {Function} The function that should be executed when a request matches the routePattern. * @param callbackScope {any} The scope of the callback function that should be executed. * @constructor * @author Robert S. (www.codeBelt.com) * @example * // Example of adding a route listener and the function callback below. * let route = new Route('/games/{gameName}/:level:/', this._method, this); * * // The above route would match the string below: * route.match('/games/asteroids/2/'); * * Route Pattern Options: * ---------------------- * **:optional:** The two colons **::** means a part of the hash url is optional for the match. The text between can be anything you want it to be. * * let route = new Route('/contact/:name:/', this._method, this); * * // Will match one of the following: * route.match('/contact/'); * route.match('/contact/heather/'); * route.match('/contact/john/'); * * * **{required}** The two curly brackets **{}** means a part of the hash url is required for the match. The text between can be anything you want it to be. * * let route = new Route('/product/{productName}/', this._method, this); * * // Will match one of the following: * route.match('/product/shoes/'); * route.match('/product/jackets/'); * * * **\*** The asterisk character means it will match all or part of part the hash url. * * let route = new Route('*', this._method, this); * * // Will match one of the following: * route.match('/anything/'); * route.match('/matches/any/hash/url/'); * route.match('/really/it/matches/any/and/all/hash/urls/'); * * * **''** The empty string means it will match when there are no hash url. * * let route = new Route('', this._method, this); * let route = new Route('/', this._method, this); * * // Will match one of the following: * route.match(''); * route.match('/'); * * * Other possible combinations but not limited too: * * let route = new Route('/games/{gameName}/:level:/', this._method1, this); * let route = new Route('/{category}/blog/', this._method2, this); * let route = new Route('/about/*', this._method3, this); * */ class Route { /** * The string pattern you want to have match, which can be any of the following combinations {}, ::, *, ?, "". See below for examples. * * @property routePattern * @type String * @public */ public routePattern = ''; /** * The regex representation for the routePattern that was passed into the constructor. * * @property regex * @type RegExp * @public * @readOnly */ public regex:RegExp = null; /** * The function that should be executed when a request matches the routePattern. The {{#crossLink "Router"}}{{/crossLink}} class will be using this property. * * @property callback * @type {Function} * @public */ public callback:Function = null; /** * The scope of the callback function that should be executed. The {{#crossLink "Router"}}{{/crossLink}} class will be using this property. * * @property callbackScope * @type {any} * @public */ public callbackScope:any = null; constructor(routePattern:string, callback:Function, scope:any) { this.routePattern = routePattern; this.regex = this._routePatternToRegexp(routePattern); this.callback = callback; this.callbackScope = scope; } /** * Converts the routePattern that was passed into the constructor to a regexp object. * * @method _routePatternToRegexp * @param {String} routePattern * @returns {RegExp} * @protected */ protected _routePatternToRegexp(routePattern):RegExp { const findFirstOrLastForwardSlash:RegExp = new RegExp('^\/|\/$', 'g'); // Finds if the first character OR if the last character is a forward slash const findOptionalColons:RegExp = new RegExp(':([^:]*):', 'g'); // Finds the colons : : const findRequiredBrackets:RegExp = new RegExp('{([^}]+)}', 'g'); // Finds the brackets { } const optionalFirstCharSlash = '^/?';// Allows the first character to be if a forward slash to be optional. const optionalLastCharSlash = '/?$';// Allows the last character to be if a forward slash to be optional. // Remove first and last forward slash. routePattern = routePattern.replace(findFirstOrLastForwardSlash, ''); // Convert the wild card * be a regex ?(.*) to select all. routePattern = routePattern.replace('*', '?(.*)'); // Make any :alphanumeric: optional routePattern = routePattern.replace(findOptionalColons, '?([^/]*)'); // Make any {alphanumeric} required routePattern = routePattern.replace(findRequiredBrackets, '([^/]+)'); return new RegExp(optionalFirstCharSlash + routePattern + optionalLastCharSlash, 'i'); } /** * Determine if a route matches a routePattern. * * @method match * @param route {String} The route or path to match against the routePattern that was passed into the constructor. * @returns {Array.<any>} * @example * let route = new Route('/games/{gameName}/:level:/', this.method, this); * console.log( route.match('/games/asteroids/2/') ); */ public match(route):Array<any> { // Remove the query string before matching against the route pattern. const routeWithoutQueryString:string = route.replace(/\?.*/, ''); return routeWithoutQueryString.match(this.regex); } } export default Route;