Created
January 4, 2019 14:43
-
-
Save heleneshaikh/a0d629dd944d30af120b69b96b3a8822 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
(function (root, factory) { | |
var routing = factory(); | |
if (typeof define === 'function' && define.amd) { | |
// AMD. Register as an anonymous module. | |
define([], routing.Routing); | |
} else if (typeof module === 'object' && module.exports) { | |
// Node. Does not work with strict CommonJS, but | |
// only CommonJS-like environments that support module.exports, | |
// like Node. | |
module.exports = routing.Routing; | |
} else { | |
// Browser globals (root is window) | |
root.Routing = routing.Routing; | |
root.fos = { | |
Router: routing.Router | |
}; | |
} | |
}(this, function () { | |
'use strict'; | |
/** | |
* @fileoverview This file defines the Router class. | |
* | |
* You can compile this file by running the following command from the Resources folder: | |
* | |
* npm install && npm run build | |
*/ | |
/** | |
* Class Router | |
*/ | |
var _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; | |
var _typeof = typeof Symbol === "function" && typeof Symbol.iterator === "symbol" ? function (obj) { return typeof obj; } : function (obj) { return obj && typeof Symbol === "function" && obj.constructor === Symbol && obj !== Symbol.prototype ? "symbol" : typeof obj; }; | |
var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); | |
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } | |
var Router = function () { | |
/** | |
* @constructor | |
* @param {Router.Context=} context | |
* @param {Object.<string, Router.Route>=} routes | |
*/ | |
function Router(context, routes) { | |
_classCallCheck(this, Router); | |
this.context_ = context || { base_url: '', prefix: '', host: '', port: '', scheme: '' }; | |
this.setRoutes(routes || {}); | |
} | |
/** | |
* Returns the current instance. | |
* @returns {Router} | |
*/ | |
_createClass(Router, [{ | |
key: 'setRoutingData', | |
/** | |
* Sets data for the current instance | |
* @param {Object} data | |
*/ | |
value: function setRoutingData(data) { | |
this.setBaseUrl(data['base_url']); | |
this.setRoutes(data['routes']); | |
if ('prefix' in data) { | |
this.setPrefix(data['prefix']); | |
} | |
if ('port' in data) { | |
this.setPort(data['port']); | |
} | |
this.setHost(data['host']); | |
this.setScheme(data['scheme']); | |
} | |
/** | |
* @param {Object.<string, Router.Route>} routes | |
*/ | |
}, { | |
key: 'setRoutes', | |
value: function setRoutes(routes) { | |
this.routes_ = Object.freeze(routes); | |
} | |
/** | |
* @return {Object.<string, Router.Route>} routes | |
*/ | |
}, { | |
key: 'getRoutes', | |
value: function getRoutes() { | |
return this.routes_; | |
} | |
/** | |
* @param {string} baseUrl | |
*/ | |
}, { | |
key: 'setBaseUrl', | |
value: function setBaseUrl(baseUrl) { | |
this.context_.base_url = baseUrl; | |
} | |
/** | |
* @return {string} | |
*/ | |
}, { | |
key: 'getBaseUrl', | |
value: function getBaseUrl() { | |
return this.context_.base_url; | |
} | |
/** | |
* @param {string} prefix | |
*/ | |
}, { | |
key: 'setPrefix', | |
value: function setPrefix(prefix) { | |
this.context_.prefix = prefix; | |
} | |
/** | |
* @param {string} scheme | |
*/ | |
}, { | |
key: 'setScheme', | |
value: function setScheme(scheme) { | |
this.context_.scheme = scheme; | |
} | |
/** | |
* @return {string} | |
*/ | |
}, { | |
key: 'getScheme', | |
value: function getScheme() { | |
return this.context_.scheme; | |
} | |
/** | |
* @param {string} host | |
*/ | |
}, { | |
key: 'setHost', | |
value: function setHost(host) { | |
this.context_.host = host; | |
} | |
/** | |
* @return {string} | |
*/ | |
}, { | |
key: 'getHost', | |
value: function getHost() { | |
return this.context_.host; | |
} | |
/** | |
* @param {string} port | |
*/ | |
}, { | |
key: 'setPort', | |
value: function setPort(port) { | |
this.context_.port = port; | |
} | |
/** | |
* @return {string} | |
*/ | |
}, { | |
key: 'getPort', | |
value: function getPort() { | |
return this.context_.port; | |
} | |
}, { | |
key: 'buildQueryParams', | |
/** | |
* Builds query string params added to a URL. | |
* Port of jQuery's $.param() function, so credit is due there. | |
* | |
* @param {string} prefix | |
* @param {Array|Object|string} params | |
* @param {Function} add | |
*/ | |
value: function buildQueryParams(prefix, params, add) { | |
var _this = this; | |
var name = void 0; | |
var rbracket = new RegExp(/\[\]$/); | |
if (params instanceof Array) { | |
params.forEach(function (val, i) { | |
if (rbracket.test(prefix)) { | |
add(prefix, val); | |
} else { | |
_this.buildQueryParams(prefix + '[' + ((typeof val === 'undefined' ? 'undefined' : _typeof(val)) === 'object' ? i : '') + ']', val, add); | |
} | |
}); | |
} else if ((typeof params === 'undefined' ? 'undefined' : _typeof(params)) === 'object') { | |
for (name in params) { | |
this.buildQueryParams(prefix + '[' + name + ']', params[name], add); | |
} | |
} else { | |
add(prefix, params); | |
} | |
} | |
/** | |
* Returns a raw route object. | |
* | |
* @param {string} name | |
* @return {Router.Route} | |
*/ | |
}, { | |
key: 'getRoute', | |
value: function getRoute(name) { | |
var prefixedName = this.context_.prefix + name; | |
if (!(prefixedName in this.routes_)) { | |
// Check first for default route before failing | |
if (!(name in this.routes_)) { | |
throw new Error('The route "' + name + '" does not exist.'); | |
} | |
} else { | |
name = prefixedName; | |
} | |
return this.routes_[name]; | |
} | |
/** | |
* Generates the URL for a route. | |
* | |
* @param {string} name | |
* @param {Object.<string, string>} opt_params | |
* @param {boolean} absolute | |
* @return {string} | |
*/ | |
}, { | |
key: 'generate', | |
value: function generate(name, opt_params) { | |
var absolute = arguments.length > 2 && arguments[2] !== undefined ? arguments[2] : false; | |
var route = this.getRoute(name), | |
params = opt_params || {}, | |
unusedParams = _extends({}, params), | |
url = '', | |
optional = true, | |
host = '', | |
port = typeof this.getPort() == "undefined" || this.getPort() === null ? '' : this.getPort(); | |
route.tokens.forEach(function (token) { | |
if ('text' === token[0]) { | |
url = token[1] + url; | |
optional = false; | |
return; | |
} | |
if ('variable' === token[0]) { | |
var hasDefault = route.defaults && token[3] in route.defaults; | |
if (false === optional || !hasDefault || token[3] in params && params[token[3]] != route.defaults[token[3]]) { | |
var value = void 0; | |
if (token[3] in params) { | |
value = params[token[3]]; | |
delete unusedParams[token[3]]; | |
} else if (hasDefault) { | |
value = route.defaults[token[3]]; | |
} else if (optional) { | |
return; | |
} else { | |
throw new Error('The route "' + name + '" requires the parameter "' + token[3] + '".'); | |
} | |
var empty = true === value || false === value || '' === value; | |
if (!empty || !optional) { | |
var encodedValue = encodeURIComponent(value).replace(/%2F/g, '/'); | |
if ('null' === encodedValue && null === value) { | |
encodedValue = ''; | |
} | |
url = token[1] + encodedValue + url; | |
} | |
optional = false; | |
} else if (hasDefault && token[3] in unusedParams) { | |
delete unusedParams[token[3]]; | |
} | |
return; | |
} | |
throw new Error('The token type "' + token[0] + '" is not supported.'); | |
}); | |
if (url === '') { | |
url = '/'; | |
} | |
route.hosttokens.forEach(function (token) { | |
var value = void 0; | |
if ('text' === token[0]) { | |
host = token[1] + host; | |
return; | |
} | |
if ('variable' === token[0]) { | |
if (token[3] in params) { | |
value = params[token[3]]; | |
delete unusedParams[token[3]]; | |
} else if (route.defaults && token[3] in route.defaults) { | |
value = route.defaults[token[3]]; | |
} | |
host = token[1] + value + host; | |
} | |
}); | |
// Foo-bar! | |
url = this.context_.base_url + url; | |
if (route.requirements && "_scheme" in route.requirements && this.getScheme() != route.requirements["_scheme"]) { | |
url = route.requirements["_scheme"] + "://" + (host || this.getHost()) + url; | |
} else if ("undefined" !== typeof route.schemes && "undefined" !== typeof route.schemes[0] && this.getScheme() !== route.schemes[0]) { | |
url = route.schemes[0] + "://" + (host || this.getHost()) + url; | |
} else if (host && this.getHost() !== host + ('' === port ? '' : ':' + port)) { | |
url = this.getScheme() + "://" + host + ('' === port ? '' : ':' + port) + url; | |
} else if (absolute === true) { | |
url = this.getScheme() + "://" + this.getHost() + url; | |
} | |
if (Object.keys(unusedParams).length > 0) { | |
var prefix = void 0; | |
var queryParams = []; | |
var add = function add(key, value) { | |
// if value is a function then call it and assign it's return value as value | |
value = typeof value === 'function' ? value() : value; | |
// change null to empty string | |
value = value === null ? '' : value; | |
queryParams.push(encodeURIComponent(key) + '=' + encodeURIComponent(value)); | |
}; | |
for (prefix in unusedParams) { | |
this.buildQueryParams(prefix, unusedParams[prefix], add); | |
} | |
url = url + '?' + queryParams.join('&').replace(/%20/g, '+'); | |
} | |
return url; | |
} | |
}], [{ | |
key: 'getInstance', | |
value: function getInstance() { | |
return Routing; | |
} | |
/** | |
* Configures the current Router instance with the provided data. | |
* @param {Object} data | |
*/ | |
}, { | |
key: 'setData', | |
value: function setData(data) { | |
var router = Router.getInstance(); | |
router.setRoutingData(data); | |
} | |
}]); | |
return Router; | |
}(); | |
/** | |
* @typedef {{ | |
* tokens: (Array.<Array.<string>>), | |
* defaults: (Object.<string, string>), | |
* requirements: Object, | |
* hosttokens: (Array.<string>) | |
* }} | |
*/ | |
Router.Route; | |
/** | |
* @typedef {{ | |
* base_url: (string) | |
* }} | |
*/ | |
Router.Context; | |
/** | |
* Router singleton. | |
* @const | |
* @type {Router} | |
*/ | |
var Routing = new Router(); | |
return { Router: Router, Routing: Routing }; | |
})); |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment