Skip to content

Instantly share code, notes, and snippets.

@zfedoran
Last active April 20, 2021 10:55
Show Gist options
  • Save zfedoran/ad6194b1dae66ff038e3ae9ab77c2241 to your computer and use it in GitHub Desktop.
Save zfedoran/ad6194b1dae66ff038e3ae9ab77c2241 to your computer and use it in GitHub Desktop.
Basic URL handler with query param support
// Example urls.js file for a Vue or React project
// -------------------------------------------------------------------------------------
// URLs.js
// -------------------------------------------------------------------------------------
/*
* Get the url query parameters from the current URL in the address bar
*/
function get_url_params() {
var url_params = {};
var match,
pl = /\+/g, // Regex for replacing addition symbol with a space
search = /([^&=]+)=?([^&]*)/g,
decode = function (s) { return decodeURIComponent(s.replace(pl, " ")); },
query = window.location.search.substring(1);
while (match = search.exec(query)) {
url_params[decode(match[1])] = decode(match[2]);
}
return url_params;
}
/*
* This function combines "old_params" and "new_params" objects and serializes
* them into a query string. Repeated/duplicate params are not supported.
*
* Example:
*
* Given the existing query params, give me a new query string sorting by date
* but remove the page and keep everything else.
*
* serialize_params({ page: 5, search_term: 'hello' }, { sort: 'by_date' }, ['page'], true);
* > "?search_term=hello&sort=by_date"
*/
function serialize_params(old_params={}, new_params={}, remove_params=[], keep_params=false) {
if (keep_params) {
const param_obj = { ...old_params, ...new_params };
const param_str = '?' + Object.keys(param_obj)
.filter((key)=>!remove_params.includes(key)) // exclude any params that are in "remove_params"
.map((key) => `${key}=${param_obj[key]}`).join('&');
return param_str.length > 1 ? param_str : '';
}
return '';
}
/*
* This function wraps serialize_params(); allows for a single option parameter instead.
*
* Example:
*
* handle_params({
* old_params: { page: 5, search_term: 'hello' },
* new_params: { sort: 'by_date' },
* remove_params: ['page'],
* keep_params: true
*);
*
* > "?search_term=hello&sort=by_date"
*
*/
function handle_params({ old_params, new_params, remove_params, keep_params }) {
return serialize_params(old_params, new_params, remove_params, keep_params)
}
//module.exports = url_module;
const url_module = {
// Export the get_url_params function
get_url_params,
// Export a helper function to set the current url
goto(url) { window.location = url },
// Initialize base properties
init(options = { web_base: '', api_base: '', /* anything else you need */ }) {
const web_base = options.web_base;
const api_base = options.api_base;
const old_params = get_url_params();
const urls = {
// List your URL configuration here or pass it in through a variable. Keeping it simple here... Some examples below.
// PROJECTS
'core:project_list': ({}) => `${web_base}/project/`,
'core:project_details': ({project}) => `${web_base}/project/${project}`,
// CAMPAIGNS
'core:campaign_list': ({}) => `${web_base}/project/campaign/`,
'core:campaign_details': ({campaign}) => `${web_base}/project/campaign/${campaign}`,
// API
'api:datasource_list': ({}) => `${api_base}/api/data/datasource`,
'api:datasource_detail': ({datasource}) => `${api_base}/api/data/datasource/${datasource}`,
'api:datasource_create': ({datasource}) => `${api_base}/api/data/datasource/new/${datasource}`,
}
return function reverse(name, args) {
if (typeof name == 'object' && name.length == 2) {
args = name[1];
name = name[0];
}
try {
return urls[name](args) + handle_params({...args, old_params});
} catch (err) {
throw `Missing a URL on the front-end: "${name}"\n\n\t${err}`
}
}
}
}
// -------------------------------------------------------------------------------------
// Example Usage
// -------------------------------------------------------------------------------------
// Lets assume the current URL includes "http://...?page=5&search_term=foobar"
url_module.get_url_params()
// {page: "5", search_term: "foobar"}
// Lets initialize the module with our base URL(s)
const reverse = url_module.init({ web_base: 'localhost:8000/web/dashboard', api_base: 'localhost:3000' })
// Basic Examples:
// -------------------------------------------------------------------------------------
reverse('api:datasource_list', {})
// "localhost:3000/api/data/datasource"
reverse('core:project_list', {})
// "localhost:8000/web/dashboard/project/"
reverse('core:project_details', { project:'b6f54cec-9d58-11eb-bcb3-0242ac110002' })
// "localhost:8000/web/dashboard/project/b6f54cec-9d58-11eb-bcb3-0242ac110002"
reverse('core:project_list', { keep_params: true })
// "localhost:8000/web/dashboard/project/?page=5&search_term=foobar"
reverse('core:project_list', { keep_params: true, new_params: { sort: 'by_date' }})
// "localhost:8000/web/dashboard/project/?page=5&search_term=foobar&sort=by_date"
reverse('core:project_list', { keep_params: true, new_params: { sort: 'by_date' }, remove_params: ['page']})
// "localhost:8000/web/dashboard/project/?search_term=foobar&sort=by_date"
// Advanced Examples
// -------------------------------------------------------------------------------------
const SEARCH_ACTION = ({ term }) => [
'core:campaign_list', {
keep_params: true,
remove_params: [ 'page' ],
new_params: { search_term: term }
}
]
reverse(SEARCH_ACTION({ term: 'hello world' }))
// "localhost:8000/web/dashboard/project/campaign/?search_term=hello world"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment